尝试使用帧缓冲区进行纹理渲染始终导致白色纹理

3

使用StackOverflow上的一些帖子,我创建了一个使用帧缓冲区渲染到纹理的简单方法。

问题在于它不起作用。由于我的最终纹理只是一个白色正方形,因此混合中出了问题。我没有得到任何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个回答

4
纹理参数是按纹理为基础设置的。您发布的代码似乎在创建或绑定要渲染的纹理之前设置了GL_TEXTURE_MIN_FILTER。如果您没有在其他地方设置过滤器,并且您没有为其余级别指定纹理图像,则您的纹理可能是不完整的,这就是为什么您得到白色的原因。
作为将来的参考,帧缓冲设置后没有GL错误并不意味着帧缓冲可用于渲染。您还应该调用glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES)来检查帧缓冲是否完整,并验证返回的GL_FRAMEBUFFER_COMPLETE_OES

我会尝试一下。实际上,我之前已经进行了完成检查,并且结果为true - 我只是没有在上面的代码中包含它。如果这个帧缓冲完整,我假设这并不意味着一切都会正常工作,对吗?此外,关于GL_TEXTURE_MIN_FILTER,我不确定我是否理解您的意思 - 在调用glGenTextures之前我已经设置了它(请参见第一个代码块)。 - Eli
每个纹理都有自己的缩小/放大函数和包裹模式。对glTexParameterf的调用仅影响在调用该函数时当前绑定的纹理。如果您想要更改正在渲染的纹理的缩小函数,则需要在创建和绑定纹理后调用glTexParameterf。听起来帧缓冲完整性对于您的特定情况并不相关,但对于更奇特的帧缓冲对象配置来说,这是一件好事情需要记住。 - Pivot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接