繁体   English   中英

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

[英]OpenGL 3.30 / GLSL 3.30 - MRT outputting black textures

我已经被这个问题困扰了大约四天了。 我正在尝试将我的几何图形渲染为具有三个纹理(反照率,法线,深度)的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用于窗口,输入和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);
}

这里有一些问题。 从最小的开始:

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)语法来指定它,并且它比OpenGL提供的location设置具有更高的优先级

同样,这些都是错误的 您不要将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不是渲染目标所需的图像格式之一 因此,不需要实现来支持它。 可以,但不一定。 而且由于您从不费心检查FBO的完整性 (仅供参考:您应该始终这样做),所以您没有测试这种格式的组合是否有效。

切勿渲染为三分量图像。 选择4、2或1。


GLenum targ [3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_DEPTH_ATTACHMENT };
glDrawBuffers (3, targ);

这可能是您的主要问题: glDrawBuffers调用失败 glDrawBuffers 设置颜色缓冲区输出 深度缓冲区不是颜色缓冲区。 只有一个深度缓冲区,因此无需进行设置。

要写入深度缓冲区...好了,您不应该将用户计算的值写入深度缓冲区。 只需让常规深度缓冲区写入即可处理它。 但是,如果您愿意(并且让我再次提醒您,您不要这样做),请写入gl_FragDepth 那就是它的目的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM