2016/09/01

How to save/remake MTLTexture to/from memory

I have been making a VR game app, and this below is a short video of the game.



After collision (means Game Over), the scene is displayed by a short animation. This post is about how to do it.

You need three render pass (for right eye, left eye, and record), and the render pass for record outputs to a texture (not display).

You can get row data of the texture withe next method :

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


You have to allocate memory for what you need in advance.

{
    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 is the number of memory for one texture (bytes).
By incrementing imageIndex, the app save data to proper address continuously. Of course imageIndex has maximum value and when it gets over the limit, imageIndex becomes zero, so the app overwrites against the old data.
The type for row data of MTLTexture is UInt8.
This process is done in every frame all the time.

And when you have to show the replay, the app makes id<MTLTexture> objects from saved data through UIImage objects. The code (from saved data to id<MTLTexture> ) is like this :

+(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;
}

Develop | Comments(0) | Trackback(0)
Comment

管理者のみに表示