【发布时间】:2014-04-20 06:10:59
【问题描述】:
我一直在尝试将 SSAO(基于此处的教程:http://john-chapman-graphics.blogspot.co.nz/2013/01/ssao-tutorial.html)添加到我的项目中,但我一直无法正确渲染深度。
我创建了一个帧缓冲纹理来绘制每一帧的深度。当我将纹理绘制到四边形时,纹理本身看起来是正确的,但我不知道如何正确地将其应用到整个场景。
这是常规场景的样子:
这是应用的深度纹理:
目前在我的片段着色器中,我只使用我的常规纹理坐标 (TexCoord0) 来绘制深度纹理。我猜我需要更改它,但我不知道将其更改为什么。 以下是相关的片段着色器代码:
#version 330 core
in vec2 TexCoord0;
smooth in vec3 vNormal;
smooth in vec3 vWorldPos;
in mat4 ProjectionMatrix;
uniform sampler2D uDepthTex;
layout(location = 0) out vec4 FragColor;
void main()
{
FragColor = texture(uDepthTex, TexCoord0);
}
我不知道如何解决这个问题。我在网上阅读了很多示例代码,似乎使用常规纹理坐标来绘制深度。
编辑: 这是我的帧缓冲区设置代码:
glGenFramebuffers(1, &ssaoFramebufferID);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glGenTextures(1, &ssaoDepthTextureID);
glBindTexture(GL_TEXTURE_2D, ssaoDepthTextureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
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);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, ssaoDepthTextureID, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
以及我在常规绘制之前调用每一帧的深度密码:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 1024);
depthShader.Bind();
depthShader.SetUniformMatrixfv("depthMVP", camera.GetViewMatrix() * Matrix4::Perspective(60, aspectRatio, 0.1f, 10.0f));
DrawScene(true);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, width, height);
我的深度着色器,顶点:
#version 330 core
layout(location = 0) in vec3 Position;
uniform mat4 depthMVP;
void main() {
gl_Position = depthMVP * vec4(Position, 1.0);
}
片段:
#version 330 core
layout(location = 0) out float fragmentdepth;
void main() {
fragmentdepth = gl_FragCoord.z;
}
编辑2: 它当前所在的 glClear 调用给了我一个完全黑色的纹理。将它放在第一个 glViewport 调用的下面给出了我在上面显示的深度图像:
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, ssaoFramebufferID);
glViewport(0, 0, 1024, 1024);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
【问题讨论】:
-
你知道深度纹理的默认输出已经是:
vec4 (r, r, r, 1.0),对吧?你可以写FragColor = texture(uDepthTex, TexCoord0);。至于其他情况,GLSL 着色器不会帮助解释这一点 - 设置深度缓冲区、投影矩阵、FBO 等的代码实际上更相关。 -
是的,我知道这一点。我的实际着色器要大得多,我只是编辑掉了不相关的东西(点光源等),这是一个疏忽。我用更多信息更新了我的问题。
-
GL_DEPTH_TEXTURE_MODE在 GLSL 3.30 中也已弃用。自 GLSL 1.30 (GL 3.0) 以来,它已被弃用。那是我在第一条评论中提到的行为开始生效的时候,GL_DEPTH_TEXTURE_MODE的原因被删除了。我很确定这不是一个实际问题,但是如果您通过 gDEBugger 之类的东西运行此代码,它会给您提供与我所做的几乎相同的警告;)至于您的实际问题,您似乎永远不会清除 FBO 的深度缓冲区.您在代码中明确颜色/深度,但仅之前绑定您的 FBO 以进行仅深度传递。 -
谢谢,我删除了 GL_DEPTH_TEXTURE_MODE 调用。移动 glClear 似乎有时会给我一个黑屏。我会更新我的问题以说明我的意思。
-
顺便说一句,您可能需要在将深度值写入片段输出之前对其进行线性化。否则您将看不到正确的可视化效果。
标签: opengl textures framebuffer depth depth-buffer