【问题标题】:Directional shadow mapping in deferred shading延迟着色中的方向阴影映射
【发布时间】:2018-05-24 05:48:22
【问题描述】:

我正在延迟着色中实现定向阴影映射。

首先,我从光照视图(正交投影)渲染深度图。

结果:

我打算做VSM所以上面的缓冲区是R32G32存储深度和深度*深度。

然后对于阴影的全屏着色通道(在光照通道之后),我编写了以下像素着色器:

    #version 330

    in vec2 texCoord; // screen coordinate
    out vec3 fragColor; // output color on the screen

    uniform mat4 lightViewProjMat; // lightView * lightProjection (ortho)

    uniform sampler2D sceneTexture; // lit scene with one directional light
    uniform sampler2D shadowMapTexture;
    uniform sampler2D scenePosTexture; // store fragment's 3D position

    void main() {
      vec3 fragPos = texture(scenePosTexture, texCoord).xyz; // get 3D position of pixel
      vec4 fragPosLightSpace = lightViewProjMat * vec4(fragPos, 1.0); // project it to light-space view: lightView * lightProjection

      // projective texture mapping
      vec3 coord = fragPosLightSpace.xyz / fragPosLightSpace.w;
      coord = coord * 0.5 + 0.5;

      float lightViewDepth; // depth value in the depth buffer - the maximum depth that light can see
      float currentDepth; // depth of screen pixel, maybe not visible to the light, that's how shadow mapping works
      vec2 moments; // depth and depth * depth for later variance shadow mapping

      moments = texture(shadowMapTexture, coord.xy).xy;
      lightViewDepth = moments.x;
      currentDepth = fragPosLightSpace.z;

      float lit_factor = 0;
      if (currentDepth <= lightViewDepth)
        lit_factor = 1; // pixel is visible to the light
      else
        lit_factor = 0; // the light doesn't see this pixel

      // I don't do VSM yet, just want to see black or full-color pixels
      fragColor = texture(sceneTexture, texCoord).rgb * lit_factor;
}

渲染的结果是黑屏,但是如果我硬编码 lit_factor 为 1,结果是:

基本上就是sceneTexture的样子。

所以我认为我的深度值是错误的,这不太可能,或者我的投影(上方着色器/投影纹理映射中的光空间投影)是错误的。你能帮我验证一下吗?

我的阴影贴图生成代码是:

// vertex shader
#version 330 compatibility

uniform mat4 lightViewMat; // lightView
uniform mat4 lightViewProjMat; // lightView * lightProj

in vec3 in_vertex;
out float depth;

void main() {
  vec4 vert = vec4(in_vertex, 1.0);
  depth = (lightViewMat * vert).z / (500 * 0.2); // 500 is far value, this line tunes the depth precision
  gl_Position = lightViewProjMat * vert;
}

// pixel shader
#version 330

in float depth;
out vec2 out_depth;

void main() {
  out_depth = vec2(depth, depth * depth);
}

【问题讨论】:

    标签: opengl glsl shadow opengl-3 deferred-rendering


    【解决方案1】:

    片段着色器内置变量gl_FragCoordz 组件包含范围[0.0, 1.0] 内的深度值。这是您应该存储到深度图的值:

    out_depth = vec2(gl_FragCoord.z, depth * depth);
    

    计算后

    vec3 fragPos = texture(scenePosTexture, texCoord).xyz; // get 3D position of pixel
    vec4 fragPosLightSpace = lightViewProjMat * vec4(fragPos, 1.0); // project it to light-space view: lightView * lightProjection
    vec3 ndc_coord = fragPosLightSpace.xyz / fragPosLightSpace.w;
    

    变量ndc_coord 包含一个标准化的设备坐标,其中所有组件都在[-1.0, 1.0] 范围内。

    标准化设备坐标的z分量可以转换为深度值(如果depth range是[0.0, 1.0]),通过

    float currentDepth = ndc_coord.z * 0.5 + 0.5;
    

    这个值可以与深度图中的值进行比较,因为currentDepthlightViewDepth是由相同的视图矩阵和投影矩阵计算的:

    moments = texture(shadowMapTexture, coord.xy).xy;
    lightViewDepth = moments.x;
    
    if (currentDepth <= lightViewDepth)
        lit_factor = 1; // pixel is visible to the light
    else
        lit_factor = 0; // the light doesn't see this pixel
    

    【讨论】:

    【解决方案2】:

    这是您存储在阴影贴图中的深度:

    depth = (lightViewMat * vert).z / (500 * 0.2);
    

    这是您比较回读值的深度:

    vec4 fragPosLightSpace = lightViewProjMat * vec4(fragPos, 1.0);
    currentDepth = fragPosLightSpace.z;
    

    如果fragPos 在世界空间中,那么我假设lightViewMat * vert == fragPos。您通过除以500 * 0.2 来压缩深度,但这不等于fragPosLightSpace.z

    提示:在一个通道中写出 currentDepth 的值,在另一个通道中写出阴影贴图中的值,然后您可以在视觉上或在 RenderDoc 或类似中比较它们。

    【讨论】:

    • 谢谢,它确实解决了我的问题,而且我发现我绑定了错误的纹理,所以 scenePosTexture 没用。一些初始阴影:i.imgur.com/lTqkMkB.png 我需要更正一下。
    猜你喜欢
    • 2014-05-17
    • 2013-08-23
    • 1970-01-01
    • 2016-12-22
    • 1970-01-01
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多