4

我在 stackoverflow 和一些书中阅读了几篇文章。但我在我的代码中找不到错误。我有一个延迟渲染器,并在 g 缓冲区内保存了反照率、深度和法线(包括规格)。此外,从场景顶部的光源创建了阴影贴图。

它看起来像这样:

反照率 (R8G8B8A8): 反照率

正常(R8G8B8A8): 普通的

线性深度 (F32): 在此处输入图像描述

来自光源的阴影贴图(线性深度)(相机上方 500 米): 在此处输入图像描述

好的。我的带有阴影映射的延迟着色器代码如下所示:我已经上传了行主矩阵。

顶点着色器:

layout(row_major) uniform UVSViewMatrix
{
    mat4 m_ScreenMatrix;
};

layout(location = 0) in vec3 VertexPosition;

smooth out vec2 PSTexCoord;

void main()
{
    vec4 Position = vec4(VertexPosition.xyz, 1.0f);

    PSTexCoord = Position.xy;

    gl_Position = Position * m_ScreenMatrix;
}

片段着色器:

#version 410

// -----------------------------------------------------------------------------
// Input from engine
// -----------------------------------------------------------------------------
layout(row_major) uniform UPSCameraProperties
{
    mat4 m_ProjectionMatrix;
    mat4 m_CameraView;
    vec3 m_CameraPosition;
    vec3 m_CameraDirection;
};

layout(row_major) uniform UPSLightProperties
{
    mat4 m_LightProjection;
    mat4 m_LightView;
    vec4 m_LightPosition;
    vec4 m_LightAmbientIntensity;
    vec4 m_LightDiffuseIntensity;
    vec4 m_LightSpecularIntensity;
};

uniform sampler2D PSTextureAlbedo;
uniform sampler2D PSTextureNormalSpecular;
uniform sampler2D PSTextureDepth;
uniform sampler2D PSTextureShadowMap;

// -----------------------------------------------------------------------------
// Input from vertex shader
// ----------------------------------------------------------------- ------------
smooth in vec2 PSTexCoord;

// -----------------------------------------------------------------------------
// Output to systembuffer
// -----------------------------------------------------------------------------
layout (location = 0) out vec4 PSOutput;

// -----------------------------------------------------------------------------
// Functions
// -----------------------------------------------------------------------------
vec3 GetViewSpacePositionFromDepth(float _Depth, vec2 _ScreenPosition, mat4 _InvertedProjectionMatrix)
{
    // -----------------------------------------------------------------------------
    // Information from:
    // http://mynameismjp.wordpress.com/2009/03/10/reconstructing-position-from-depth/
    // -----------------------------------------------------------------------------
    vec4 ScreenPosition;

    ScreenPosition.x = _ScreenPosition.x * 2.0f - 1.0f;
    ScreenPosition.y = _ScreenPosition.y * 2.0f - 1.0f;
    ScreenPosition.z = _Depth * 2.0f - 1.0f;
    ScreenPosition.w = 1.0f;

    // -----------------------------------------------------------------------------
    // Transform by the inverse projection matrix
    // -----------------------------------------------------------------------------
    vec4 VSPosition = ScreenPosition * _InvertedProjectionMatrix;

    // -----------------------------------------------------------------------------
    // Divide by w to get the view-space position
    // -----------------------------------------------------------------------------
    return (VSPosition.xyz / VSPosition.w);
}

// -----------------------------------------------------------------------------

float GetShadowAtPosition(vec3 _WSPosition)
{
    // -----------------------------------------------------------------------------
    // Set worls space coord into light projection by multiply with light
    // view and projection matrix;
    // -----------------------------------------------------------------------------
    vec4 LSPosition = vec4(_WSPosition, 1.0f) * m_LightView * m_LightProjection;

    // -----------------------------------------------------------------------------
    // Divide xyz by w to get the position in light view's clip space.
    // -----------------------------------------------------------------------------
    LSPosition.xyz /= LSPosition.w;

    // -----------------------------------------------------------------------------
    // Get uv texcoords for this position
    // -----------------------------------------------------------------------------
    vec3 ShadowCoord = LSPosition.xyz * 0.5f + 0.5f;

    // -----------------------------------------------------------------------------
    // Get final depth at this texcoord and compare it with the real
    // position z value (do a manual depth test)
    // -----------------------------------------------------------------------------
    float DepthValue = texture( PSTextureShadowMap, vec2(ShadowCoord.x, ShadowCoord.y) ).r;

    float Shadow = 1.0f;

    if (ShadowCoord.z > DepthValue)
    {
        Shadow = 0.3f;
    }

    return Shadow;
}

// -----------------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------------
void main() 
{
    // -----------------------------------------------------------------------------
    // Get informations from g-buffer
    // -----------------------------------------------------------------------------
    vec2 TexCoord = vec2(PSTexCoord.s, 1.0f - PSTexCoord.t);

    vec4  AlbedoColor      = texture(PSTextureAlbedo        , TexCoord);
    vec4  NormalSpec       = texture(PSTextureNormalSpecular, TexCoord);
    float Depth            = texture(PSTextureDepth         , TexCoord).r;
    vec3  VSPosition       = GetViewSpacePositionFromDepth(Depth, TexCoord, inverse(m_ProjectionMatrix));
    vec3  Normal           = normalize(NormalSpec.xyz);
    float SpecularExponent = NormalSpec.w;

    vec4  WSPosition = vec4(VSPosition, 1.0f) * inverse(m_CameraView);

    // -----------------------------------------------------------------------------
    // Compute lighting (Light Accumulation)
    // -----------------------------------------------------------------------------
    vec3 CameraPosition  = m_CameraPosition.xyz;
    vec3 LightPosition   = m_LightPosition.xyz;
    vec3 EyeDirection    = WSPosition.xyz - CameraPosition;
    vec3 LightDirection  = normalize(LightPosition - WSPosition.xyz);
    vec3 LightReflection = normalize(-reflect(LightDirection, Normal));

    vec4 AmbientColor  = m_LightAmbientIntensity;
    vec4 DiffuseColor  = clamp(m_LightDiffuseIntensity * max(dot(Normal, LightDirection), 0.0f), 0.0f, 1.0f);
    vec4 SpecularColor = clamp(m_LightSpecularIntensity * pow(max(dot(LightReflection, EyeDirection), 0.0f), SpecularExponent), 0.0f, 1.0f);

    float Shadow = GetShadowAtPosition(WSPosition.xyz);

    // -----------------------------------------------------------------------------
    // Final result
    // -----------------------------------------------------------------------------
    PSOutput = vec4((AlbedoColor * (AmbientColor + DiffuseColor) * Shadow).xyz, 1.0f);
}

最后我的结果是这样的: 结果总是有阴影

有人能看出我的错误吗?

部分测量结果:

  • ShadowCoord.xy 始终为 0.5、0.5

  • ShadowCoord.z 接缝为 1.0f

以下是一些变量值:

   LightProjection
    (
     1.29903805f, 0.0f,         0.0,          0.0f,
     0.0f,        1.73205066f,  0.0f,         0.0f,
     0.0f,        0.0f,        -1.00024426f, -1.0f,
     0.0f,        0.0f,        -1.00024426f,  0.0f
     );

   LightView
    (
     1.0f, 0.0f,     0.0f, 0.0f,
     0.0f, 1.0f,     0.0f, 0.0f,
     0.0f, 0.0f,     1.0f, 0.0f,
     0.0f, 0.0f, -1500.0f, 1.0f
     );

   CameraProjection
    (
     1.29903805f, 0.0f,         0.0f,         0.0f,
     0.0f,        1.73205066f,  0.0f,         0.0f,
     0.0f,        0.0f,        -1.00024426f, -1.0f,
     0.0f,        0.0f,        -1.00024426f,  0.0f
     );

   CameraView
    (
     1.0f, 0.0f,    0.0f, 0.0f,
     0.0f, 1.0f,    0.0f, 0.0f,
     0.0f, 0.0f,    1.0f, 0.0f,
     0.0f, 0.0f, -1000.0f, 1.0f
     );
4

1 回答 1

1

我可以看到的一个问题是线性深度和双曲线深度之间的差异。看起来您的“线性深度(F32)”G 缓冲区深度实际上是双曲线的,这很好,因为代码需要这个。然而,光的深度实际上是线性的,但在透视分割后会与剪辑空间深度进行比较。

只制作光缓冲区的深度双曲线 ( gl_FragCoord.z) 可能是最简单的,但更改为与眼睛空间 Z 进行比较也应该有效:

float ShadowCoordZ = -(vec4(_WSPosition, 1.0f) * m_LightView).z;

关于“ShadowCoord.xy 始终为 0.5, 0.5”的说法令人困惑。G-buffer 纹理坐标似乎有效。我真的不能用阴影来判断,但是照明方程有效吗?如果是这样,矩阵可能有问题?我还会将矩阵的逆矩阵作为制服传递,这样就不会花时间在着色器中计算它。

于 2014-11-20T10:04:35.513 回答