OpenGL 3.30 / GLSL 3.30 - MRT输出黑色纹理

时间:2013-08-02 20:05:36

标签: c++ opengl glsl glew glfw

我已经坚持这个问题大约四天了。我正在尝试将我的几何体渲染成具有三个纹理(反照率,法线,深度)的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);
}

1 个答案:

答案 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 failsglDrawBuffers sets the color buffer outputs。深度缓冲区不是颜色缓冲区。只有一个深度缓冲区,所以不需要设置它。

要写入深度缓冲区......好吧,您不应该将用户计算的值写入深度缓冲区。只需让常规深度缓冲区写入即可。但是如果你想(并且让我再次提醒你,你没有),你写信给gl_FragDepth。这就是它的用途。