2
0
Эх сурвалжийг харах

Even more optimization of the shadow mapping shader. In 4 sample mode, pre-adjust the shadow map coordinates on the CPU.

Lasse Öörni 14 жил өмнө
parent
commit
1421058c9f

+ 18 - 5
Engine/Graphics/Batch.cpp

@@ -239,6 +239,13 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
                         0.5f * (float)(viewport.bottom_ - viewport.top_) / height
                     );
                     
+                    // If using 4 shadow samples, offset the position diagonally by half pixel
+                    if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
+                    {
+                        offset.x_ -= 0.5f / width;
+                        offset.y_ -= 0.5f / height;
+                    }
+                    
                     #ifdef USE_OPENGL
                     offset.x_ += scale.x_;
                     offset.y_ += scale.y_;
@@ -246,8 +253,8 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
                     texAdjust.SetTranslation(Vector3(offset.x_, offset.y_, 0.5f));
                     texAdjust.SetScale(Vector3(scale.x_, scale.y_, 0.5f));
                     #else
-                    offset.x_ += scale.x_ + 0.5f / (float)shadowMap->GetWidth();
-                    offset.y_ += scale.y_ + 0.5f / (float)shadowMap->GetHeight();
+                    offset.x_ += scale.x_ + 0.5f / width;
+                    offset.y_ += scale.y_ + 0.5f / height;
                     scale.y_ = -scale.y_;
                     texAdjust.SetTranslation(Vector3(offset.x_, offset.y_, 0.0f));
                     texAdjust.SetScale(Vector3(scale.x_, scale.y_, 1.0f));
@@ -261,9 +268,9 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
             
             if (graphics->NeedParameterUpdate(PSP_SAMPLEOFFSETS, shadowMap))
             {
-                float xOffset = 1.0f / (float)shadowMap->GetWidth();
-                float yOffset = 1.0f / (float)shadowMap->GetHeight();
-                graphics->SetShaderParameter(PSP_SAMPLEOFFSETS, Vector4(-0.5f * xOffset, -0.5f * yOffset, xOffset, yOffset));
+                float addX = 1.0f / (float)shadowMap->GetWidth();
+                float addY = 1.0f / (float)shadowMap->GetHeight();
+                graphics->SetShaderParameter(PSP_SAMPLEOFFSETS, Vector4(addX, addY, 0.0f, 0.0f));
             }
             
             if (graphics->NeedParameterUpdate(PSP_SHADOWCUBEADJUST, light))
@@ -283,6 +290,12 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, const HashMap<String
                     float addX = 2.5f / width;
                     float addY = 2.5f / height;
                 #endif
+                // If using 4 shadow samples, offset the position diagonally by half pixel
+                if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
+                {
+                    addX -= 0.5f / width;
+                    addY -= 0.5f / height;
+                }
                 graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY));
             }
             

+ 2 - 0
Engine/Graphics/Renderer.cpp

@@ -350,6 +350,8 @@ void Renderer::SetShadowQuality(int quality)
     quality &= SHADOWQUALITY_HIGH_24BIT;
     if (!graphics_->GetHiresShadowSupport())
         quality &= SHADOWQUALITY_HIGH_16BIT;
+    if (graphics_->GetFallback())
+        quality = SHADOWQUALITY_LOW_16BIT;
     
     if (quality != shadowQuality_)
     {

+ 5 - 6
SourceAssets/GLSLShaders/Lighting.frag

@@ -33,16 +33,15 @@ float GetShadow(vec4 shadowPos)
     #ifndef LQSHADOW
         // Take four samples and average them
         #ifndef POINTLIGHT
-            float4 offsets = cSampleOffsets * shadowPos.w;
+            vec2 offsets = cSampleOffsets * shadowPos.w;
         #else
-            float4 offsets = cSampleOffsets;
+            vec2 offsets = cSampleOffsets;
         #endif
-        shadowPos.xy += offsets.xy;
         vec4 inLight = vec4(
             shadow2DProj(sShadowMap, shadowPos).r,
-            shadow2DProj(sShadowMap, vec4(shadowPos.x + offsets.z, shadowPos.yzw)).r,
-            shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.w, shadowPos.zw)).r,
-            shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.zw, shadowPos.zw)).r
+            shadow2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r,
+            shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r,
+            shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r
         );
         return cShadowIntensity.z + dot(inLight, vec4(cShadowIntensity.y));
     #else

+ 1 - 1
SourceAssets/GLSLShaders/Uniforms.frag

@@ -5,7 +5,7 @@ uniform vec4 cLightColor;
 uniform vec4 cMatDiffColor;
 uniform vec3 cMatEmissiveColor;
 uniform vec2 cMatSpecProperties;
-uniform vec4 cSampleOffsets;
+uniform vec2 cSampleOffsets;
 uniform vec4 cShadowCubeAdjust;
 uniform vec2 cShadowCubeProj;
 uniform vec4 cShadowIntensity;

+ 5 - 6
SourceAssets/HLSLShaders/Lighting.hlsl

@@ -36,16 +36,15 @@ float GetShadow(float4 shadowPos)
         #ifndef LQSHADOW
             // Take four samples and average them
             #ifndef POINTLIGHT
-                float4 offsets = cSampleOffsets * shadowPos.w;
+                float2 offsets = cSampleOffsets * shadowPos.w;
             #else
-                float4 offsets = cSampleOffsets;
+                float2 offsets = cSampleOffsets;
             #endif
-            shadowPos.xy += offsets.xy;
             float4 inLight = float4(
                 tex2Dproj(sShadowMap, shadowPos).r,
-                tex2Dproj(sShadowMap, float4(shadowPos.x + offsets.z, shadowPos.yzw)).r,
-                tex2Dproj(sShadowMap, float4(shadowPos.x, shadowPos.y + offsets.w, shadowPos.zw)).r,
-                tex2Dproj(sShadowMap, float4(shadowPos.xy + offsets.zw, shadowPos.zw)).r
+                tex2Dproj(sShadowMap, float4(shadowPos.x + offsets.x, shadowPos.yzw)).r,
+                tex2Dproj(sShadowMap, float4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r,
+                tex2Dproj(sShadowMap, float4(shadowPos.xy + offsets.xy, shadowPos.zw)).r
             );
             #ifdef HWSHADOW
                 return cShadowIntensity.z + dot(inLight, cShadowIntensity.y);

+ 1 - 1
SourceAssets/HLSLShaders/Uniforms.hlsl

@@ -24,7 +24,7 @@ uniform float4 cLightColor : register(C3);
 uniform float4 cMatDiffColor : register(C4);
 uniform float3 cMatEmissiveColor : register(C5);
 uniform float2 cMatSpecProperties : register(C6);
-uniform float4 cSampleOffsets : register(C7);
+uniform float2 cSampleOffsets : register(C7);
 uniform float4 cShadowCubeAdjust : register(C8);
 uniform float2 cShadowCubeProj : register(C9);
 uniform float2 cShadowFade : register(C10);