在着色器中生成浮动纹理和用法

时间:2016-07-01 14:22:48

标签: ios objective-c opengl-es textures

我在生成带有深度数据的Float纹理时遇到问题。

由于我认为它更像是一个OpenGL ES(OES 2.0)问题而不是我正在使用的SDK,我试着在这里考虑OpenGL ES部分获得帮助。

我得到的错误只是我的应用程序崩溃,这就是为什么我认为错误是错误的纹理和/或错误使用浮动纹理。

关于我正在使用的数据的几个注释:

-The depthFrame I am getting is in Float
-With the use of depthInMillimeters, it is possible to get actual mm values in Float 
-Since i am working on an iPhone 5 GL_HALF_FLOAT_OES should be available to use
-If someone wants to know, the data comes from the StructureSensor

这是我从流式深度数据生成纹理的功能。 我使用几乎相同的函数从图像生成RGB纹理,但使用其他数据输入和值。

    -(GLuint) generateDepthTexture: (STDepthFrame*)depthFrame{

    //data from depth in mm
    NSData *data = [NSData dataWithBytes:depthFrame.depthInMillimeters length:depthFrame.width*depthFrame.height*4];

    //data to texture
    UIImage* depthImage = [[UIImage alloc] initWithData:data];

    CGImageRef spriteImage = [depthImage CGImage];
    if(!spriteImage){
        NSLog(@"Failed to load image depth");
        exit(1);
    }

    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);

    GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte)); // *4


    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,
                                                   CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);

    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
    CGContextRelease(spriteContext);


    GLuint texName;

    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_FLOAT, (GLsizei)width,(GLsizei)height, 0, GL_FLOAT, GL_HALF_FLOAT_OES, spriteData);

    free(spriteData);

    return texName;


    }

这是我的渲染方法的重要部分:

    //depth
    //depthFrame is given every call
    _depthTexture = [self generateDepthTexture:depthFrame];

    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, _depthTexture);
    glUniform1i(_depthUniform, 2);

我在着色器中使用它:

    //texture 
    uniform sampler2D DepthTexture;

    //usage of the Texture
    mediump vec4 depthV = texture2D(DepthTexture,TexCoordsIn);

我不确定这里的正确使用方法,因为我宁愿在浮点数中获取值,而不是在vec4中。

同样,我想在考虑具有浮动纹理的OpenGL ES部分时获得一些帮助。如果完全正确,问题必须与我得到的数据有关。如果是这样的话,我会问使用传感器的人。

错误可能只是错误的纹理大小或内存。

我真的希望,有人对此有答案。

1 个答案:

答案 0 :(得分:2)

OP似乎已经意识到了这一点,但为了清晰起见,只是提前发送:浮动纹理标准的ES 2.0功能。仅当OES_texture_float and/or OES_texture_half_float扩展名存在时才支持它们。对于半浮点情况,这是相当明显的,因为扩展引入了GL_HALF_FLOAT_OES值,但浮点大小写也需要扩展支持,即使扩展不引入新的枚举值。

您尝试使用此扩展程序存在许多问题:

glTexImage2D(GL_TEXTURE_2D, 0, GL_FLOAT, (GLsizei)width, (GLsizei)height, 0,
             GL_FLOAT, GL_HALF_FLOAT_OES, spriteData);

您尝试将GL_FLOAT / GL_HALF_FLOAT值传递给内部格式格式类型 glTexImage2D()的论点。但扩展只为 type 参数引入了新值。因此,分配单分量浮动纹理的正确调用是:

glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, (GLsizei)width, (GLsizei)height, 0,
             GL_LUMINANCE, GL_FLOAT, spriteData);

请注意,与新版本的OpenGL不同,ES 2.0仍然使用GL_LUMINANCEGL_ALPHA作为单组件的 internalformat format 纹理。

对于半浮点纹理,调用是:

glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, (GLsizei)width, (GLsizei)height, 0,
             GL_LUMINANCE, GL_HALF_FLOAT_OES, spriteData);

对于这种半浮动情况,了解您需要将半浮点(每值16位)数据传递到调用中非常重要。如果您的原始数据是浮动格式,则您必须编写(或查找)将其转换为half-float format的代码。

这在ES 3.0及更高版本中看起来有所不同,其中引入了来自更现代的OpenGL版本的大小的内部格式。在那里,分配单组件浮动纹理的调用将是:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, (GLsizei)width, (GLsizei)height, 0,
             GL_RED, GL_FLOAT, spriteData);