我對這個問題捶了很長一段時間,終于意識到我需要認真的幫助......所以基本上我想在我的項目中實現適當的陰影 im 用 Monogame 編寫。為此,我使用多個教程在HLSL中編寫了一個延遲的dhader,主要用于舊的XNA。問題是,盡管我的光照和陰影可以用作聚光燈,但我場景地板上的光線非常依賴于我的相機,正如您在圖像中看到的那樣:https://imgur.com/a/TU7y0bs我嘗試了許多不同的方法來解決這個問題:更大的DeepBias將通過大規模的彼得平移來擴大“無陰影”的半徑,并且所描述的問題根本沒有得到解決。一篇論文建議使用指數陰影貼圖,但我根本不喜歡結果,因為光線出血是難以忍受的,較小的陰影(如墻上火炬后面的陰影)將無法渲染。我將GBuffer DepthMap切換到1-z / w以獲得更高的精度,但這也沒有解決問題。我正在使用new RenderTarget2D(device,
Width, Height, false, SurfaceFormat.Vector2, DepthFormat.Depth24Stencil8)以從燈光角度存儲深度。我使用此PixelShader函數計算陰影:請注意,我想在將來將此著色器調整為點光源 - 這就是為什么我簡單地使用長度(LightPos - PixelPos)。SpotLight.fx - PixelShaderfloat4 PS(VSO input) : SV_TARGET0{ // Fancy Lighting equationsinput.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 DepthMapfloat Depth = DepthMap.Sample(SampleTypeClamp, UV).x;// Getting the PixelPosition in WorldSpacefloat4 Position = 1.0f;Position.xy = input.ScreenPosition.xy;Position.z = Depth;// Transform Position to WorldSpacePosition = 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] Spacefloat2 LightUV = 0.5f * (float2(LightScreenPos.x, -LightScreenPos.y) + 1.0f);float lightDepth = ShadowMap.Sample(SampleDot, LightUV).r;// Linear depth modelfloat 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)
1 回答

叮當貓咪
TA貢獻1776條經驗 獲得超12個贊
我終于找到了解決方案,如果有人偶然發現同樣的問題,我會在這里發布它:
我使用的教程是針對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)
- 1 回答
- 0 關注
- 95 瀏覽
添加回答
舉報
0/150
提交
取消