頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


Metalで描画したものを後で動画として表示する


↑衝突後に衝突の様子を動画として中央に表示させてるんだけど、ここではどうやってるかのお話。
こういうのをGIF動画にしてツイートってよくあるけど、ここではそういうのは無しでとりあえず動画を表示するってことで。

上の動画で言うと左目用、右目用とさらに別視点での録画用のrenderPassを用意してやって録画用はテクスチャに保存するように設定。

そのテクスチャを id<MTLTexture> *texture に対して

- (void)getBytes:(void *)pixelBytes bytesPerRow:(NSUInteger)bytesPerRow fromRegion:(MTLRegion)region mipmapLevel:(NSUInteger)mipmapLevel


ってメソッドでデータの保存ができる。

保存先はあらかじめ必要な枚数分メモリを確保しておく。
ちなみに上の動画はデータのサイズが横172x縦129、20FPSで表示してるんだけど、まあこれくらいならいいかなって感じ。

{
    MTLRegion region = MTLRegionMake2D(0, 0, ImageWidth, ImageHeight);//172x129
    
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * ImageWidth;

    UInt8 *recordingBuffer = (UInt8 *)&imageBuffer[unitSize * imageIndex];

    [texture getBytes:recordingBuffer bytesPerRow:bytesPerRow fromRegion:region mipmapLevel:0];
}
ここでunitSizeは画像1枚あたりのバイト数で、imageIndexにより保存先をどんどん変えていくようになってる。もちろん無限に保存するわけにもいかないのでimageIndexが決められた最大数を超えるとゼロになって最初に戻り、古いのに上書きしていく。
MTLTextureの内容を取得する型はUInt8でOK。

以上の処理が毎フレームで行われて、いざ表示となるとその時点で全ての保存してるデータを再度 id<MTLTexture> のテクスチャに戻してる。保存データをUIImageにするコードはこんな感じ。この後UIImageオブジェクトからMTLTextureにしてる。

+(UIImage *)makeImageFromUInt8Data:(UInt8 *)buffer size:(CGSize)size
{
    size_t width = size.width;
    size_t height = size.height;
    size_t bitsPerComponent = 8;
    size_t bitsPerPixel = 32;
    size_t bytesPerRow = 4*width;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaFirst;
    bool shouldInterpolate = 1;
    CGColorRenderingIntent intent = 0;
    
    CFDataRef data = CFDataCreate(NULL, buffer, width*height*4);
    CGDataProviderRef   dataProvider = CGDataProviderCreateWithCFData(data);
    
    CGImageRef cgimage = CGImageCreate(
                            width, height,
                            bitsPerComponent, bitsPerPixel, bytesPerRow,
                            colorSpace, bitmapInfo, dataProvider,
                            NULL, shouldInterpolate, intent);
    
    UIImage *image = [UIImage imageWithCGImage:cgimage];

    CGImageRelease(cgimage);
    CGDataProviderRelease(dataProvider);
    CGColorSpaceRelease(colorSpace);
    CFRelease(data);
    
    return image;
}

<< コストコのバースデーケーキに挑戦した話  TopPage  ベクトル二つでカメラ姿勢を決めるのは不十分 >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/1030-9a13bfa2




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad