SC5Shout
-
Postów
2 -
Dołączył
-
Ostatnio
Typ zawartości
Profile
Fora
Kalendarz
Articles
Pliki
Posty napisane przez SC5Shout
-
-
Mam problem z cieniami dla światła punktowego. Widziałem sporo artykułów, filmików, pytań zadanych na forach związanych z tym tematem:
-
https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows
-
-
i wiele innych...
i napisałem taki (pseudo) kod
struct PointShadowMatrix { glm::mat4 viewProjection[6]; }; const glm::mat4 shadowProj = glm::perspective(Math::HALF_PI, 1.0f, 25.0f, 1.0f); const glm::vec3 lightPos = light.getPosition(); PointShadowMatrix shadowData; shadowData.viewProjection[0] = shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0)); shadowData.viewProjection[1] = shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0)); shadowData.viewProjection[2] = shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)); shadowData.viewProjection[3] = shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)); shadowData.viewProjection[4] = shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, 1.0, 0.0)); shadowData.viewProjection[5] = shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, 1.0, 0.0)); shadowConstantBuffer.AddData(shadowData); auto textureCube = TextureCube( .Width = 1024, .Height = 1024, .MipLevels = 1, .Format = DXGI_FORMAT_R24G8_TYPELESS, .BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE ); auto cubeDepthRenderTarget = CubeRenderTarget( .resource = textureCube, .FirstArraySlice = 0, .MipSlice = 0 ); auto shader = Shader(.path = "PointShadowShader.hlsl"); shader.Bind(); cubeDepthRenderTarget.Bind(); shadowConstantBuffer.Bind(); SetViewport(.w = 1024, .h = 1024); ClearDepth(cubeDepthRenderTarget, 0.0f); DrawDepth();
PointShadowShader:
struct VertexInput { float3 position : POSITION; nointerpolation float4 modelToWorld1 : I_MODEL_TO_WORLD_ONE; nointerpolation float4 modelToWorld2 : I_MODEL_TO_WORLD_TWO; nointerpolation float4 modelToWorld3 : I_MODEL_TO_WORLD_THREE; nointerpolation float4 modelToWorld4 : I_MODEL_TO_WORLD_FOUR; }; float4 VSMain(VertexInput input) : SV_POSITION { float4x4 model = float4x4(input.modelToWorld1, input.modelToWorld2, input.modelToWorld3, input.modelToWorld4); return mul(float4(input.position, 1.0f), model); } cbuffer PointShadowData : register(b4) { row_major float4x4 pointShadowViewProjection[6]; }; struct GS_OUTPUT { float4 position : SV_POSITION; float3 worldPosition : WORLD_POSITION; uint RTIndex : SV_RenderTargetArrayIndex; }; [maxvertexcount(18)] void GSMain(triangle float4 position[3] : SV_POSITION, inout TriangleStream<GS_OUTPUT> OutStream) { for (uint face = 0; face < 6; ++face) { GS_OUTPUT output; output.RTIndex = face; for (uint v = 0; v < 3; ++v) { output.worldPosition = position[v].xyz; output.position = mul(position[v], pointShadowViewProjection[face]); OutStream.Append(output); } OutStream.RestartStrip(); } } cbuffer LightInfo : register(b1) { float3 lightPos; }; struct PixelInput { float4 position : SV_POSITION; float3 worldPosition : WORLD_POSITION; }; float PSMain(PixelInput input) : SV_DEPTH { //próbowałem input.position zamiast input.worldPosition, efekt ten sam //próbowałem rozwiązania z artykułu NVidi - obliczenie kwadratu dystansu //próbowałem zwykłego dystansu bez dzielenia przez far plane //nic nie pomogło return length(input.worldPosition - lightPos) / 25.0f; }
mapa cieni wygląda nawet dobrze:
ale jak odpale apke to cienie już niekoniecznie:
fioletowa kula to "wizualizator" światła
kolejny screenshot, tym razem ze światłem za ścianą:
funkcja do samplowania tej mapy:
float PointLightShadows(float3 worldPosition, float3 lightPosition) { float3 fragToLight = worldPosition - lightPosition; float distance = length(fragToLight); return t_pointShadowMap.SampleCmpLevelZero(g_shadowBorder, float4(fragToLight, lightIndex), distance / 25.0f); }
Jak już wspominałem wcześniej, wchodziłem w wiele linków na ten temat i nie wiem, nic nie pomagało.
Bufor głębi jest czyszczony na `0`, `depthFunc` jest ustawione na `GREATER`.
Myślałem, że problem może leżeć np. w pozycji światła, ale sprawdziłem i w obu tych przypadkach (shadow pass, color pass), pozycja jest ta sama.
Gdzie może leżeć błąd? Jak go naprawić? Jakie rzeczy powinienem wziąć pod uwagę debugując ten problem?
Próbowałem jeszcze obliczyć `lightPosition - worldPosition` zamiast `worldPosition - lightPosition`, to też nie naprawia cieni. Zmieniałem wartości `up` w funkcji `lookUp` na różne, np. zamiast `glm::vec3(0.0f, 1.0f, 0.0f)` na `glm::vec3(0.0f, -1.0f, 0.0f)`. Negowałem po kolei `x`, `y`, `z` w `fragToLight`, zmieniałem z `row_major` na `column_major`, zmieniałem kolejności mnożenia, używałem funkcji `glm` z postfixami `RH` i `LH`.
-
Cienie dla światła punktowego nie działają prawidłowo. Jak mogę to zdebugować?
w C++
Napisano
Wyczyściłem bufor głębi na
1.0f
, ustawiłemdepthFunc
naLESS
i samplerComparisonFunction
naLESS
i zaczęło działać. Teraz pytanie dlaczego?