无法使用深度附件渲染到FBO中

时间:2014-02-04 19:56:28

标签: java opengl 3d shader lwjgl

我正在尝试实施阴影贴图几天,我想我开始看到手头上的真正问题:我有一个附有深度纹理的FBO,用于阴影贴图的光通过,但是没有任何东西在里面呈现。甚至没有硬编码的值。

我已经仔细检查了可视化深度纹理的程序部分,并且使用了常规纹理,而且我看到我的场景中没有出现阴影,所以我认为某些内容肯定是错误的。

INIT:

    //shadow FBO and texture
    depthFBO = new FrameBufferObject().create().bind();
    depthTexture = new Texture2D().create().bind()
            .storage2D(12, GL_DEPTH_COMPONENT32F, 4096, 4096)
            .minFilter(GL_LINEAR)
            .magFilter(GL_LINEAR)
            .compareMode(GL_COMPARE_REF_TO_TEXTURE)
            .compareFunc(GL_LEQUAL);
    depthFBO.texture2D(GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, depthTexture, 0)
            .checkStatus().unbind();
    depthTexture.unbind();

渲染:

    depthFBO.bind();
    glViewport(0, 0, 4096, 4096);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(4.0f, 4.0f);
    glDrawBuffer(GL_NONE);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClearDepthf(1f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    Drawable.drawAllLightPass(drawables, lightNormalProgram, lightTessellationProgram);
    glDisable(GL_POLYGON_OFFSET_FILL);
    depthFBO.unbind();

直接gl*来电中的代码。

INIT:

int frameBufferObjectId = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferObjectId);

int textureId = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 12, GL_DEPTH_COMPONENT32F, 4096, 4096);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, textureId, 0);
if (GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) != GL30.GL_FRAMEBUFFER_COMPLETE) {
    throw new RuntimeException(this + " is not complete.");
}
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

渲染:

GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBufferObjectId);
glViewport(0, 0, 4096, 4096);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(4.0f, 4.0f);
glDrawBuffer(GL_NONE);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepthf(1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//appropiate calls to glDraw* are being done, this is confirmed to work as it works for displaying data

glDisable(GL_POLYGON_OFFSET_FILL);
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);

现在最重要的着色器:

light-normal.vs.glsl

#version 430 core

layout(location = 4) uniform mat4 light_model_matrix;
layout(location = 5) uniform mat4 light_view_matrix;
layout(location = 6) uniform mat4 light_projection_matrix;

layout(location = 0) in vec4 position;

void main(void) {
    gl_Position = light_projection_matrix * light_view_matrix * light_model_matrix * position;
}

light-normal.fs.glsl

#version 430 core

layout(location = 0) out float depth;

void main(void) {
    depth = gl_FragCoord.z;
}

即使将depth硬编码到0.0f0.5f1.0f也不起作用。

只是为了澄清我的期望是否正确:当我将相机移动到靠近屏幕上呈现的对象时,深度缓冲区的颜色应该改变吗?深度将接近0.0f,然后远离1.0f?

另一个澄清:我所看到的深度值是一个到处都是白色的矩形。

根据要求,着色器可视化深度纹理数据:

depth-box.vs.glsl

#version 430 core

void main(void) {
    const vec4 vertices[6] = vec4[](
        vec4(-1.0, -1.0, 1.0, 1.0),
        vec4(-1.0, 1.0, 1.0, 1.0),
        vec4(1.0, 1.0, 1.0, 1.0),

        vec4(1.0, 1.0, 1.0, 1.0),
        vec4(1.0, -1.0, 1.0, 1.0),
        vec4(-1.0, -1.0, 1.0, 1.0)
    ); 

    gl_Position = vertices[gl_VertexID];
}

depth-box.fs.glsl

#version 430 core

layout(location = 7) uniform int screen_width;
layout(location = 8) uniform int screen_height;

layout(binding = 0) uniform sampler2D shadow_tex;

out vec4 color;

void main(void) {
    vec2 tex_coords = vec2(
        (gl_FragCoord.x - 100) / (screen_width / 5),
        (gl_FragCoord.y - (screen_height - (screen_height / 5) - 100)) / (screen_height / 5)
    );
    color = vec4(vec3(texture(shadow_tex, tex_coords).r), 1.0);
}

1 个答案:

答案 0 :(得分:1)

这不起作用,你忘了禁用纹理比较。您无法使用GL_NONE使用sampler2D以外的texutre比较模式对纹理进行采样。 结果将是未定义的。

在启用比较的情况下读取纹理需要

sampler2DShadow。当你这样做时,前两个纹理坐标正常工作,但第三个是要比较的深度值,texture (...)的返回值是一个浮点值(1.0表示通过,0.0表示失败)。如果你有一个线性过滤器,它可能介于两者之间。