(Monogame/HLSL)阴影映射的问题 - 阴影取决于相机位置

我对这个问题捶了很长一段时间,终于意识到我需要认真的帮助......

所以基本上我想在我的项目中实现适当的阴影 im 用 Monogame 编写。为此,我使用多个教程在HLSL中编写了一个延迟的dhader,主要用于旧的XNA。问题是,尽管我的光照和阴影可以用作聚光灯,但我场景地板上的光线非常依赖于我的相机,正如您在图像中看到的那样:https://imgur.com/a/TU7y0bs

我尝试了许多不同的方法来解决这个问题:

  1. 更大的DeepBias将通过大规模的彼得平移来扩大“无阴影”的半径,并且所描述的问题根本没有得到解决。

  2. 一篇论文建议使用指数阴影贴图,但我根本不喜欢结果,因为光线出血是难以忍受的,较小的阴影(如墙上火炬后面的阴影)将无法渲染。

  3. 我将GBuffer DepthMap切换到1-z / w以获得更高的精度,但这也没有解决问题。

我正在使用

new RenderTarget2D(device,
                Width, Height, false, SurfaceFormat.Vector2, DepthFormat.Depth24Stencil8)

以从灯光角度存储深度。

我使用此PixelShader函数计算阴影:请注意,我想在将来将此着色器调整为点光源 - 这就是为什么我简单地使用长度(LightPos - PixelPos)。SpotLight.fx - PixelShader

float4 PS(VSO input) : SV_TARGET0

{


    // Fancy Lighting equations


input.ScreenPosition.xy /= input.ScreenPosition.w;

float2 UV = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - float2(1.0f / GBufferTextureSize.xy);


// Sample Depth from DepthMap

float Depth = DepthMap.Sample(SampleTypeClamp, UV).x;


// Getting the PixelPosition in WorldSpace

float4 Position = 1.0f;

Position.xy = input.ScreenPosition.xy;

Position.z = Depth;


// Transform Position to WorldSpace

Position = mul(Position, InverseViewProjection);

Position /= Position.w;


float4 LightScreenPos = mul(Position, LightViewProjection);

LightScreenPos /= LightScreenPos.w;



// Calculate Projected UV from Light POV -> ScreenPos is in [-1;1] Space

float2 LightUV = 0.5f * (float2(LightScreenPos.x, -LightScreenPos.y) + 1.0f);

float lightDepth = ShadowMap.Sample(SampleDot, LightUV).r;


// Linear depth model

float closestDepth = lightDepth * LightFarplane; // Depth is stored in [0, 1]; bring it to [0, farplane]

float currentDepth = length(LightPosition.xyz - Position.xyz) - DepthBias;

ShadowFactor = step(currentDepth, closestDepth); // closestDepth > currentDepth -> Occluded, Shadow.


float4 phong = Phong(...); 

return ShadowFactor * phong;

}

LightViewProjection只是InverseViewProjection是Phong()是一个函数,我调用来完成照明光光DepthMap简单地存储light.View * light.ProjectionMatrix.Invert(camera.View * Camera.Projection)length(lightPos - Position)


千万里不及你
浏览 62回答 1
1回答

叮当猫咪

我终于找到了解决方案,如果有人偶然发现同样的问题,我会在这里发布它:我使用的教程是针对XNA / DX9的。但是,由于目标是DX10 +,因此需要做一个微小的改变:在XNA / DX9中,UV坐标与实际像素不对齐,需要对齐。这就是 in 的目的。这在DX10及以上版本中是不需要的,并且会导致我遇到的问题。- float2(1.0f / GBufferTextureSize.xy);float2 UV = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - float2(1.0f / GBufferTextureSize.xy);溶液:全屏四边形的 UV 坐标:对于 XNA / DX9:input.ScreenPosition.xy /= input.ScreenPosition.w; float2 UV = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - float2(1.0f / GBufferTextureSize.xy);适用于单游戏 / DX10+input.ScreenPosition.xy /= input.ScreenPosition.w; float2 UV = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1)
打开App,查看更多内容
随时随地看视频慕课网APP