我想将场景绘制到帧缓冲区对象,然后在另一个着色器中使用它的纹理。出于测试目的,我只想实际输出帧缓冲区对象的纹理。然而,对应的部分(矩形)恰好是全黑的。所以我想知道是 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/