c++ - OpenGL 3.0 : Cannot use framebuffer object in shader (black)

标签 c++ opengl framebuffer

我想将场景绘制到帧缓冲区对象,然后在另一个着色器中使用它的纹理。出于测试目的,我只想实际输出帧缓冲区对象的纹理。然而,对应的部分(矩形)恰好是全黑的。所以我想知道是 fbo 的渲染不起作用还是无法访问它。

这里是重要的代码部分:

在渲染到 FBO 之前调用:

void TextureRenderer::bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
    //  glPushAttrib(GL_VIEWPORT_BIT);
    glViewport(0, 0, mWidth, mHeight);
}

这是应该显示 FBO 的平面。第一个纹理“mTextureId”是我从 TGA 文件加载并显示的另一个纹理,效果很好。然而,第二个“mReflectionTextureId”是来自 VBO 的那个,这是我无法访问的那个(或者它真的是黑色的,因为之前有错误)。

void WaterPlane::render(const Transform& trans) {
    mat4 projection = trans.projection;
    mat4 view = trans.view;
    mat4 model = mat4::identitiy();

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);

    mShader->bind();

    // lets activate the textures now
    glEnable(GL_TEXTURE_2D);

    // bumpmap texture
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mTextureId);
    // set the texture
    mShader->seti("waterBumpTextureSampler", 0);

    // rendered reflection texture (has been rendered previously with the help of Framebuffer object for reflection)
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, mReflectionTextureId);
    // set reflection texture 
    mShader->seti("renderedReflection", 1);

    mShader->setMatrix("matProjection", projection, GL_TRUE);
    mShader->setMatrix("matView", view, GL_TRUE);
    mShader->setMatrix("matModel", model, GL_TRUE);
    mShader->setf("vecTextureShift", mTextureShift);

    mVboWaterPlane->render();

    mShader->release();

    glDisable(GL_TEXTURE_2D);

    glPopClientAttrib();
    glPopAttrib();
}

最后,water.fs 着色器:

#version 130
in vec4 VertPosition;
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture;

uniform vec3 lightPos;
uniform sampler2D waterBumpTextureSampler;
uniform sampler2D renderedReflection; // reflection on the water

void main()
{
    // completely black
    gl_FragColor = texture( renderedReflection, VertTexture.xz); 

    // if this is actually commented in the bumpmap texture will be shown nicely
   // gl_FragColor = texture( waterBumpTextureSampler, VertTexture.xz); 
}

所以一般来说,显示纹理是可行的,但是显示来自帧缓冲区对象的纹理却不行(或者之前对它的渲染不起作用)。

截图:

编辑:

FBO的初始化代码:

void TextureRenderer::init() {
    glGenFramebuffers(1, &mFramebufferName);
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);

    // The texture we're going to render to
    glGenTextures(1, &mRenderedTextureId);

    // "Bind" the newly created texture : all future texture functions will modify this texture
    glBindTexture(GL_TEXTURE_2D, mRenderedTextureId);

    cout << "TextureRenderer: creating with id " << mFramebufferName << " and tex id " << mRenderedTextureId << endl;

    // Give an empty image to OpenGL ( the last "0" )
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mWidth, mHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

    // Poor filtering. Needed !
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    // The depth buffer 
    // TODO this is probably not needed?!?!?!
    glGenRenderbuffers(1, &mDepthRenderBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, mDepthRenderBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, mWidth, mHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepthRenderBuffer);

    // Set "renderedTexture" as our colour attachement #0
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mRenderedTextureId, 0);

    // Set the list of draw buffers.
    GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
    glDrawBuffers(1, DrawBuffers); // "1" is the size of DrawBuffers

    // Always check that our framebuffer is ok
    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
        cout << "Problem during creation of TextureRenderer" << endl;
        throw std::runtime_error("Something Bad happened here");
    }

    unbind();

    cout << "TextureRenderer: creating with id " << mFramebufferName << "...done" << endl;
}

绑定(bind)代码(在渲染到 FBO 之前立即调用):

void TextureRenderer::bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
    //  glPushAttrib(GL_VIEWPORT_BIT); // http://wiki.delphigl.com/index.php/Tutorial_Framebufferobject
    glViewport(0, 0, mWidth, mHeight);
}

最佳答案

现在已经解决了。问题很简单,我在 water.fs(片段)着色器中使用了错误的纹理坐标。下面是 water.fs 的更正变体。请注意随后提供给 texture(...) 函数的坐标计算的差异。

in vec4 VertPosition; 
in vec4 VertNormal;
in vec4 VertColor;
in vec4 VertTexture; 
in vec4 VertTexturePS;

uniform vec3 lightPos;
uniform sampler2D waterBumpTextureSampler; 
uniform sampler2D texReflection; // reflection on the water

void main()
{
    vec2 originalTexCoord = VertTexturePS.xy / VertTexturePS.w * 0.5 + vec2(0.5);
    gl_FragColor = texture( texReflection, originalTexCoord.xy); 
}

VertTexturePS 只是在 water.vs 中计算出来的:

VertTexturePS = matProjection * matView * matModel * vec4(Position.xyz, 1);

关于c++ - OpenGL 3.0 : Cannot use framebuffer object in shader (black),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24012931/

相关文章:

c++ - 如何处理使用 dlopen() 打开的已更改库

c++ - 了解C++中的decltype返回什么

c - Linux framebuffer像素位域通用实现

ios - 在 OpenGL ES 中绑定(bind)多个缓冲区

image - Vulkan 中的帧缓冲区和图像有什么区别?

c++ - 错误 : comparison between signed and unsigned integer expressions?

c++ - C++ const mysqlpp::String模棱两可的错误

C - OpenGL 中的深度效果

c++ - OpenGL reshape 函数

c++ - 布局中有多个 QGLWidget