Browse Source

Further OpenGL ES shadow optimization.

Lasse Öörni 13 years ago
parent
commit
d4b0f662e2

+ 2 - 2
Bin/CoreData/Shaders/GLSL/DeferredLight.frag

@@ -64,13 +64,13 @@ void main()
     #ifdef SHADOW
     #ifdef SHADOW
         #if defined(DIRLIGHT)
         #if defined(DIRLIGHT)
             vec4 shadowPos = GetDirShadowPosDeferred(cLightMatricesPS, projWorldPos, depth);
             vec4 shadowPos = GetDirShadowPosDeferred(cLightMatricesPS, projWorldPos, depth);
-            diff *= min(GetShadow(shadowPos) + GetShadowFade(depth), 1.0);
+            diff *= GetDirShadow(shadowPos, depth);
         #elif defined(SPOTLIGHT)
         #elif defined(SPOTLIGHT)
             vec4 shadowPos = cLightMatricesPS[1] * projWorldPos;
             vec4 shadowPos = cLightMatricesPS[1] * projWorldPos;
             diff *= GetShadow(shadowPos);
             diff *= GetShadow(shadowPos);
         #else
         #else
             vec3 shadowPos = worldPos - cLightPosPS.xyz;
             vec3 shadowPos = worldPos - cLightPosPS.xyz;
-            diff *= GetCubeShadow(shadowPos);
+            diff *= GetPointShadow(shadowPos);
         #endif
         #endif
     #endif
     #endif
 
 

+ 18 - 11
Bin/CoreData/Shaders/GLSL/Lighting.frag

@@ -54,33 +54,28 @@ float GetShadow(vec4 shadowPos)
                 shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r,
                 shadow2DProj(sShadowMap, vec4(shadowPos.x, shadowPos.y + offsets.y, shadowPos.zw)).r,
                 shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r
                 shadow2DProj(sShadowMap, vec4(shadowPos.xy + offsets.xy, shadowPos.zw)).r
             );
             );
-            return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x));
-        #else
+            return cShadowIntensity.y + dot(inLight, vec4(cShadowIntensity.x));
+        #else
             float compare = shadowPos.z / shadowPos.w;
             float compare = shadowPos.z / shadowPos.w;
             vec2 inLight = vec2(
             vec2 inLight = vec2(
                 texture2DProj(sShadowMap, shadowPos).r > compare,
                 texture2DProj(sShadowMap, shadowPos).r > compare,
                 texture2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r > compare
                 texture2DProj(sShadowMap, vec4(shadowPos.x + offsets.x, shadowPos.yzw)).r > compare
             );
             );
-            return cShadowIntensity.y + dot(inLight, vec2(cShadowIntensity.x));
+            return 0.5 * (inLight.x + inLight.y);
         #endif
         #endif
     #else
     #else
         // Take one sample
         // Take one sample
         #ifndef GL_ES
         #ifndef GL_ES
             float inLight = shadow2DProj(sShadowMap, shadowPos).r;
             float inLight = shadow2DProj(sShadowMap, shadowPos).r;
+            return cShadowIntensity.y + cShadowIntensity.x * inLight;
         #else
         #else
-            float inLight = texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z ? 1.0 : 0.0;
+            return texture2DProj(sShadowMap, shadowPos).r * shadowPos.w > shadowPos.z ? 1.0 : 0.0;
         #endif
         #endif
-        return cShadowIntensity.y + cShadowIntensity.x * inLight;
     #endif
     #endif
 }
 }
 
 
-float GetShadowFade(float depth)
-{
-    return clamp((depth - cShadowDepthFade.z) * cShadowDepthFade.w, 0.0, 1.0);
-}
-
 #ifdef POINTLIGHT
 #ifdef POINTLIGHT
-float GetCubeShadow(vec3 lightVec)
+float GetPointShadow(vec3 lightVec)
 {
 {
     vec3 axis = textureCube(sFaceSelectCubeMap, lightVec).rgb;
     vec3 axis = textureCube(sFaceSelectCubeMap, lightVec).rgb;
     float depth = abs(dot(lightVec, axis));
     float depth = abs(dot(lightVec, axis));
@@ -102,6 +97,18 @@ float GetCubeShadow(vec3 lightVec)
 #endif
 #endif
 
 
 #ifdef DIRLIGHT
 #ifdef DIRLIGHT
+float GetDirShadow(vec4 shadowPos, float depth)
+{
+    #ifndef GL_ES
+        return min(GetShadow(shadowPos) + clamp((depth - cShadowDepthFade.z) * cShadowDepthFade.w, 0.0, 1.0), 1.0);
+    #else
+        if (depth < cShadowDepthFade.z)
+            return GetShadow(shadowPos);
+        else
+            return 1.0;
+    #endif
+}
+
 vec4 GetDirShadowPos(const vec4 shadowPos[4], float depth)
 vec4 GetDirShadowPos(const vec4 shadowPos[4], float depth)
 {
 {
     if (depth < cShadowSplits.x)
     if (depth < cShadowSplits.x)

+ 2 - 2
Bin/CoreData/Shaders/GLSL/LitSolid.frag

@@ -86,11 +86,11 @@ void main()
         #ifdef SHADOW
         #ifdef SHADOW
             #if defined(DIRLIGHT)
             #if defined(DIRLIGHT)
                 vec4 shadowPos = GetDirShadowPos(vShadowPos, vLightVec.w);
                 vec4 shadowPos = GetDirShadowPos(vShadowPos, vLightVec.w);
-                diff *= min(GetShadow(shadowPos) + GetShadowFade(vLightVec.w), 1.0);
+                diff *= GetDirShadow(shadowPos, vLightVec.w);
             #elif defined(SPOTLIGHT)
             #elif defined(SPOTLIGHT)
                 diff *= GetShadow(vShadowPos);
                 diff *= GetShadow(vShadowPos);
             #else
             #else
-                diff *= GetCubeShadow(vShadowPos);
+                diff *= GetPointShadow(vShadowPos);
             #endif
             #endif
         #endif
         #endif
     
     

+ 2 - 2
Bin/CoreData/Shaders/GLSL/PrepassLight.frag

@@ -63,13 +63,13 @@ void main()
     #ifdef SHADOW
     #ifdef SHADOW
         #if defined(DIRLIGHT)
         #if defined(DIRLIGHT)
             vec4 shadowPos = GetDirShadowPosDeferred(cLightMatricesPS, projWorldPos, depth);
             vec4 shadowPos = GetDirShadowPosDeferred(cLightMatricesPS, projWorldPos, depth);
-            diff *= min(GetShadow(shadowPos) + GetShadowFade(depth), 1.0);
+            diff *= GetDirShadow(shadowPos, depth);
         #elif defined(SPOTLIGHT)
         #elif defined(SPOTLIGHT)
             vec4 shadowPos = cLightMatricesPS[1] * projWorldPos;
             vec4 shadowPos = cLightMatricesPS[1] * projWorldPos;
             diff *= GetShadow(shadowPos);
             diff *= GetShadow(shadowPos);
         #else
         #else
             vec3 shadowPos = worldPos - cLightPosPS.xyz;
             vec3 shadowPos = worldPos - cLightPosPS.xyz;
-            diff *= GetCubeShadow(shadowPos);
+            diff *= GetPointShadow(shadowPos);
         #endif
         #endif
     #endif
     #endif
 
 

+ 9 - 2
Engine/Graphics/Batch.cpp

@@ -130,7 +130,8 @@ void CalculateShadowMatrix(Matrix4& dest, LightBatchQueue* queue, unsigned split
     if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
     if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
     {
     {
         offset.x_ -= 0.5f / width;
         offset.x_ -= 0.5f / width;
-        #if !defined(ANDROID) && !defined(IOS)
+        // Use only 2 samples offset in X direction on OpenGL ES for better performance
+        #ifndef GL_ES_VERSION_2_0
         offset.y_ -= 0.5f / height;
         offset.y_ -= 0.5f / height;
         #endif
         #endif
     }
     }
@@ -551,7 +552,12 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransfo
                 float fadeEnd = shadowRange / viewFarClip;
                 float fadeEnd = shadowRange / viewFarClip;
                 float fadeRange = fadeEnd - fadeStart;
                 float fadeRange = fadeEnd - fadeStart;
                 
                 
+                // Do not use last cascade fade on OpenGL ES for better performance, rather compare directly against the fade end
+                #ifndef GL_ES_VERSION_2_0
                 graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
                 graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
+                #else
+                graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeEnd, 1.0f / fadeRange));
+                #endif
             }
             }
             
             
             {
             {
@@ -561,7 +567,8 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransfo
                 if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
                 if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
                     intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
                     intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
                 float pcfValues = (1.0f - intensity);
                 float pcfValues = (1.0f - intensity);
-                #if !defined(ANDROID) && !defined(IOS)
+                // Use only 2 samples offset in X direction on OpenGL ES for better performance
+                #ifndef GL_ES_VERSION_2_0
                 float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f;
                 float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f;
                 #else
                 #else
                 float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 2.0f : 1.0f;
                 float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 2.0f : 1.0f;