现在我敲我的头,在这个问题相当长的一段时间,终于意识到,我需要认真的帮助......
所以基本上我想要实现正确的阴影到Monogame我的项目我写。为此,我使用多个教程,主要为老XNA写了递延dhader在HLSL。问题是,尽管对我的聚光灯照明和阴影的工作,在我的场景的地板上的光线非常依赖我的相机,因为你可以在图像中看到:https://imgur.com/a/TU7y0bs
我尝试了很多不同的东西来解决这个问题:
我使用的是
new RenderTarget2D(device,
Width, Height, false, SurfaceFormat.Vector2, DepthFormat.Depth24Stencil8)
以存储从灯立体深度。
我计算使用此功能PixelShader暗影:请注意,我想这个shader适应在将来点光 - 这就是为什么IM简单地使用长度(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只是light.View * light.Projection
InverseViewProjection是Matrix.Invert(camera.View * Camera.Projection)
蓬()是一个函数调用我以完成灯光的lightDepthMap简单地存储length(lightPos - Position)
我想在去能够适应代码点光源,以及图片显示,神器。
难道这是与我检索屏幕空间世界上的地位和我的深度得到了一个低分辨率的方式有问题?
帮助深表感谢!
---更新---
我改变了我的灯光着色器来显示存储在阴影贴图的距离和在Pixelshader当场计算出的距离之间的差异:
float4 PixelShaderFct(...) : SV_TARGET0
{
// Get Depth from Texture
float4 Position = 1.0f;
Position.xy = input.ScreenPosition.xy;
Position.z = Depth;
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 LUV = 0.5f * (float2(LightScreenPos.x, -LightScreenPos.y) + 1.0f);
float lightZ = ShadowMap.Sample(SampleDot, LUV).r;
float Attenuation = AttenuationMap.Sample(SampleType, LUV).r;
float ShadowFactor = 1;
// Linear depth model; lightZ stores (LightPos - Pos)/LightFarPlane
float closestDepth = lightZ * LightFarPlane;
float currentDepth = length(LightPosition.xyz - Position.xyz) -DepthBias;
return (closestDepth - currentDepth);
}
正如我基本上输出长度 - (长度 - 偏差)人会期望有一个图像的“DepthBias”作为自己的颜色。但是,这并不是我在这里得到的结果:
在此基础上,我假设,要么我有精密的问题(我觉得这不可思议,因为IM与近和farplanes [0.1,50]工作),或什么是错与IM的方式恢复从我的深度图给定像素的worldPosition。
我终于找到了解决办法,如果有人在同样的问题绊倒我在这里张贴:
我使用的教程是为XNA / DX9。但是,作为即时通讯打靶DX10 +一个微小的变化需要做的事情:
在XNA / DX9的UV坐标与实际像素对齐,需要对齐。这就是- float2(1.0f / GBufferTextureSize.xy);
在float2 UV = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - float2(1.0f / GBufferTextureSize.xy);
用的。这是没有必要的DX10及以上,并会导致问题,我有。
解:
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)