我无法正确渲染自己的深度。没有抛出任何错误,glCheckFramebufferStatus表示它也是完整的。
下面是代码,屏幕始终显示白色。深度值不是1,但非常接近:
所以我尝试线性化深度片段着色器内部的深度,然后将其直接绘制到屏幕上以确保值正确。他们是对的。但是,即使我将线性化深度发送到我的全屏四边形着色器(下面的第二个),屏幕仍然全白。
public void initFramebuffers() {
glBindFramebuffer(GL_FRAMEBUFFER, depthShader.fbo);
depthShader.initTexture(width, height, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthShader.tex, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
}
public void initTexture(int width, int height, int format, int internalFormat) {
tex = glGenTextures();
glBindTexture(GL_TEXTURE_2D, tex);
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_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_FLOAT, (ByteBuffer)null);
}
深度着色器:
#version 400
in vec3 pos;
in float radius;
uniform mat4 mView;
uniform mat4 projection;
uniform vec2 screenSize;
uniform vec3 lightPos;
out float depth;
float linearizeDepth(float depth) {
float n = 0.01;
float f = 100;
return (2.0 * n) / (f + n - depth * (f - n));
}
void main() {
//calculate normal
vec3 normal;
normal.xy = gl_PointCoord * 2.0 - 1.0;
float r2 = dot(normal.xy, normal.xy);
if (r2 > 1.0) {
discard;
}
normal.z = sqrt(1.0 - r2);
//calculate depth
vec4 pixelPos = vec4(pos + normal * radius, 1.0);
vec4 clipSpacePos = projection * pixelPos;
depth = clipSpacePos.z / clipSpacePos.w * 0.5f + 0.5f;
depth = linearizeDepth(depth);
}
深入读取的着色器。 linearizeDepth中的值是我的近距离和远距离:
#version 400
in vec2 coord;
uniform sampler2D depthMap;
uniform vec2 screenSize;
uniform mat4 projection;
out vec4 color;
float linearizeDepth(float depth) {
float n = 0.01;
float f = 100;
return (2.0 * n) / (f + n - depth * (f - n));
}
void main() {
float curDepth = texture2D(depthMap, coord).x;
//float d = linearizeDepth(curDepth);
color = vec4(d, d, d, 1.0f);
}
绘制所有内容的代码:
//--------------------Particle Depth-----------------------
{
glUseProgram(depthShader.program);
glBindFramebuffer(GL_FRAMEBUFFER, depthShader.fbo);
depthShader.particleDepthVAO(points);
//Sets uniforms
RenderUtility.addMatrix(depthShader, mView, "mView");
RenderUtility.addMatrix(depthShader, projection, "projection");
RenderUtility.addVector2(depthShader, screenSize, "screenSize");
RenderUtility.addVector3(depthShader, lightPosition, "lightPos");
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(depthShader.vao);
glDrawArrays(GL_POINTS, 0, points.size());
}
//Draw full screen
{
glUseProgram(blurShader.program);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
blurShader.blurDepthVAO();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthShader.tex);
glUniform1i(blurShader.depthMap, 0);
//Sets uniforms
RenderUtility.addMatrix(blurShader, mView, "mView");
RenderUtility.addMatrix(blurShader, projection, "projection");
RenderUtility.addVector2(blurShader, screenSize, "screenSize");
//glEnable(GL_DEPTH_TEST);
glBindVertexArray(blurShader.vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glViewport(0, 0, width, height);
}
答案 0 :(得分:2)
问题最终是我的顶点着色器的变量名称与变量名称(doh)中的片段着色器不匹配。上面发布的代码是100%正确的,如果有人在将来看到这个。
答案 1 :(得分:0)
发布的代码存在一些问题。
在FBO的设置中,只有深度附件,没有颜色附件。颜色绘制缓冲区也被明确禁用:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthShader.tex, 0);
glDrawBuffer(GL_NONE);
但是,片段着色器会写入颜色输出:
out float depth;
...
depth = clipSpacePos.z / clipSpacePos.w * 0.5f + 0.5f;
depth = linearizeDepth(depth);
要写入帧缓冲区的深度附件,您必须设置预定义gl_FragDepth
变量的值。仅仅因为out变量名为depth
并不意味着它实际上被用作深度输出。如果要使用颜色输出,则必须创建常规纹理,并将其附加到GL_COLOR_ATTACHMENT0
。这实际上看起来更容易。
float linearizeDepth(float depth) {
float n = 0.01;
float f = 100;
return (2.0 * n) / (f + n - depth * (f - n));
}
depth = clipSpacePos.z / clipSpacePos.w * 0.5f + 0.5f;
depth = linearizeDepth(depth);
处理clipSpacePos
的方式,看起来linarizeDepth()
的参数介于0.0和1.0之间。然后,函数内部对这些极值的计算是:
0.0 --> (2.0 * n) / (f + n)
1.0 --> 1.0
1.0看起来很好,但0.0可疑。我认为制定准备步骤实际上更为正确:
depth = clipSpacePos.z / clipSpacePos.w;
然后将-1.0和1.0之间的参数传递给函数,然后生成:
-1.0 --> n / f
1.0 --> 1.0
实际上,对整个事物进行缩放以产生0.0到1.0之间的结果会更有意义,但至少这个版本具有直观意义,产生与远平面的相对距离。
以上看起来对我来说是不必要的。您正在应用投影矩阵,从结果中获取深度,然后有效地反转投影矩阵应用的深度计算。
首先不应用投影矩阵似乎更简单,只需采用原始距离即可。如果你想要一个相对距离,你仍然可以除以远距离。至少只要您使用标准投影矩阵,我相信以下内容相当于上面的更正计算:
vec4 pixelPos = vec4(pos + normal * radius, 1.0);
float f = 100.0; // far plane
depth = -pixelPos.z / f;
减号出现是因为最常用的眼睛坐标系统假设您正在向下看负z轴。
如果您希望结果介于0.0和1.0之间,您还可以将其更改为:
float n = 0.01; // near plane
float f = 100.0; // far plane
depth = (-pixelPos.z - n) / (f - n);