我已经坚持这个问题大约四天了。我正在尝试将我的几何体渲染成具有三个纹理(反照率,法线,深度)的FBO(G缓冲区)。到目前为止,我已经“有点”实现了MRT功能,但是当我使用gDEBugger检查纹理时,它们只显示为黑色。无论我改变什么,它们都会产生坚实的黑色。输出的实际值是正确的,我通过禁用MRT使片段着色器输出到后台缓冲区来检查。正确初始化纹理,gDEBugger正确显示我为它们添加的参数。但它们都只有一个纯黑色(0,0,0,255)填充。
对于GLSL 3.30,几乎没有关于MRT的详细信息。我完全依赖于这里的回答问题,以及网上的OpenGL / GLSL文档和教程(过时,但我更新了代码)。我可能花了整整一天的时间在Google上寻找解决这个问题的方法。如果代码的顺序或语法有问题,请指出。我甚至不知道这个实现是否正确......
我正在使用Visual C ++ 2010,OpenGL 3.30和GLSL 3.30(如标题中所述)。对于我的库,GLFW 3.0用于Windows,输入和OpenGL上下文,GLEW 1.10.0用于扩展。
请记住,所有这些代码都来自我的包装器类。代码的排序是它在运行时的运行方式(换句话说,它就好像我没有包装类,并且所有代码都在main()中)。
初始化阶段
// Initialize textures
glGenTextures (3, tex_ids);
glEnable (GL_TEXTURE_2D);
glBindTexture (GL_TEXTURE_2D, tex_ids[0]); // Diffuse
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);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB8, res.x, res.y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture (GL_TEXTURE_2D, tex_ids[1]); // Normal
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf (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);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB8, res.x, res.y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture (GL_TEXTURE_2D, tex_ids[2]); // Depth
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf (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);
glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, res.x, res.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glBindTexture (GL_TEXTURE_2D, 0);
glDisable (GL_TEXTURE_2D);
// Initialize FBO
glEnable (GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex_ids[0]);
glFramebufferTexture2D ( GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
tex_ids[0],
0 ); // diffuse
glBindTexture(GL_TEXTURE_2D, tex_ids[1]);
glFramebufferTexture2D ( GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT1,
GL_TEXTURE_2D,
tex_ids[1],
0 ); // normal
glBindTexture(GL_TEXTURE_2D, tex_ids[2]);
glFramebufferTexture2D ( GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,
GL_TEXTURE_2D,
tex_ids[2], 0 ); // depth
glBindFramebuffer (GL_FRAMEBUFFER, 0);
glDisable (GL_TEXTURE_2D);
// Initialize shaders
// Snipped out irrelevant code relating to getting shader source & compiling shaders
glBindFragDataLocation (renderer_1prog, GL_COLOR_ATTACHMENT0, "diffuse_out");
glBindFragDataLocation (renderer_1prog, GL_COLOR_ATTACHMENT1, "normal_out");
glBindFragDataLocation (renderer_1prog, GL_DEPTH_ATTACHMENT, "depth_out");
// More snipped out code relating to linking programs and finalizing
绘制舞台 - 每个帧都调用
// Bind everything
glUseProgram (renderer_1prog);
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, fbo_id);
GLenum targ [3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_DEPTH_ATTACHMENT };
glDrawBuffers (3, targ);
// Draw mesh
glEnable (GL_CULL_FACE);
glEnable (GL_DEPTH_TEST);
teshmesh.draw ();
// Unbind fbo
glDisable (GL_CULL_FACE);
glDisable (GL_DEPTH_TEST);
glBindFramebuffer (GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer (GL_DRAW_FRAMEBUFFER, 0);
顶点着色器
#version 330
layout(location = 0)in vec4 v;
layout(location = 1)in vec3 c;
layout(location = 2)in vec3 n;
out vec4 pos;
out vec3 col;
out vec3 nrm;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 world;
void main () {
gl_Position = projection * view * world * v;
pos = view * world * v;
pos.z = -pos.z / 500.0;
col = c.xyz;
nrm = n;
}
片段着色器
#version 330
in vec3 col;
in vec3 nrm;
in vec4 pos;
layout(location = 0) out vec3 diffuse_out;
layout(location = 1) out vec3 normal_out;
layout(location = 2) out vec3 depth_out;
out vec3 o;
void main () {
diffuse_out = col;
normal_out = (nrm / 2.0) + 0.5;
depth_out = vec3 (pos.z, pos.z, pos.z);
}
答案 0 :(得分:4)
这里有一些问题。从最小的开始:
glBindFragDataLocation (renderer_1prog, GL_COLOR_ATTACHMENT0, "diffuse_out");
glBindFragDataLocation (renderer_1prog, GL_COLOR_ATTACHMENT1, "normal_out");
glBindFragDataLocation (renderer_1prog, GL_DEPTH_ATTACHMENT, "depth_out");
这些毫无意义。您在着色器中使用了layout(location)
语法来指定此语法,并that takes priority over OpenGL-provided location settings。
此外,这些错误。您不要将FBO缓冲附件名称放入该位置;您将索引放入该位置。因此,即使您没有使用layout(location)
,这也是不正确的。 glBindFragDataLocation
会发出OpenGL错误,因为该位置肯定会大于GL_MAX_DRAW_BUFFERS
。
考虑到您的代码应该发出多少OpenGL错误,我很惊讶您使用gDEBugger并没有告诉您任何这些错误。
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB8, res.x, res.y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
GL_RGB8
不是required image formats for render targets之一。因此,实施不需要支持它;它可能但不是必须的。因为你从不打扰check the completeness of the FBO(仅供参考:你应该总是这样做),你没有测试这种格式组合是否有效。
永远不要渲染到3分量图像。选择4,2或1。
GLenum targ [3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_DEPTH_ATTACHMENT };
glDrawBuffers (3, targ);
这可能是您的主要问题:您的glDrawBuffers
call fails。 glDrawBuffers
sets the color buffer outputs。深度缓冲区不是颜色缓冲区。只有一个深度缓冲区,所以不需要设置它。
要写入深度缓冲区......好吧,您不应该将用户计算的值写入深度缓冲区。只需让常规深度缓冲区写入即可。但是如果你想(并且让我再次提醒你,你没有),你写信给gl_FragDepth
。这就是它的用途。