尝试使用帧缓冲区渲染到纹理总是会导致白色纹理

Posted

技术标签:

【中文标题】尝试使用帧缓冲区渲染到纹理总是会导致白色纹理【英文标题】:Trying to render to texture using framebuffer always results in white texture 【发布时间】:2009-12-23 01:35:04 【问题描述】:

使用 *** 中的几篇文章,我使用帧缓冲区创建了一个简单的渲染到纹理。

这里的问题是它不起作用。混合中有些东西坏了,因为我的最终纹理只是一个白色方块。我没有收到任何 gl 错误。这是我的代码。

声明实例变量。

GLuint texture;
GLuint textureFrameBuffer;

生成纹理和帧缓冲区。

    glGetError();

    //Generate the texture that we will draw to (saves us a lot of processor).
    glEnable(GL_TEXTURE_2D);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    // Use OpenGL ES to generate a name for the texture.
    // Pass by reference so that our texture variable gets set.
    glGenTextures(1, &texture);

    // Bind the texture name. 
    glBindTexture(GL_TEXTURE_2D, texture);

    // Specify a 2D texture image, providing a pointer to the image data in memory.
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    //Create a frame buffer to draw to. This will allow us to directly edit the texture.
    GLint oldFBO;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);
    glGenFramebuffersOES(1, &textureFrameBuffer);
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture, 0);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);

    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
    
        NSLog(@"Error on framebuffer init. glError: 0x%04X", err);
    

在帧缓冲区中画一个大字符串。

glGetError();

GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);

//Bind our frame buffer.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);

//Clear out the texture.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//Draw the letters to the frame buffer. (calls glDrawArrays a bunch of times, binds various textures, etc.) Does everything in 2D.
[self renderDialog:displayString withSprite:displaySprite withName:displaySpriteName];

//Unbind the frame buffer.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);

GLenum err = glGetError();
if (err != GL_NO_ERROR)

    NSLog(@"Error on string creation. glError: 0x%04X", err);

画出来。

    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    glGetError();

    //Draw the text.
    [EAGLView enable2D];

    //Push the matrix so we can keep it as it was previously.
    glPushMatrix();

    //Store the coordinates/dimensions from the rectangle.
    float x = 0;
    float y = [Globals getPlayableHeight] - dialogRect.size.height;
    float w = [Globals getPlayableWidth];
    float h = dialogRect.size.height;

    // Set up an array of values to use as the sprite vertices.
    GLfloat vertices[] =
    
        x,      y,
        x,      y+h,
        x+w,    y+h,
        x+w,    y
    ;

    // Set up an array of values for the texture coordinates.
    GLfloat texcoords[] =
    
        0,          0,
        0,          h / 128,
        w / 512,    h / 128,
        w / 512,    0
    ;

    //Render the vertices by pointing to the arrays.
    glVertexPointer(2, GL_FLOAT, 0, vertices);
    glTexCoordPointer(2, GL_FLOAT, 0, texcoords);

    // Set the texture parameters to use a linear filter when minifying.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    //Allow transparency and blending.
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    //Enable 2D textures.
    glEnable(GL_TEXTURE_2D);

    //Bind this texture.
    [EAGLView bindTexture:texture];

    //Finally draw the arrays.
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    //Restore the model view matrix to prevent contamination.
    glPopMatrix();

    GLenum err = glGetError();
    if (err != GL_NO_ERROR)
    
        NSLog(@"Error on draw. glError: 0x%04X", err);
    

我所说的任何外部事物在其他情况下都可以正常工作。有任何想法吗?我对帧缓冲区几乎一无所知,所以任何故障排除帮助都会很棒。

【问题讨论】:

【参考方案1】:

纹理参数是基于每个纹理设置的。您发布的代码似乎在创建或绑定您要渲染的纹理之前设置GL_TEXTURE_MIN_FILTER。如果您没有在其他任何地方设置过滤器,并且您没有为其余级别指定纹理图像,则您的纹理可能不完整,这就是您变白的原因。

为了将来参考,帧缓冲区设置后没有 GL 错误并不意味着帧缓冲区可用于渲染。您还应该通过调用 glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) 并验证是否返回了 GL_FRAMEBUFFER_COMPLETE_OES 来检查帧缓冲区是否完整。

【讨论】:

我会试试看的。实际上我之前进行了完成检查,这是真的 - 我只是没有将它包含在上面的代码中。如果这个帧缓冲区是完整的,我认为这并不一定意味着一切都会正常工作,对吗?另外,我不确定我是否关注 GL_TEXTURE_MIN_FILTER - 我在调用 glGenTextures 之前设置了它(参见第一个代码块)。 每个纹理都有自己的缩小/放大功能和包裹模式。调用 glTexParameterf 只会影响调用函数时当前绑定的纹理。如果要更改要渲染到的纹理的缩小函数,则需要在创建和绑定纹理后调用 glTexParameterf。听起来帧缓冲区的完整性与您的特定情况无关,但记住更多奇特的帧缓冲区对象配置是一件好事。

以上是关于尝试使用帧缓冲区渲染到纹理总是会导致白色纹理的主要内容,如果未能解决你的问题,请参考以下文章

Opengl渲染到深度纹理 - 红色?

JOGL 和帧缓冲区渲染到纹理的问题:无效帧缓冲区操作错误

帧缓冲纹理出现白色(片段着色器不影响它)

OpenGL 帧缓冲区 - 渲染到纹理创建带有主帧缓冲区内容的纹理

使用帧缓冲区将深度缓冲区渲染到纹理中

Android GLES 2.0:帧缓冲渲染到半浮点纹理适用于某些设备,而不是其他设备