Browse Source

Switch forward light calculations back to world space instead of tangent space to avoid light attenuation bugs when TBN matrix is not orthogonal. Shader code becomes simpler and more similar between forward and deferred, and number of vertex shader variations is reduced, but disadvantage is a more complex pixel shader which requires disabling expensive features on SM2.0 to avoid exceeding the arithmetic instruction limit. Fix cube mapped point light displaying the cube map upside down. Closes #276.

Lasse Öörni 11 years ago
parent
commit
c3425334a3
33 changed files with 517 additions and 817 deletions
  1. 1 1
      Bin/CoreData/Shaders/GLSL/DeferredLight.glsl
  2. 37 41
      Bin/CoreData/Shaders/GLSL/LitParticle.glsl
  3. 52 113
      Bin/CoreData/Shaders/GLSL/LitSolid.glsl
  4. 1 1
      Bin/CoreData/Shaders/GLSL/PrepassLight.glsl
  5. 52 62
      Bin/CoreData/Shaders/GLSL/TerrainBlend.glsl
  6. 1 0
      Bin/CoreData/Shaders/GLSL/Uniforms.glsl
  7. 8 13
      Bin/CoreData/Shaders/GLSL/Unlit.glsl
  8. 37 55
      Bin/CoreData/Shaders/GLSL/Vegetation.glsl
  9. 2 9
      Bin/CoreData/Shaders/HLSL/DeferredLight.hlsl
  10. 31 12
      Bin/CoreData/Shaders/HLSL/Lighting.hlsl
  11. 44 44
      Bin/CoreData/Shaders/HLSL/LitParticle.hlsl
  12. 59 126
      Bin/CoreData/Shaders/HLSL/LitSolid.hlsl
  13. 1 1
      Bin/CoreData/Shaders/HLSL/PrepassLight.hlsl
  14. 1 1
      Bin/CoreData/Shaders/HLSL/Samplers.hlsl
  15. 46 78
      Bin/CoreData/Shaders/HLSL/TerrainBlend.hlsl
  16. 1 0
      Bin/CoreData/Shaders/HLSL/Uniforms.hlsl
  17. 7 15
      Bin/CoreData/Shaders/HLSL/Unlit.hlsl
  18. 39 52
      Bin/CoreData/Shaders/HLSL/Vegetation.hlsl
  19. 1 1
      Bin/CoreData/Techniques/DiffNormalEnvCube.xml
  20. 1 1
      Bin/CoreData/Techniques/DiffNormalPackedEnvCube.xml
  21. 6 7
      Bin/Data/Scripts/Editor.as
  22. 11 5
      Docs/Reference.dox
  23. 1 0
      Source/Engine/Graphics/Batch.cpp
  24. 1 0
      Source/Engine/Graphics/GraphicsDefs.cpp
  25. 1 0
      Source/Engine/Graphics/GraphicsDefs.h
  26. 28 0
      Source/Engine/Graphics/Light.cpp
  27. 2 0
      Source/Engine/Graphics/Light.h
  28. 27 56
      Source/Engine/Graphics/Renderer.cpp
  29. 0 12
      Source/Engine/Graphics/Renderer.h
  30. 15 9
      Source/Engine/Graphics/View.cpp
  31. 2 0
      Source/Engine/LuaScript/pkgs/Graphics/Light.pkg
  32. 0 100
      Source/Engine/LuaScript/pkgs/Graphics/Renderer.pkg
  33. 1 2
      Source/Engine/Script/GraphicsAPI.cpp

+ 1 - 1
Bin/CoreData/Shaders/GLSL/DeferredLight.glsl

@@ -80,7 +80,7 @@ void PS()
         lightColor = spotPos.w > 0.0 ? texture2DProj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : vec3(0.0);
         lightColor = spotPos.w > 0.0 ? texture2DProj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : vec3(0.0);
     #elif defined(CUBEMASK)
     #elif defined(CUBEMASK)
         mat3 lightVecRot = mat3(cLightMatricesPS[0][0].xyz, cLightMatricesPS[0][1].xyz, cLightMatricesPS[0][2].xyz);
         mat3 lightVecRot = mat3(cLightMatricesPS[0][0].xyz, cLightMatricesPS[0][1].xyz, cLightMatricesPS[0][2].xyz);
-        lightColor = textureCube(sLightCubeMap, lightVecRot * lightVec).rgb * cLightColor.rgb;
+        lightColor = textureCube(sLightCubeMap, lightVecRot * -lightVec).rgb * cLightColor.rgb;
     #else
     #else
         lightColor = cLightColor.rgb;
         lightColor = cLightColor.rgb;
     #endif
     #endif

+ 37 - 41
Bin/CoreData/Shaders/GLSL/LitParticle.glsl

@@ -5,14 +5,14 @@
 #include "Fog.glsl"
 #include "Fog.glsl"
 
 
 varying vec2 vTexCoord;
 varying vec2 vTexCoord;
-#ifdef HEIGHTFOG
-    varying vec3 vWorldPos;
-#endif
+varying vec4 vWorldPos;
 #ifdef VERTEXCOLOR
 #ifdef VERTEXCOLOR
     varying vec4 vColor;
     varying vec4 vColor;
 #endif
 #endif
 #ifdef PERPIXEL
 #ifdef PERPIXEL
-    varying vec4 vLightVec;
+    #ifdef SHADOW
+        varying vec4 vShadowPos[NUMCASCADES];
+    #endif
     #ifdef SPOTLIGHT
     #ifdef SPOTLIGHT
         varying vec4 vSpotPos;
         varying vec4 vSpotPos;
     #endif
     #endif
@@ -20,7 +20,7 @@ varying vec2 vTexCoord;
         varying vec3 vCubeMaskVec;
         varying vec3 vCubeMaskVec;
     #endif
     #endif
 #else
 #else
-    varying vec4 vVertexLight;
+    varying vec3 vVertexLight;
 #endif
 #endif
 
 
 void VS()
 void VS()
@@ -29,10 +29,7 @@ void VS()
     vec3 worldPos = GetWorldPos(modelMatrix);
     vec3 worldPos = GetWorldPos(modelMatrix);
     gl_Position = GetClipPos(worldPos);
     gl_Position = GetClipPos(worldPos);
     vTexCoord = GetTexCoord(iTexCoord);
     vTexCoord = GetTexCoord(iTexCoord);
-    
-    #ifdef HEIGHTFOG
-        vWorldPos = worldPos;
-    #endif
+    vWorldPos = vec4(worldPos, GetDepth(gl_Position));
 
 
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         vColor = iColor;
         vColor = iColor;
@@ -41,28 +38,28 @@ void VS()
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         vec4 projWorldPos = vec4(worldPos, 1.0);
         vec4 projWorldPos = vec4(worldPos, 1.0);
-    
-        #ifdef DIRLIGHT
-            vLightVec = vec4(cLightDir, GetDepth(gl_Position));
-        #else
-            vLightVec = vec4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(gl_Position));
+
+        #ifdef SHADOW
+            // Shadow projection: transform from world space to shadow space
+            for (int i = 0; i < NUMCASCADES; i++)
+                vShadowPos[i] = GetShadowPos(i, projWorldPos);
         #endif
         #endif
-    
+
         #ifdef SPOTLIGHT
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
             // Spotlight projection: transform from world space to projector texture coordinates
             vSpotPos = cLightMatrices[0] * projWorldPos;
             vSpotPos = cLightMatrices[0] * projWorldPos;
         #endif
         #endif
     
     
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * vLightVec.xyz;
+            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        vVertexLight = vec4(GetAmbient(GetZonePos(worldPos)), GetDepth(gl_Position));
+        vVertexLight = GetAmbient(GetZonePos(worldPos));
 
 
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                vVertexLight.rgb += GetVertexLightVolumetric(i, worldPos) * cVertexLights[i * 3].rgb;
+                vVertexLight += GetVertexLightVolumetric(i, worldPos) * cVertexLights[i * 3].rgb;
         #endif
         #endif
     #endif
     #endif
 }
 }
@@ -85,14 +82,31 @@ void PS()
         diffColor *= vColor;
         diffColor *= vColor;
     #endif
     #endif
 
 
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(vWorldPos.w);
+    #endif
+
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         vec3 lightColor;
         vec3 lightColor;
+        vec3 lightDir;
         vec3 finalColor;
         vec3 finalColor;
         float diff;
         float diff;
-    
-        diff = GetDiffuseVolumetric(vLightVec.xyz);
 
 
+        #ifdef DIRLIGHT
+            diff = GetDiffuseVolumetric(cLightDirPS);
+        #else
+            vec3 lightVec = (cLightPosPS.xyz - vWorldPos.xyz) * cLightPosPS.w;
+            diff = GetDiffuseVolumetric(lightVec);
+        #endif
+
+        #ifdef SHADOW
+            diff *= GetShadow(vShadowPos, vWorldPos.w);
+        #endif
+    
         #if defined(SPOTLIGHT)
         #if defined(SPOTLIGHT)
             lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0);
             lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0);
         #elif defined(CUBEMASK)
         #elif defined(CUBEMASK)
@@ -100,30 +114,12 @@ void PS()
         #else
         #else
             lightColor = cLightColor.rgb;
             lightColor = cLightColor.rgb;
         #endif
         #endif
-    
-        finalColor = diff * lightColor * diffColor.rgb;
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vLightVec.w, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vLightVec.w);
-        #endif
-        
-        #ifdef AMBIENT
-            finalColor += cAmbientColor * diffColor.rgb;
-            gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
-        #else
-            gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
-        #endif
+        finalColor = diff * lightColor * diffColor.rgb;
+        gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        vec3 finalColor = vVertexLight.rgb * diffColor.rgb;
-        
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vVertexLight.a, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vVertexLight.a);
-        #endif
+        vec3 finalColor = vVertexLight * diffColor.rgb;
 
 
         gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
         gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
     #endif
     #endif

+ 52 - 113
Bin/CoreData/Shaders/GLSL/LitSolid.glsl

@@ -5,18 +5,15 @@
 #include "Lighting.glsl"
 #include "Lighting.glsl"
 #include "Fog.glsl"
 #include "Fog.glsl"
 
 
-varying vec2 vTexCoord;
-#ifdef HEIGHTFOG
-    varying vec3 vWorldPos;
+#ifdef NORMALMAP
+    varying vec4 vTexCoord;
+    varying vec4 vTangent;
+#else
+    varying vec2 vTexCoord;
 #endif
 #endif
+varying vec3 vNormal;
+varying vec4 vWorldPos;
 #ifdef PERPIXEL
 #ifdef PERPIXEL
-    varying vec4 vLightVec;
-    #ifdef SPECULAR
-        varying vec3 vEyeVec;
-    #endif
-    #ifndef NORMALMAP
-        varying vec3 vNormal;
-    #endif
     #ifdef SHADOW
     #ifdef SHADOW
         varying vec4 vShadowPos[NUMCASCADES];
         varying vec4 vShadowPos[NUMCASCADES];
     #endif
     #endif
@@ -27,12 +24,7 @@ varying vec2 vTexCoord;
         varying vec3 vCubeMaskVec;
         varying vec3 vCubeMaskVec;
     #endif
     #endif
 #else
 #else
-    varying vec4 vVertexLight;
-    varying vec3 vNormal;
-    #ifdef NORMALMAP
-        varying vec3 vTangent;
-        varying vec3 vBitangent;
-    #endif
+    varying vec3 vVertexLight;
     varying vec4 vScreenPos;
     varying vec4 vScreenPos;
     #ifdef ENVCUBEMAP
     #ifdef ENVCUBEMAP
         varying vec3 vReflectionVec;
         varying vec3 vReflectionVec;
@@ -47,24 +39,18 @@ void VS()
     mat4 modelMatrix = iModelMatrix;
     mat4 modelMatrix = iModelMatrix;
     vec3 worldPos = GetWorldPos(modelMatrix);
     vec3 worldPos = GetWorldPos(modelMatrix);
     gl_Position = GetClipPos(worldPos);
     gl_Position = GetClipPos(worldPos);
-    vTexCoord = GetTexCoord(iTexCoord);
-    
-    #ifdef HEIGHTFOG
-        vWorldPos = worldPos;
-    #endif
-
-    #if defined(PERPIXEL) && defined(NORMALMAP)
-        vec3 vNormal;
-        vec3 vTangent;
-        vec3 vBitangent;
-    #endif
-
     vNormal = GetWorldNormal(modelMatrix);
     vNormal = GetWorldNormal(modelMatrix);
+    vWorldPos = vec4(worldPos, GetDepth(gl_Position));
+
     #ifdef NORMALMAP
     #ifdef NORMALMAP
-        vTangent = GetWorldTangent(modelMatrix);
-        vBitangent = cross(vTangent, vNormal) * iTangent.w;
+        vec3 tangent = GetWorldTangent(modelMatrix);
+        vec3 bitangent = cross(tangent, vNormal) * iTangent.w;
+        vTexCoord = vec4(GetTexCoord(iTexCoord), bitangent.xy);
+        vTangent = vec4(tangent, bitangent.z);
+    #else
+        vTexCoord = GetTexCoord(iTexCoord);
     #endif
     #endif
-    
+
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         vec4 projWorldPos = vec4(worldPos, 1.0);
         vec4 projWorldPos = vec4(worldPos, 1.0);
@@ -81,43 +67,22 @@ void VS()
         #endif
         #endif
     
     
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (cLightPos.xyz - worldPos);
-        #endif
-    
-        #ifdef NORMALMAP
-            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
-            #ifdef DIRLIGHT
-                vLightVec = vec4(cLightDir * tbn, GetDepth(gl_Position));
-            #else
-                vLightVec = vec4((cLightPos.xyz - worldPos) * tbn * cLightPos.w, GetDepth(gl_Position));
-            #endif
-            #ifdef SPECULAR
-                vEyeVec = (cCameraPos - worldPos) * tbn;
-            #endif
-        #else
-            #ifdef DIRLIGHT
-                vLightVec = vec4(cLightDir, GetDepth(gl_Position));
-            #else
-                vLightVec = vec4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(gl_Position));
-            #endif
-            #ifdef SPECULAR
-                vEyeVec = cCameraPos - worldPos;
-            #endif
+            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
         #if defined(LIGHTMAP) || defined(AO)
         #if defined(LIGHTMAP) || defined(AO)
             // If using lightmap, disregard zone ambient light
             // If using lightmap, disregard zone ambient light
             // If using AO, calculate ambient in the PS
             // If using AO, calculate ambient in the PS
-            vVertexLight = vec4(0.0, 0.0, 0.0, GetDepth(gl_Position));
+            vVertexLight = vec3(0.0, 0.0, 0.0);
             vTexCoord2 = iTexCoord2;
             vTexCoord2 = iTexCoord2;
         #else
         #else
-            vVertexLight = vec4(GetAmbient(GetZonePos(worldPos)), GetDepth(gl_Position));
+            vVertexLight = GetAmbient(GetZonePos(worldPos));
         #endif
         #endif
         
         
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                vVertexLight.rgb += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
+                vVertexLight += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
         #endif
         #endif
         
         
         vScreenPos = GetScreenPos(gl_Position);
         vScreenPos = GetScreenPos(gl_Position);
@@ -132,7 +97,7 @@ void PS()
 {
 {
     // Get material diffuse albedo
     // Get material diffuse albedo
     #ifdef DIFFMAP
     #ifdef DIFFMAP
-        vec4 diffInput = texture2D(sDiffMap, vTexCoord);
+        vec4 diffInput = texture2D(sDiffMap, vTexCoord.xy);
         #ifdef ALPHAMASK
         #ifdef ALPHAMASK
             if (diffInput.a < 0.5)
             if (diffInput.a < 0.5)
                 discard;
                 discard;
@@ -144,11 +109,26 @@ void PS()
     
     
     // Get material specular albedo
     // Get material specular albedo
     #ifdef SPECMAP
     #ifdef SPECMAP
-        vec3 specColor = cMatSpecColor.rgb * texture2D(sSpecMap, vTexCoord).rgb;
+        vec3 specColor = cMatSpecColor.rgb * texture2D(sSpecMap, vTexCoord.xy).rgb;
     #else
     #else
         vec3 specColor = cMatSpecColor.rgb;
         vec3 specColor = cMatSpecColor.rgb;
     #endif
     #endif
 
 
+    // Get normal
+    #ifdef NORMALMAP
+        mat3 tbn = mat3(vTangent.xyz, vec3(vTexCoord.zw, vTangent.w), vNormal);
+        vec3 normal = normalize(tbn * DecodeNormal(texture2D(sNormalMap, vTexCoord.xy)));
+    #else
+        vec3 normal = normalize(vNormal);
+    #endif
+
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(vWorldPos.w);
+    #endif
+
     #if defined(PERPIXEL)
     #if defined(PERPIXEL)
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         vec3 lightColor;
         vec3 lightColor;
@@ -156,16 +136,15 @@ void PS()
         vec3 finalColor;
         vec3 finalColor;
         float diff;
         float diff;
 
 
-        #ifdef NORMALMAP
-            vec3 normal = DecodeNormal(texture2D(sNormalMap, vTexCoord));
+        #ifdef DIRLIGHT
+            diff = GetDiffuse(normal, cLightDirPS, lightDir);
         #else
         #else
-            vec3 normal = normalize(vNormal);
+            vec3 lightVec = (cLightPosPS.xyz - vWorldPos.xyz) * cLightPosPS.w;
+            diff = GetDiffuse(normal, lightVec, lightDir);
         #endif
         #endif
-    
-        diff = GetDiffuse(normal, vLightVec.xyz, lightDir);
-    
+
         #ifdef SHADOW
         #ifdef SHADOW
-            diff *= GetShadow(vShadowPos, vLightVec.w);
+            diff *= GetShadow(vShadowPos, vWorldPos.w);
         #endif
         #endif
     
     
         #if defined(SPOTLIGHT)
         #if defined(SPOTLIGHT)
@@ -177,18 +156,12 @@ void PS()
         #endif
         #endif
     
     
         #ifdef SPECULAR
         #ifdef SPECULAR
-            float spec = GetSpecular(normal, vEyeVec, lightDir, cMatSpecColor.a);
+            float spec = GetSpecular(normal, cCameraPosPS - vWorldPos.xyz, lightDir, cMatSpecColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
         #else
         #else
             finalColor = diff * lightColor * diffColor.rgb;
             finalColor = diff * lightColor * diffColor.rgb;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vLightVec.w, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vLightVec.w);
-        #endif
-
         #ifdef AMBIENT
         #ifdef AMBIENT
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cMatEmissiveColor;
             finalColor += cMatEmissiveColor;
@@ -198,61 +171,40 @@ void PS()
         #endif
         #endif
     #elif defined(PREPASS)
     #elif defined(PREPASS)
         // Fill light pre-pass G-Buffer
         // Fill light pre-pass G-Buffer
-        #ifdef NORMALMAP
-            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
-            vec3 normal = tbn * DecodeNormal(texture2D(sNormalMap, vTexCoord.xy));
-        #else
-            vec3 normal = vNormal;
-        #endif
-
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
         gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
-        gl_FragData[1] = vec4(EncodeDepth(vVertexLight.a), 0.0);
+        gl_FragData[1] = vec4(EncodeDepth(vWorldPos.w), 0.0);
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
         // Fill deferred G-buffer
         // Fill deferred G-buffer
-        #ifdef NORMALMAP
-            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
-            vec3 normal = tbn * DecodeNormal(texture2D(sNormalMap, vTexCoord));
-        #else
-            vec3 normal = vNormal;
-        #endif
-
         float specIntensity = specColor.g;
         float specIntensity = specColor.g;
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
-        vec3 finalColor = vVertexLight.rgb * diffColor.rgb;
+        vec3 finalColor = vVertexLight * diffColor.rgb;
         #ifdef AO
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb;
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb;
         #endif
         #endif
 
 
         #ifdef ENVCUBEMAP
         #ifdef ENVCUBEMAP
-            normal = normalize(normal);
-            finalColor = cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
+            finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
         #endif
         #endif
         #ifdef LIGHTMAP
         #ifdef LIGHTMAP
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
         #endif
         #endif
         #ifdef EMISSIVEMAP
         #ifdef EMISSIVEMAP
-            finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord).rgb;
+            finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord.xy).rgb;
         #else
         #else
             finalColor += cMatEmissiveColor;
             finalColor += cMatEmissiveColor;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vVertexLight.a, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vVertexLight.a);
-        #endif
-
         gl_FragData[0] = vec4(GetFog(finalColor, fogFactor), 1.0);
         gl_FragData[0] = vec4(GetFog(finalColor, fogFactor), 1.0);
         gl_FragData[1] = fogFactor * vec4(diffColor.rgb, specIntensity);
         gl_FragData[1] = fogFactor * vec4(diffColor.rgb, specIntensity);
         gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
-        gl_FragData[3] = vec4(EncodeDepth(vVertexLight.a), 0.0);
+        gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), 0.0);
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        vec3 finalColor = vVertexLight.rgb * diffColor.rgb;
+        vec3 finalColor = vVertexLight * diffColor.rgb;
         #ifdef AO
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb;
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * cAmbientColor * diffColor.rgb;
@@ -268,30 +220,17 @@ void PS()
         #endif
         #endif
 
 
         #ifdef ENVCUBEMAP
         #ifdef ENVCUBEMAP
-            #ifdef NORMALMAP
-                mat3 tbn = mat3(vTangent, vBitangent, vNormal);
-                vec3 normal = tbn * DecodeNormal(texture2D(sNormalMap, vTexCoord));
-            #else
-                vec3 normal = vNormal;
-            #endif
-            normal = normalize(normal);
             finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
             finalColor += cMatEnvMapColor * textureCube(sEnvCubeMap, reflect(vReflectionVec, normal)).rgb;
         #endif
         #endif
         #ifdef LIGHTMAP
         #ifdef LIGHTMAP
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
             finalColor += texture2D(sEmissiveMap, vTexCoord2).rgb * diffColor.rgb;
         #endif
         #endif
         #ifdef EMISSIVEMAP
         #ifdef EMISSIVEMAP
-            finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord).rgb;
+            finalColor += cMatEmissiveColor * texture2D(sEmissiveMap, vTexCoord.xy).rgb;
         #else
         #else
             finalColor += cMatEmissiveColor;
             finalColor += cMatEmissiveColor;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vVertexLight.a, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vVertexLight.a);
-        #endif
-
         gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
         gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
     #endif
     #endif
 }
 }

+ 1 - 1
Bin/CoreData/Shaders/GLSL/PrepassLight.glsl

@@ -78,7 +78,7 @@ void PS()
         lightColor = spotPos.w > 0.0 ? texture2DProj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : vec3(0.0);
         lightColor = spotPos.w > 0.0 ? texture2DProj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : vec3(0.0);
     #elif defined(CUBEMASK)
     #elif defined(CUBEMASK)
         mat3 lightVecRot = mat3(cLightMatricesPS[0][0].xyz, cLightMatricesPS[0][1].xyz, cLightMatricesPS[0][2].xyz);
         mat3 lightVecRot = mat3(cLightMatricesPS[0][0].xyz, cLightMatricesPS[0][1].xyz, cLightMatricesPS[0][2].xyz);
-        lightColor = textureCube(sLightCubeMap, lightVecRot * lightVec).rgb * cLightColor.rgb;
+        lightColor = textureCube(sLightCubeMap, lightVecRot * -lightVec).rgb * cLightColor.rgb;
     #else
     #else
         lightColor = cLightColor.rgb;
         lightColor = cLightColor.rgb;
     #endif
     #endif

+ 52 - 62
Bin/CoreData/Shaders/GLSL/TerrainBlend.glsl

@@ -6,15 +6,9 @@
 #include "Fog.glsl"
 #include "Fog.glsl"
 
 
 varying vec2 vTexCoord;
 varying vec2 vTexCoord;
-#ifdef HEIGHTFOG
-    varying vec3 vWorldPos;
-#endif
+varying vec3 vNormal;
+varying vec4 vWorldPos;
 #ifdef PERPIXEL
 #ifdef PERPIXEL
-    varying vec4 vLightVec;
-    #ifdef SPECULAR
-        varying vec3 vEyeVec;
-    #endif
-    varying vec3 vNormal;
     #ifdef SHADOW
     #ifdef SHADOW
         varying vec4 vShadowPos[NUMCASCADES];
         varying vec4 vShadowPos[NUMCASCADES];
     #endif
     #endif
@@ -25,9 +19,14 @@ varying vec2 vTexCoord;
         varying vec3 vCubeMaskVec;
         varying vec3 vCubeMaskVec;
     #endif
     #endif
 #else
 #else
-    varying vec4 vVertexLight;
-    varying vec3 vNormal;
+    varying vec3 vVertexLight;
     varying vec4 vScreenPos;
     varying vec4 vScreenPos;
+    #ifdef ENVCUBEMAP
+        varying vec3 vReflectionVec;
+    #endif
+    #if defined(LIGHTMAP) || defined(AO)
+        varying vec2 vTexCoord2;
+    #endif
 #endif
 #endif
 
 
 #ifdef COMPILEPS
 #ifdef COMPILEPS
@@ -43,12 +42,9 @@ void VS()
     mat4 modelMatrix = iModelMatrix;
     mat4 modelMatrix = iModelMatrix;
     vec3 worldPos = GetWorldPos(modelMatrix);
     vec3 worldPos = GetWorldPos(modelMatrix);
     gl_Position = GetClipPos(worldPos);
     gl_Position = GetClipPos(worldPos);
-    vTexCoord = GetTexCoord(iTexCoord);
     vNormal = GetWorldNormal(modelMatrix);
     vNormal = GetWorldNormal(modelMatrix);
-
-    #ifdef HEIGHTFOG
-        vWorldPos = worldPos;
-    #endif
+    vWorldPos = vec4(worldPos, GetDepth(gl_Position));
+    vTexCoord = GetTexCoord(iTexCoord);
 
 
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
@@ -64,29 +60,31 @@ void VS()
             // Spotlight projection: transform from world space to projector texture coordinates
             // Spotlight projection: transform from world space to projector texture coordinates
             vSpotPos = cLightMatrices[0] * projWorldPos;
             vSpotPos = cLightMatrices[0] * projWorldPos;
         #endif
         #endif
-
+    
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (cLightPos.xyz - worldPos);
-        #endif
-
-        #ifdef DIRLIGHT
-            vLightVec = vec4(cLightDir, GetDepth(gl_Position));
-        #else
-            vLightVec = vec4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(gl_Position));
-        #endif
-        #ifdef SPECULAR
-            vEyeVec = cCameraPos - worldPos;
+            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        vVertexLight = vec4(GetAmbient(GetZonePos(worldPos)), GetDepth(gl_Position));
-
+        #if defined(LIGHTMAP) || defined(AO)
+            // If using lightmap, disregard zone ambient light
+            // If using AO, calculate ambient in the PS
+            vVertexLight = vec3(0.0, 0.0, 0.0);
+            vTexCoord2 = iTexCoord2;
+        #else
+            vVertexLight = GetAmbient(GetZonePos(worldPos));
+        #endif
+        
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                vVertexLight.rgb += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
+                vVertexLight += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
         #endif
         #endif
         
         
         vScreenPos = GetScreenPos(gl_Position);
         vScreenPos = GetScreenPos(gl_Position);
+
+        #ifdef ENVCUBEMAP
+            vReflectionVec = worldPos - cCameraPos;
+        #endif
     #endif
     #endif
 }
 }
 
 
@@ -103,6 +101,16 @@ void PS()
     // Get material specular albedo
     // Get material specular albedo
     vec3 specColor = cMatSpecColor.rgb;
     vec3 specColor = cMatSpecColor.rgb;
 
 
+    // Get normal
+    vec3 normal = normalize(vNormal);
+
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(vWorldPos.w);
+    #endif
+
     #if defined(PERPIXEL)
     #if defined(PERPIXEL)
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         vec3 lightColor;
         vec3 lightColor;
@@ -110,14 +118,17 @@ void PS()
         vec3 finalColor;
         vec3 finalColor;
         float diff;
         float diff;
 
 
-        vec3 normal = normalize(vNormal);
-
-        diff = GetDiffuse(normal, vLightVec.xyz, lightDir);
+        #ifdef DIRLIGHT
+            diff = GetDiffuse(normal, cLightDirPS, lightDir);
+        #else
+            vec3 lightVec = (cLightPosPS.xyz - vWorldPos.xyz) * cLightPosPS.w;
+            diff = GetDiffuse(normal, lightVec, lightDir);
+        #endif
 
 
         #ifdef SHADOW
         #ifdef SHADOW
-            diff *= GetShadow(vShadowPos, vLightVec.w);
+            diff *= GetShadow(vShadowPos, vWorldPos.w);
         #endif
         #endif
-
+    
         #if defined(SPOTLIGHT)
         #if defined(SPOTLIGHT)
             lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0);
             lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0);
         #elif defined(CUBEMASK)
         #elif defined(CUBEMASK)
@@ -125,54 +136,39 @@ void PS()
         #else
         #else
             lightColor = cLightColor.rgb;
             lightColor = cLightColor.rgb;
         #endif
         #endif
-
+    
         #ifdef SPECULAR
         #ifdef SPECULAR
-            float spec = GetSpecular(normal, vEyeVec, lightDir, cMatSpecColor.a);
+            float spec = GetSpecular(normal, cCameraPosPS - vWorldPos.xyz, lightDir, cMatSpecColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
         #else
         #else
             finalColor = diff * lightColor * diffColor.rgb;
             finalColor = diff * lightColor * diffColor.rgb;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vLightVec.w, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vLightVec.w);
-        #endif
-
         #ifdef AMBIENT
         #ifdef AMBIENT
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cAmbientColor * diffColor.rgb;
+            finalColor += cMatEmissiveColor;
             gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
             gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
         #else
         #else
             gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
             gl_FragColor = vec4(GetLitFog(finalColor, fogFactor), diffColor.a);
         #endif
         #endif
     #elif defined(PREPASS)
     #elif defined(PREPASS)
         // Fill light pre-pass G-Buffer
         // Fill light pre-pass G-Buffer
-        vec3 normal = vNormal;
-
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
         gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
-        gl_FragData[1] = vec4(EncodeDepth(vVertexLight.a), 0.0);
+        gl_FragData[1] = vec4(EncodeDepth(vWorldPos.w), 0.0);
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
         // Fill deferred G-buffer
         // Fill deferred G-buffer
-        vec3 normal = vNormal;
-
         float specIntensity = specColor.g;
         float specIntensity = specColor.g;
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vVertexLight.a, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vVertexLight.a);
-        #endif
-
-        gl_FragData[0] = vec4(GetFog(vVertexLight.rgb * diffColor.rgb, fogFactor), 1.0);
+        gl_FragData[0] = vec4(GetFog(vVertexLight * diffColor.rgb, fogFactor), 1.0);
         gl_FragData[1] = fogFactor * vec4(diffColor.rgb, specIntensity);
         gl_FragData[1] = fogFactor * vec4(diffColor.rgb, specIntensity);
         gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
         gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
-        gl_FragData[3] = vec4(EncodeDepth(vVertexLight.a), 0.0);
+        gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), 0.0);
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        vec3 finalColor = vVertexLight.rgb * diffColor.rgb;
+        vec3 finalColor = vVertexLight * diffColor.rgb;
 
 
         #ifdef MATERIAL
         #ifdef MATERIAL
             // Add light pre-pass accumulation result
             // Add light pre-pass accumulation result
@@ -183,12 +179,6 @@ void PS()
             finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
             finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(vVertexLight.a, vWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(vVertexLight.a);
-        #endif
-
         gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
         gl_FragColor = vec4(GetFog(finalColor, fogFactor), diffColor.a);
     #endif
     #endif
 }
 }

+ 1 - 0
Bin/CoreData/Shaders/GLSL/Uniforms.glsl

@@ -41,6 +41,7 @@ uniform mat4 cZone;
 #endif
 #endif
 
 
 uniform vec3 cAmbientColor;
 uniform vec3 cAmbientColor;
+uniform vec3 cCameraPosPS;
 uniform float cDeltaTimePS;
 uniform float cDeltaTimePS;
 uniform float cElapsedTimePS;
 uniform float cElapsedTimePS;
 uniform vec4 cFogParams;
 uniform vec4 cFogParams;

+ 8 - 13
Bin/CoreData/Shaders/GLSL/Unlit.glsl

@@ -5,13 +5,10 @@
 #include "Fog.glsl"
 #include "Fog.glsl"
 
 
 varying vec2 vTexCoord;
 varying vec2 vTexCoord;
+varying vec4 vWorldPos;
 #ifdef VERTEXCOLOR
 #ifdef VERTEXCOLOR
     varying vec4 vColor;
     varying vec4 vColor;
 #endif
 #endif
-#ifdef HEIGHTFOG
-    varying vec3 vWorldPos;
-#endif
-varying float vDepth;
 
 
 void VS()
 void VS()
 {
 {
@@ -19,11 +16,7 @@ void VS()
     vec3 worldPos = GetWorldPos(modelMatrix);
     vec3 worldPos = GetWorldPos(modelMatrix);
     gl_Position = GetClipPos(worldPos);
     gl_Position = GetClipPos(worldPos);
     vTexCoord = GetTexCoord(iTexCoord);
     vTexCoord = GetTexCoord(iTexCoord);
-    vDepth = GetDepth(gl_Position);
-
-    #ifdef HEIGHTFOG
-        vWorldPos = worldPos;
-    #endif
+    vWorldPos = vec4(worldPos, GetDepth(gl_Position));
 
 
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         vColor = iColor;
         vColor = iColor;
@@ -32,6 +25,7 @@ void VS()
 
 
 void PS()
 void PS()
 {
 {
+    // Get material diffuse albedo
     #ifdef DIFFMAP
     #ifdef DIFFMAP
         vec4 diffColor = cMatDiffColor * texture2D(sDiffMap, vTexCoord);
         vec4 diffColor = cMatDiffColor * texture2D(sDiffMap, vTexCoord);
         #ifdef ALPHAMASK
         #ifdef ALPHAMASK
@@ -46,21 +40,22 @@ void PS()
         diffColor *= vColor;
         diffColor *= vColor;
     #endif
     #endif
 
 
+    // Get fog factor
     #ifdef HEIGHTFOG
     #ifdef HEIGHTFOG
-        float fogFactor = GetHeightFogFactor(vDepth, vWorldPos.y);
+        float fogFactor = GetHeightFogFactor(vWorldPos.w, vWorldPos.y);
     #else
     #else
-        float fogFactor = GetFogFactor(vDepth);
+        float fogFactor = GetFogFactor(vWorldPos.w);
     #endif
     #endif
 
 
     #if defined(PREPASS)
     #if defined(PREPASS)
         // Fill light pre-pass G-Buffer
         // Fill light pre-pass G-Buffer
         gl_FragData[0] = vec4(0.5, 0.5, 0.5, 1.0);
         gl_FragData[0] = vec4(0.5, 0.5, 0.5, 1.0);
-        gl_FragData[1] = vec4(EncodeDepth(vDepth), 0.0);
+        gl_FragData[1] = vec4(EncodeDepth(vWorldPos.w), 0.0);
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
         gl_FragData[0] = vec4(GetFog(diffColor.rgb, fogFactor), diffColor.a);
         gl_FragData[0] = vec4(GetFog(diffColor.rgb, fogFactor), diffColor.a);
         gl_FragData[1] = vec4(0.0, 0.0, 0.0, 0.0);
         gl_FragData[1] = vec4(0.0, 0.0, 0.0, 0.0);
         gl_FragData[2] = vec4(0.5, 0.5, 0.5, 1.0);
         gl_FragData[2] = vec4(0.5, 0.5, 0.5, 1.0);
-        gl_FragData[3] = vec4(EncodeDepth(vDepth), 0.0);
+        gl_FragData[3] = vec4(EncodeDepth(vWorldPos.w), 0.0);
     #else
     #else
         gl_FragColor = vec4(GetFog(diffColor.rgb, fogFactor), diffColor.a);
         gl_FragColor = vec4(GetFog(diffColor.rgb, fogFactor), diffColor.a);
     #endif
     #endif

+ 37 - 55
Bin/CoreData/Shaders/GLSL/Vegetation.glsl

@@ -8,18 +8,15 @@ uniform float cWindHeightPivot;
 uniform float cWindPeriod;
 uniform float cWindPeriod;
 uniform vec2 cWindWorldSpacing;
 uniform vec2 cWindWorldSpacing;
 
 
-varying vec2 vTexCoord;
-#ifdef HEIGHTFOG
-    varying vec3 vWorldPos;
+#ifdef NORMALMAP
+    varying vec4 vTexCoord;
+    varying vec4 vTangent;
+#else
+    varying vec2 vTexCoord;
 #endif
 #endif
+varying vec3 vNormal;
+varying vec4 vWorldPos;
 #ifdef PERPIXEL
 #ifdef PERPIXEL
-    varying vec4 vLightVec;
-    #ifdef SPECULAR
-        varying vec3 vEyeVec;
-    #endif
-    #ifndef NORMALMAP
-        varying vec3 vNormal;
-    #endif
     #ifdef SHADOW
     #ifdef SHADOW
         varying vec4 vShadowPos[NUMCASCADES];
         varying vec4 vShadowPos[NUMCASCADES];
     #endif
     #endif
@@ -30,13 +27,14 @@ varying vec2 vTexCoord;
         varying vec3 vCubeMaskVec;
         varying vec3 vCubeMaskVec;
     #endif
     #endif
 #else
 #else
-    varying vec4 vVertexLight;
-    varying vec3 vNormal;
-    #ifdef NORMALMAP
-        varying vec3 vTangent;
-        varying vec3 vBitangent;
-    #endif
+    varying vec3 vVertexLight;
     varying vec4 vScreenPos;
     varying vec4 vScreenPos;
+    #ifdef ENVCUBEMAP
+        varying vec3 vReflectionVec;
+    #endif
+    #if defined(LIGHTMAP) || defined(AO)
+        varying vec2 vTexCoord2;
+    #endif
 #endif
 #endif
 
 
 void VS()
 void VS()
@@ -51,24 +49,18 @@ void VS()
     worldPos.z -= windStrength * cos(windPeriod);
     worldPos.z -= windStrength * cos(windPeriod);
 
 
     gl_Position = GetClipPos(worldPos);
     gl_Position = GetClipPos(worldPos);
-    vTexCoord = GetTexCoord(iTexCoord);
-
-    #ifdef HEIGHTFOG
-        vWorldPos = worldPos;
-    #endif
-
-    #if defined(PERPIXEL) && defined(NORMALMAP)
-        vec3 vNormal;
-        vec3 vTangent;
-        vec3 vBitangent;
-    #endif
-
     vNormal = GetWorldNormal(modelMatrix);
     vNormal = GetWorldNormal(modelMatrix);
+    vWorldPos = vec4(worldPos, GetDepth(gl_Position));
+
     #ifdef NORMALMAP
     #ifdef NORMALMAP
-        vTangent = GetWorldTangent(modelMatrix);
-        vBitangent = cross(vTangent, vNormal) * iTangent.w;
+        vec3 tangent = GetWorldTangent(modelMatrix);
+        vec3 bitangent = cross(tangent, vNormal) * iTangent.w;
+        vTexCoord = vec4(GetTexCoord(iTexCoord), bitangent.xy);
+        vTangent = vec4(tangent, bitangent.z);
+    #else
+        vTexCoord = GetTexCoord(iTexCoord);
     #endif
     #endif
-    
+
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         vec4 projWorldPos = vec4(worldPos, 1.0);
         vec4 projWorldPos = vec4(worldPos, 1.0);
@@ -85,38 +77,28 @@ void VS()
         #endif
         #endif
     
     
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (cLightPos.xyz - worldPos);
-        #endif
-    
-        #ifdef NORMALMAP
-            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
-            #ifdef DIRLIGHT
-                vLightVec = vec4(cLightDir * tbn, GetDepth(gl_Position));
-            #else
-                vLightVec = vec4((cLightPos.xyz - worldPos) * tbn * cLightPos.w, GetDepth(gl_Position));
-            #endif
-            #ifdef SPECULAR
-                vEyeVec = (cCameraPos - worldPos) * tbn;
-            #endif
-        #else
-            #ifdef DIRLIGHT
-                vLightVec = vec4(cLightDir, GetDepth(gl_Position));
-            #else
-                vLightVec = vec4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(gl_Position));
-            #endif
-            #ifdef SPECULAR
-                vEyeVec = cCameraPos - worldPos;
-            #endif
+            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (worldPos - cLightPos.xyz);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        vVertexLight = vec4(GetAmbient(GetZonePos(worldPos)), GetDepth(gl_Position));
+        #if defined(LIGHTMAP) || defined(AO)
+            // If using lightmap, disregard zone ambient light
+            // If using AO, calculate ambient in the PS
+            vVertexLight = vec3(0.0, 0.0, 0.0);
+            vTexCoord2 = iTexCoord2;
+        #else
+            vVertexLight = GetAmbient(GetZonePos(worldPos));
+        #endif
         
         
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                vVertexLight.rgb += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
+                vVertexLight += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
         #endif
         #endif
         
         
         vScreenPos = GetScreenPos(gl_Position);
         vScreenPos = GetScreenPos(gl_Position);
+
+        #ifdef ENVCUBEMAP
+            vReflectionVec = worldPos - cCameraPos;
+        #endif
     #endif
     #endif
 }
 }

+ 2 - 9
Bin/CoreData/Shaders/HLSL/DeferredLight.hlsl

@@ -69,14 +69,7 @@ void PS(
         float4 normalInput = tex2Dproj(sNormalBuffer, iScreenPos);
         float4 normalInput = tex2Dproj(sNormalBuffer, iScreenPos);
     #endif
     #endif
 
 
-    // With a cubemasked shadowed point light and hardware depth reconstruction, SM2 runs out of instructions,
-    // so skip normalization of normals in that case
-    #if defined(SM3) || defined(HWSHADOW) || !defined(POINTLIGHT) || !defined(SHADOW) || !defined(CUBEMASK)
-        float3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
-    #else
-        float3 normal = normalInput.rgb * 2.0 - 1.0;
-    #endif
-
+    float3 normal = normalize(normalInput.rgb * 2.0 - 1.0);
     float4 projWorldPos = float4(worldPos, 1.0);
     float4 projWorldPos = float4(worldPos, 1.0);
     float3 lightColor;
     float3 lightColor;
     float3 lightDir;
     float3 lightDir;
@@ -97,7 +90,7 @@ void PS(
         float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
         float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
         lightColor = spotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
         lightColor = spotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
     #elif defined(CUBEMASK)
     #elif defined(CUBEMASK)
-        lightColor = texCUBE(sLightCubeMap, mul(lightVec, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
+        lightColor = texCUBE(sLightCubeMap, mul(-lightVec, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
     #else
     #else
         lightColor = cLightColor.rgb;
         lightColor = cLightColor.rgb;
     #endif
     #endif

+ 31 - 12
Bin/CoreData/Shaders/HLSL/Lighting.hlsl

@@ -65,7 +65,11 @@ float GetVertexLightVolumetric(int index, float3 worldPos)
 #ifdef SHADOW
 #ifdef SHADOW
 
 
 #ifdef DIRLIGHT
 #ifdef DIRLIGHT
-    #define NUMCASCADES 4
+    #ifdef SM3
+        #define NUMCASCADES 4
+    #else
+        #define NUMCASCADES 3
+    #endif
 #else
 #else
     #define NUMCASCADES 1
     #define NUMCASCADES 1
 #endif
 #endif
@@ -77,7 +81,9 @@ void GetShadowPos(float4 projWorldPos, out float4 shadowPos[NUMCASCADES])
         shadowPos[0] = mul(projWorldPos, cLightMatrices[0]);
         shadowPos[0] = mul(projWorldPos, cLightMatrices[0]);
         shadowPos[1] = mul(projWorldPos, cLightMatrices[1]);
         shadowPos[1] = mul(projWorldPos, cLightMatrices[1]);
         shadowPos[2] = mul(projWorldPos, cLightMatrices[2]);
         shadowPos[2] = mul(projWorldPos, cLightMatrices[2]);
-        shadowPos[3] = mul(projWorldPos, cLightMatrices[3]);
+        #ifdef SM3
+            shadowPos[3] = mul(projWorldPos, cLightMatrices[3]);
+        #endif
     #elif defined(SPOTLIGHT)
     #elif defined(SPOTLIGHT)
         shadowPos[0] = mul(projWorldPos, cLightMatrices[1]);
         shadowPos[0] = mul(projWorldPos, cLightMatrices[1]);
     #else
     #else
@@ -130,7 +136,11 @@ float GetIntensity(float3 color)
 #ifdef SHADOW
 #ifdef SHADOW
 
 
 #ifdef DIRLIGHT
 #ifdef DIRLIGHT
-    #define NUMCASCADES 4
+    #ifdef SM3
+        #define NUMCASCADES 4
+    #else
+        #define NUMCASCADES 3
+    #endif
 #else
 #else
     #define NUMCASCADES 1
     #define NUMCASCADES 1
 #endif
 #endif
@@ -207,15 +217,24 @@ float GetDirShadow(const float4 iShadowPos[NUMCASCADES], float depth)
 {
 {
     float4 shadowPos;
     float4 shadowPos;
 
 
-    if (depth < cShadowSplits.x)
-        shadowPos = iShadowPos[0];
-    else if (depth < cShadowSplits.y)
-        shadowPos = iShadowPos[1];
-    else if (depth < cShadowSplits.z)
-        shadowPos = iShadowPos[2];
-    else
-        shadowPos = iShadowPos[3];
-        
+    #ifdef SM3
+        if (depth < cShadowSplits.x)
+            shadowPos = iShadowPos[0];
+        else if (depth < cShadowSplits.y)
+            shadowPos = iShadowPos[1];
+        else if (depth < cShadowSplits.z)
+            shadowPos = iShadowPos[2];
+        else
+            shadowPos = iShadowPos[3];
+    #else
+        if (depth < cShadowSplits.x)
+            shadowPos = iShadowPos[0];
+        else if (depth < cShadowSplits.y)
+            shadowPos = iShadowPos[1];
+        else
+            shadowPos = iShadowPos[2];
+    #endif
+
     return GetDirShadowFade(GetShadow(shadowPos), depth);
     return GetDirShadowFade(GetShadow(shadowPos), depth);
 }
 }
 
 

+ 44 - 44
Bin/CoreData/Shaders/HLSL/LitParticle.hlsl

@@ -21,19 +21,19 @@ void VS(float4 iPos : POSITION,
         float2 iSize : TEXCOORD1,
         float2 iSize : TEXCOORD1,
     #endif
     #endif
     out float2 oTexCoord : TEXCOORD0,
     out float2 oTexCoord : TEXCOORD0,
-    #ifdef HEIGHTFOG
-        out float3 oWorldPos : TEXCOORD8,
-    #endif
+    out float4 oWorldPos : TEXCOORD3,
     #if PERPIXEL
     #if PERPIXEL
-        out float4 oLightVec : TEXCOORD1,
+        #ifdef SHADOW
+            out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
+        #endif
         #ifdef SPOTLIGHT
         #ifdef SPOTLIGHT
-            out float4 oSpotPos : TEXCOORD2,
+            out float4 oSpotPos : TEXCOORD5,
         #endif
         #endif
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            out float3 oCubeMaskVec : TEXCOORD2,
+            out float3 oCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        out float4 oVertexLight : TEXCOORD1,
+        out float3 oVertexLight : TEXCOORD4,
     #endif
     #endif
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         out float4 oColor : COLOR0,
         out float4 oColor : COLOR0,
@@ -44,10 +44,7 @@ void VS(float4 iPos : POSITION,
     float3 worldPos = GetWorldPos(modelMatrix);
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
     oPos = GetClipPos(worldPos);
     oTexCoord = GetTexCoord(iTexCoord);
     oTexCoord = GetTexCoord(iTexCoord);
-
-    #ifdef HEIGHTFOG
-        oWorldPos = worldPos;
-    #endif
+    oWorldPos = float4(worldPos, GetDepth(oPos));
 
 
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         oColor = iColor;
         oColor = iColor;
@@ -55,47 +52,46 @@ void VS(float4 iPos : POSITION,
 
 
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
-        float4 projWorldPos = float4(worldPos, 1.0);
-    
-        #ifdef DIRLIGHT
-            oLightVec = float4(cLightDir, GetDepth(oPos));
-        #else
-            oLightVec = float4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(oPos));
+        float4 projWorldPos = float4(worldPos.xyz, 1.0);
+
+        #ifdef SHADOW
+            // Shadow projection: transform from world space to shadow space
+            GetShadowPos(projWorldPos, oShadowPos);
         #endif
         #endif
-    
+
         #ifdef SPOTLIGHT
         #ifdef SPOTLIGHT
             // Spotlight projection: transform from world space to projector texture coordinates
             // Spotlight projection: transform from world space to projector texture coordinates
             oSpotPos = mul(projWorldPos, cLightMatrices[0]);
             oSpotPos = mul(projWorldPos, cLightMatrices[0]);
         #endif
         #endif
-    
+
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            oCubeMaskVec = mul(oLightVec.xyz, (float3x3)cLightMatrices[0]);
+            oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        oVertexLight = float4(GetAmbient(GetZonePos(worldPos)), GetDepth(oPos));
+        oVertexLight = GetAmbient(GetZonePos(worldPos));
 
 
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                oVertexLight.rgb += GetVertexLightVolumetric(i, worldPos) * cVertexLights[i * 3].rgb;
+                oVertexLight += GetVertexLightVolumetric(i, worldPos) * cVertexLights[i * 3].rgb;
         #endif
         #endif
     #endif
     #endif
 }
 }
 
 
 void PS(float2 iTexCoord : TEXCOORD0,
 void PS(float2 iTexCoord : TEXCOORD0,
-    #ifdef HEIGHTFOG
-        float3 iWorldPos : TEXCOORD8,
-    #endif
+    float4 iWorldPos : TEXCOORD3,
     #ifdef PERPIXEL
     #ifdef PERPIXEL
-        float4 iLightVec : TEXCOORD1,
+        #ifdef SHADOW
+            float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
+        #endif
         #ifdef SPOTLIGHT
         #ifdef SPOTLIGHT
-            float4 iSpotPos : TEXCOORD2,
+            float4 iSpotPos : TEXCOORD5,
         #endif
         #endif
         #ifdef CUBEMASK
         #ifdef CUBEMASK
-            float3 iCubeMaskVec : TEXCOORD2,
+            float3 iCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        float4 iVertexLight : TEXCOORD1,
+        float3 iVertexLight : TEXCOORD4,
     #endif
     #endif
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         float4 iColor : COLOR0,
         float4 iColor : COLOR0,
@@ -118,13 +114,29 @@ void PS(float2 iTexCoord : TEXCOORD0,
         diffColor *= iColor;
         diffColor *= iColor;
     #endif
     #endif
 
 
-    #if PERPIXEL
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(iWorldPos.w);
+    #endif
+
+    #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         float3 lightColor;
         float3 lightColor;
         float3 finalColor;
         float3 finalColor;
         float diff;
         float diff;
     
     
-        diff = GetDiffuseVolumetric(iLightVec.xyz);
+        #ifdef DIRLIGHT
+            diff = GetDiffuseVolumetric(cLightDirPS);
+        #else
+            float3 lightVec = (cLightPosPS.xyz - iWorldPos.xyz) * cLightPosPS.w;
+            diff = GetDiffuseVolumetric(lightVec);
+        #endif
+
+        #ifdef SHADOW
+            diff *= GetShadow(iShadowPos, iWorldPos.w);
+        #endif
 
 
         #if defined(SPOTLIGHT)
         #if defined(SPOTLIGHT)
             lightColor = iSpotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
             lightColor = iSpotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
@@ -134,23 +146,11 @@ void PS(float2 iTexCoord : TEXCOORD0,
             lightColor = cLightColor.rgb;
             lightColor = cLightColor.rgb;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iLightVec.w, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iLightVec.w);
-        #endif
-    
         finalColor = diff * lightColor * diffColor.rgb;
         finalColor = diff * lightColor * diffColor.rgb;
         oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
         oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        float3 finalColor = iVertexLight.rgb * diffColor.rgb;
-        
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iVertexLight.a, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iVertexLight.a);
-        #endif
+        float3 finalColor = iVertexLight * diffColor.rgb;
 
 
         oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
         oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
     #endif
     #endif

+ 59 - 126
Bin/CoreData/Shaders/HLSL/LitSolid.hlsl

@@ -29,18 +29,15 @@ void VS(float4 iPos : POSITION,
     #ifdef BILLBOARD
     #ifdef BILLBOARD
         float2 iSize : TEXCOORD1,
         float2 iSize : TEXCOORD1,
     #endif
     #endif
-    out float2 oTexCoord : TEXCOORD0,
-    #ifdef HEIGHTFOG
-        out float3 oWorldPos : TEXCOORD8,
+    #ifndef NORMALMAP
+        out float2 oTexCoord : TEXCOORD0,
+    #else
+        out float4 oTexCoord : TEXCOORD0,
+        out float4 oTangent : TEXCOORD3,
     #endif
     #endif
+    out float3 oNormal : TEXCOORD1,
+    out float4 oWorldPos : TEXCOORD2,
     #ifdef PERPIXEL
     #ifdef PERPIXEL
-        out float4 oLightVec : TEXCOORD1,
-        #ifndef NORMALMAP
-            out float3 oNormal : TEXCOORD2,
-        #endif
-        #ifdef SPECULAR
-            out float3 oEyeVec : TEXCOORD3,
-        #endif
         #ifdef SHADOW
         #ifdef SHADOW
             out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
             out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
         #endif
         #endif
@@ -51,12 +48,7 @@ void VS(float4 iPos : POSITION,
             out float3 oCubeMaskVec : TEXCOORD5,
             out float3 oCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        out float4 oVertexLight : TEXCOORD1,
-        out float3 oNormal : TEXCOORD2,
-        #ifdef NORMALMAP
-            out float3 oTangent : TEXCOORD3,
-            out float3 oBitangent : TEXCOORD4,
-        #endif
+        out float3 oVertexLight : TEXCOORD4,
         out float4 oScreenPos : TEXCOORD5,
         out float4 oScreenPos : TEXCOORD5,
         #ifdef ENVCUBEMAP
         #ifdef ENVCUBEMAP
             out float3 oReflectionVec : TEXCOORD6,
             out float3 oReflectionVec : TEXCOORD6,
@@ -70,34 +62,22 @@ void VS(float4 iPos : POSITION,
     float4x3 modelMatrix = iModelMatrix;
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
     oPos = GetClipPos(worldPos);
-    oTexCoord = GetTexCoord(iTexCoord);
-
-    #ifdef HEIGHTFOG
-        oWorldPos = worldPos;
-    #endif
-
-    #if defined(PERPIXEL) && defined(NORMALMAP)
-        float3 oNormal;
-        float3 oTangent;
-        float3 oBitangent;
-    #endif
-
     oNormal = GetWorldNormal(modelMatrix);
     oNormal = GetWorldNormal(modelMatrix);
+    oWorldPos = float4(worldPos, GetDepth(oPos));
+
     #ifdef NORMALMAP
     #ifdef NORMALMAP
-        oTangent = GetWorldTangent(modelMatrix);
-        oBitangent = cross(oTangent, oNormal) * iTangent.w;
+        float3 tangent = GetWorldTangent(modelMatrix);
+        float3 bitangent = cross(tangent, oNormal) * iTangent.w;
+        oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy);
+        oTangent = float4(tangent, bitangent.z);
+    #else
+        oTexCoord = GetTexCoord(iTexCoord);
     #endif
     #endif
 
 
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
-        float4 projWorldPos = float4(worldPos, 1.0);
+        float4 projWorldPos = float4(worldPos.xyz, 1.0);
 
 
-        #ifdef DIRLIGHT
-            oLightVec = float4(cLightDir, GetDepth(oPos));
-        #else
-            oLightVec = float4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(oPos));
-        #endif
-    
         #ifdef SHADOW
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             // Shadow projection: transform from world space to shadow space
             GetShadowPos(projWorldPos, oShadowPos);
             GetShadowPos(projWorldPos, oShadowPos);
@@ -109,32 +89,22 @@ void VS(float4 iPos : POSITION,
         #endif
         #endif
 
 
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            oCubeMaskVec = mul(oLightVec.xyz, (float3x3)cLightMatrices[0]);
-        #endif
-
-        #ifdef NORMALMAP
-            float3x3 tbn = float3x3(oTangent, oBitangent, oNormal);
-            oLightVec.xyz = mul(tbn, oLightVec.xyz);
-            #ifdef SPECULAR
-                oEyeVec = mul(tbn, cCameraPos - worldPos);
-            #endif
-        #elif defined(SPECULAR)
-            oEyeVec = cCameraPos - worldPos;
+            oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
         #if defined(LIGHTMAP) || defined(AO)
         #if defined(LIGHTMAP) || defined(AO)
             // If using lightmap, disregard zone ambient light
             // If using lightmap, disregard zone ambient light
             // If using AO, calculate ambient in the PS
             // If using AO, calculate ambient in the PS
-            oVertexLight = float4(0.0, 0.0, 0.0, GetDepth(oPos));
+            oVertexLight = float3(0.0, 0.0, 0.0);
             oTexCoord2 = iTexCoord2;
             oTexCoord2 = iTexCoord2;
         #else
         #else
-            oVertexLight = float4(GetAmbient(GetZonePos(worldPos)), GetDepth(oPos));
+            oVertexLight = GetAmbient(GetZonePos(worldPos));
         #endif
         #endif
 
 
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                oVertexLight.rgb += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
+                oVertexLight += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
         #endif
         #endif
         
         
         oScreenPos = GetScreenPos(oPos);
         oScreenPos = GetScreenPos(oPos);
@@ -145,18 +115,16 @@ void VS(float4 iPos : POSITION,
     #endif
     #endif
 }
 }
 
 
-void PS(float2 iTexCoord : TEXCOORD0,
-    #ifdef HEIGHTFOG
-        float3 iWorldPos : TEXCOORD8,
+void PS(
+    #ifndef NORMALMAP
+        float2 iTexCoord : TEXCOORD0,
+    #else
+        float4 iTexCoord : TEXCOORD0,
+        float4 iTangent : TEXCOORD3,
     #endif
     #endif
+    float3 iNormal : TEXCOORD1,
+    float4 iWorldPos : TEXCOORD2,
     #ifdef PERPIXEL
     #ifdef PERPIXEL
-        float4 iLightVec : TEXCOORD1,
-        #ifndef NORMALMAP
-            float3 iNormal : TEXCOORD2,
-        #endif
-        #ifdef SPECULAR
-            float3 iEyeVec : TEXCOORD3,
-        #endif
         #ifdef SHADOW
         #ifdef SHADOW
             float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
             float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
         #endif
         #endif
@@ -167,12 +135,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
             float3 iCubeMaskVec : TEXCOORD5,
             float3 iCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        float4 iVertexLight : TEXCOORD1,
-        float3 iNormal : TEXCOORD2,
-        #ifdef NORMALMAP
-            float3 iTangent : TEXCOORD3,
-            float3 iBitangent : TEXCOORD4,
-        #endif
+        float3 iVertexLight : TEXCOORD4,
         float4 iScreenPos : TEXCOORD5,
         float4 iScreenPos : TEXCOORD5,
         #ifdef ENVCUBEMAP
         #ifdef ENVCUBEMAP
             float3 iReflectionVec : TEXCOORD6,
             float3 iReflectionVec : TEXCOORD6,
@@ -193,7 +156,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
 {
 {
     // Get material diffuse albedo
     // Get material diffuse albedo
     #ifdef DIFFMAP
     #ifdef DIFFMAP
-        float4 diffInput = tex2D(sDiffMap, iTexCoord);
+        float4 diffInput = tex2D(sDiffMap, iTexCoord.xy);
         #ifdef ALPHAMASK
         #ifdef ALPHAMASK
             if (diffInput.a < 0.5)
             if (diffInput.a < 0.5)
                 discard;
                 discard;
@@ -205,10 +168,25 @@ void PS(float2 iTexCoord : TEXCOORD0,
     
     
     // Get material specular albedo
     // Get material specular albedo
     #ifdef SPECMAP
     #ifdef SPECMAP
-        float3 specColor = cMatSpecColor.rgb * tex2D(sSpecMap, iTexCoord).rgb;
+        float3 specColor = cMatSpecColor.rgb * tex2D(sSpecMap, iTexCoord.xy).rgb;
     #else
     #else
         float3 specColor = cMatSpecColor.rgb;
         float3 specColor = cMatSpecColor.rgb;
     #endif
     #endif
+    
+    // Get normal
+    #ifdef NORMALMAP
+        float3x3 tbn = float3x3(iTangent.xyz, float3(iTexCoord.zw, iTangent.w), iNormal);
+        float3 normal = normalize(mul(DecodeNormal(tex2D(sNormalMap, iTexCoord.xy)), tbn));
+    #else
+        float3 normal = normalize(iNormal);
+    #endif
+    
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(iWorldPos.w);
+    #endif
 
 
     #if defined(PERPIXEL)
     #if defined(PERPIXEL)
         // Per-pixel forward lighting
         // Per-pixel forward lighting
@@ -217,16 +195,15 @@ void PS(float2 iTexCoord : TEXCOORD0,
         float3 finalColor;
         float3 finalColor;
         float diff;
         float diff;
 
 
-        #ifdef NORMALMAP
-            float3 normal = DecodeNormal(tex2D(sNormalMap, iTexCoord));
+        #ifdef DIRLIGHT
+            diff = GetDiffuse(normal, cLightDirPS, lightDir);
         #else
         #else
-            float3 normal = normalize(iNormal);
+            float3 lightVec = (cLightPosPS.xyz - iWorldPos.xyz) * cLightPosPS.w;
+            diff = GetDiffuse(normal, lightVec, lightDir);
         #endif
         #endif
 
 
-        diff = GetDiffuse(normal, iLightVec.xyz, lightDir);
-
         #ifdef SHADOW
         #ifdef SHADOW
-            diff *= GetShadow(iShadowPos, iLightVec.w);
+            diff *= GetShadow(iShadowPos, iWorldPos.w);
         #endif
         #endif
     
     
         #if defined(SPOTLIGHT)
         #if defined(SPOTLIGHT)
@@ -238,18 +215,12 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
         #endif
     
     
         #ifdef SPECULAR
         #ifdef SPECULAR
-            float spec = GetSpecular(normal, iEyeVec, lightDir, cMatSpecColor.a);
+            float spec = GetSpecular(normal, cCameraPosPS - iWorldPos.xyz, lightDir, cMatSpecColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
         #else
         #else
             finalColor = diff * lightColor * diffColor.rgb;
             finalColor = diff * lightColor * diffColor.rgb;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iLightVec.w, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iLightVec.w);
-        #endif
-    
         #ifdef AMBIENT
         #ifdef AMBIENT
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cMatEmissiveColor;
             finalColor += cMatEmissiveColor;
@@ -259,35 +230,16 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
         #endif
     #elif defined(PREPASS)
     #elif defined(PREPASS)
         // Fill light pre-pass G-Buffer
         // Fill light pre-pass G-Buffer
-        #ifdef NORMALMAP
-            float3x3 tbn = float3x3(iTangent, iBitangent, iNormal);
-            float3 normal = mul(DecodeNormal(tex2D(sNormalMap, iTexCoord.xy)), tbn);
-        #else
-            float3 normal = iNormal;
-        #endif
-
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
         oColor = float4(normal * 0.5 + 0.5, specPower);
         oColor = float4(normal * 0.5 + 0.5, specPower);
-        oDepth = iVertexLight.a;
+        oDepth = iWorldPos.w;
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
         // Fill deferred G-buffer
         // Fill deferred G-buffer
-        #ifdef NORMALMAP
-            float3x3 tbn = float3x3(iTangent, iBitangent, iNormal);
-            float3 normal = mul(DecodeNormal(tex2D(sNormalMap, iTexCoord)), tbn);
-        #else
-            float3 normal = iNormal;
-        #endif
-
-        // If using SM2, light volume shader may not have instructions left to normalize the normal. Therefore do it here
-        #if !defined(SM3) || defined(ENVCUBEMAP)
-            normal = normalize(normal);
-        #endif
-
         float specIntensity = specColor.g;
         float specIntensity = specColor.g;
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
-        float3 finalColor = iVertexLight.rgb * diffColor.rgb;
+        float3 finalColor = iVertexLight * diffColor.rgb;
         #ifdef AO
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
@@ -299,24 +251,18 @@ void PS(float2 iTexCoord : TEXCOORD0,
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * diffColor.rgb;
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * diffColor.rgb;
         #endif
         #endif
         #ifdef EMISSIVEMAP
         #ifdef EMISSIVEMAP
-            finalColor += cMatEmissiveColor * tex2D(sEmissiveMap, iTexCoord).rgb;
+            finalColor += cMatEmissiveColor * tex2D(sEmissiveMap, iTexCoord.xy).rgb;
         #else
         #else
             finalColor += cMatEmissiveColor;
             finalColor += cMatEmissiveColor;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iVertexLight.a, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iVertexLight.a);
-        #endif
-
         oColor = float4(GetFog(finalColor, fogFactor), 1.0);
         oColor = float4(GetFog(finalColor, fogFactor), 1.0);
         oAlbedo = fogFactor * float4(diffColor.rgb, specIntensity);
         oAlbedo = fogFactor * float4(diffColor.rgb, specIntensity);
         oNormal = float4(normal * 0.5 + 0.5, specPower);
         oNormal = float4(normal * 0.5 + 0.5, specPower);
-        oDepth = iVertexLight.a;
+        oDepth = iWorldPos.w;
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        float3 finalColor = iVertexLight.rgb * diffColor.rgb;
+        float3 finalColor = iVertexLight * diffColor.rgb;
         #ifdef AO
         #ifdef AO
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             // If using AO, the vertex light ambient is black, calculate occluded ambient here
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * cAmbientColor * diffColor.rgb;
@@ -332,30 +278,17 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
         #endif
 
 
         #ifdef ENVCUBEMAP
         #ifdef ENVCUBEMAP
-            #ifdef NORMALMAP
-                float3x3 tbn = float3x3(iTangent, iBitangent, iNormal);
-                float3 normal = mul(DecodeNormal(tex2D(sNormalMap, iTexCoord)), tbn);
-            #else
-                float3 normal = iNormal;
-            #endif
-            normal = normalize(normal);
             finalColor += cMatEnvMapColor * texCUBE(sEnvCubeMap, reflect(iReflectionVec, normal)).rgb;
             finalColor += cMatEnvMapColor * texCUBE(sEnvCubeMap, reflect(iReflectionVec, normal)).rgb;
         #endif
         #endif
         #ifdef LIGHTMAP
         #ifdef LIGHTMAP
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * diffColor.rgb;
             finalColor += tex2D(sEmissiveMap, iTexCoord2).rgb * diffColor.rgb;
         #endif
         #endif
         #ifdef EMISSIVEMAP
         #ifdef EMISSIVEMAP
-            finalColor += cMatEmissiveColor * tex2D(sEmissiveMap, iTexCoord).rgb;
+            finalColor += cMatEmissiveColor * tex2D(sEmissiveMap, iTexCoord.xy).rgb;
         #else
         #else
             finalColor += cMatEmissiveColor;
             finalColor += cMatEmissiveColor;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iVertexLight.a, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iVertexLight.a);
-        #endif
-
         oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
         oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
     #endif
     #endif
 }
 }

+ 1 - 1
Bin/CoreData/Shaders/HLSL/PrepassLight.hlsl

@@ -89,7 +89,7 @@ void PS(
         float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
         float4 spotPos = mul(projWorldPos, cLightMatricesPS[0]);
         lightColor = spotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
         lightColor = spotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, spotPos).rgb * cLightColor.rgb : 0.0;
     #elif defined(CUBEMASK)
     #elif defined(CUBEMASK)
-        lightColor = texCUBE(sLightCubeMap, mul(lightVec, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
+        lightColor = texCUBE(sLightCubeMap, mul(-lightVec, (float3x3)cLightMatricesPS[0])).rgb * cLightColor.rgb;
     #else
     #else
         lightColor = cLightColor.rgb;
         lightColor = cLightColor.rgb;
     #endif
     #endif

+ 1 - 1
Bin/CoreData/Shaders/HLSL/Samplers.hlsl

@@ -36,7 +36,7 @@ float3 DecodeNormal(float4 normalInput)
         normal.z = sqrt(max(1.0 - dot(normal.xy, normal.xy), 0.0));
         normal.z = sqrt(max(1.0 - dot(normal.xy, normal.xy), 0.0));
         return normal;
         return normal;
     #else
     #else
-        return normalize(normalInput.rgb * 2.0 - 1.0);
+        return normalInput.rgb * 2.0 - 1.0;
     #endif
     #endif
 }
 }
 #endif
 #endif

+ 46 - 78
Bin/CoreData/Shaders/HLSL/TerrainBlend.hlsl

@@ -26,15 +26,9 @@ void VS(float4 iPos : POSITION,
         float2 iSize : TEXCOORD1,
         float2 iSize : TEXCOORD1,
     #endif
     #endif
     out float2 oTexCoord : TEXCOORD0,
     out float2 oTexCoord : TEXCOORD0,
-    #ifdef HEIGHTFOG
-        out float3 oWorldPos : TEXCOORD8,
-    #endif
-    out float3 oNormal : TEXCOORD2,
+    out float3 oNormal : TEXCOORD1,
+    out float4 oWorldPos : TEXCOORD2,
     #ifdef PERPIXEL
     #ifdef PERPIXEL
-        out float4 oLightVec : TEXCOORD1,
-        #ifdef SPECULAR
-            out float3 oEyeVec : TEXCOORD3,
-        #endif
         #ifdef SHADOW
         #ifdef SHADOW
             out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
             out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
         #endif
         #endif
@@ -45,33 +39,29 @@ void VS(float4 iPos : POSITION,
             out float3 oCubeMaskVec : TEXCOORD5,
             out float3 oCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        out float4 oVertexLight : TEXCOORD1,
-        out float4 oScreenPos : TEXCOORD3,
-    #endif
-    #ifdef VERTEXCOLOR
-        out float4 oColor : COLOR0,
+        out float3 oVertexLight : TEXCOORD4,
+        out float4 oScreenPos : TEXCOORD5,
     #endif
     #endif
     out float4 oPos : POSITION)
     out float4 oPos : POSITION)
 {
 {
     float4x3 modelMatrix = iModelMatrix;
     float4x3 modelMatrix = iModelMatrix;
     float3 worldPos = GetWorldPos(modelMatrix);
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
     oPos = GetClipPos(worldPos);
-    oTexCoord = GetTexCoord(iTexCoord);
     oNormal = GetWorldNormal(modelMatrix);
     oNormal = GetWorldNormal(modelMatrix);
+    oWorldPos = float4(worldPos, GetDepth(oPos));
 
 
-    #ifdef HEIGHTFOG
-        oWorldPos = worldPos;
+    #if defined(NORMALMAP)
+        float3 tangent = GetWorldTangent(modelMatrix);
+        float3 bitangent = cross(tangent, oNormal) * iTangent.w;
+        oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy);
+        oTangent = float4(tangent, bitangent.z);
+    #else
+        oTexCoord = GetTexCoord(iTexCoord);
     #endif
     #endif
 
 
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
-        float4 projWorldPos = float4(worldPos, 1.0);
-
-        #ifdef DIRLIGHT
-            oLightVec = float4(cLightDir, GetDepth(oPos));
-        #else
-            oLightVec = float4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(oPos));
-        #endif
+        float4 projWorldPos = float4(worldPos.xyz, 1.0);
 
 
         #ifdef SHADOW
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             // Shadow projection: transform from world space to shadow space
@@ -84,35 +74,25 @@ void VS(float4 iPos : POSITION,
         #endif
         #endif
 
 
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            oCubeMaskVec = mul(oLightVec.xyz, (float3x3)cLightMatrices[0]);
-        #endif
-
-        #ifdef SPECULAR
-            oEyeVec = cCameraPos - worldPos;
+            oCubeMaskVec = mul(worldPos - cLightPos.xyz, (float3x3)cLightMatrices[0]);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        oVertexLight = float4(GetAmbient(GetZonePos(worldPos)), GetDepth(oPos));
+        oVertexLight = GetAmbient(GetZonePos(worldPos));
 
 
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                oVertexLight.rgb += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
+                oVertexLight += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
         #endif
         #endif
-
+        
         oScreenPos = GetScreenPos(oPos);
         oScreenPos = GetScreenPos(oPos);
     #endif
     #endif
 }
 }
 
 
 void PS(float2 iTexCoord : TEXCOORD0,
 void PS(float2 iTexCoord : TEXCOORD0,
-    #ifdef HEIGHTFOG
-        float3 iWorldPos : TEXCOORD8,
-    #endif
+    float3 iNormal : TEXCOORD1,
+    float4 iWorldPos : TEXCOORD2,
     #ifdef PERPIXEL
     #ifdef PERPIXEL
-        float4 iLightVec : TEXCOORD1,
-        float3 iNormal : TEXCOORD2,
-        #ifdef SPECULAR
-            float3 iEyeVec : TEXCOORD3,
-        #endif
         #ifdef SHADOW
         #ifdef SHADOW
             float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
             float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
         #endif
         #endif
@@ -123,9 +103,8 @@ void PS(float2 iTexCoord : TEXCOORD0,
             float3 iCubeMaskVec : TEXCOORD5,
             float3 iCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        float4 iVertexLight : TEXCOORD1,
-        float3 iNormal : TEXCOORD2,
-        float4 iScreenPos : TEXCOORD3,
+        float3 iVertexLight : TEXCOORD4,
+        float4 iScreenPos : TEXCOORD5,
     #endif
     #endif
     #ifdef PREPASS
     #ifdef PREPASS
         out float4 oDepth : COLOR1,
         out float4 oDepth : COLOR1,
@@ -148,6 +127,16 @@ void PS(float2 iTexCoord : TEXCOORD0,
     // Get material specular albedo
     // Get material specular albedo
     float3 specColor = cMatSpecColor.rgb;
     float3 specColor = cMatSpecColor.rgb;
 
 
+    // Get normal
+    float3 normal = normalize(iNormal);
+
+    // Get fog factor
+    #ifdef HEIGHTFOG
+        float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y);
+    #else
+        float fogFactor = GetFogFactor(iWorldPos.w);
+    #endif
+
     #if defined(PERPIXEL)
     #if defined(PERPIXEL)
         // Per-pixel forward lighting
         // Per-pixel forward lighting
         float3 lightDir;
         float3 lightDir;
@@ -155,12 +144,15 @@ void PS(float2 iTexCoord : TEXCOORD0,
         float3 finalColor;
         float3 finalColor;
         float diff;
         float diff;
 
 
-        float3 normal = normalize(iNormal);
-        
-        diff = GetDiffuse(normal, iLightVec.xyz, lightDir);
-    
+        #ifdef DIRLIGHT
+            diff = GetDiffuse(normal, cLightDirPS, lightDir);
+        #else
+            float3 lightVec = (cLightPosPS.xyz - iWorldPos.xyz) * cLightPosPS.w;
+            diff = GetDiffuse(normal, lightVec, lightDir);
+        #endif
+
         #ifdef SHADOW
         #ifdef SHADOW
-            diff *= GetShadow(iShadowPos, iLightVec.w);
+            diff *= GetShadow(iShadowPos, iWorldPos.w);
         #endif
         #endif
     
     
         #if defined(SPOTLIGHT)
         #if defined(SPOTLIGHT)
@@ -172,57 +164,39 @@ void PS(float2 iTexCoord : TEXCOORD0,
         #endif
         #endif
     
     
         #ifdef SPECULAR
         #ifdef SPECULAR
-            float spec = GetSpecular(normal, iEyeVec, lightDir, cMatSpecColor.a);
+            float spec = GetSpecular(normal, cCameraPosPS - iWorldPos.xyz, lightDir, cMatSpecColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
             finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
         #else
         #else
             finalColor = diff * lightColor * diffColor.rgb;
             finalColor = diff * lightColor * diffColor.rgb;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iLightVec.w, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iLightVec.w);
-        #endif
-    
         #ifdef AMBIENT
         #ifdef AMBIENT
             finalColor += cAmbientColor * diffColor.rgb;
             finalColor += cAmbientColor * diffColor.rgb;
+            finalColor += cMatEmissiveColor;
             oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
             oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
         #else
         #else
             oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
             oColor = float4(GetLitFog(finalColor, fogFactor), diffColor.a);
         #endif
         #endif
     #elif defined(PREPASS)
     #elif defined(PREPASS)
         // Fill light pre-pass G-Buffer
         // Fill light pre-pass G-Buffer
-        float3 normal = iNormal;
-
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
         oColor = float4(normal * 0.5 + 0.5, specPower);
         oColor = float4(normal * 0.5 + 0.5, specPower);
-        oDepth = iVertexLight.a;
+        oDepth = iWorldPos.w;
     #elif defined(DEFERRED)
     #elif defined(DEFERRED)
         // Fill deferred G-buffer
         // Fill deferred G-buffer
-        float3 normal = iNormal;
-
-        // If using SM2, light volume shader may not have instructions left to normalize the normal. Therefore do it here
-        #if !defined(SM3)
-            normal = normalize(normal);
-        #endif
-
         float specIntensity = specColor.g;
         float specIntensity = specColor.g;
         float specPower = cMatSpecColor.a / 255.0;
         float specPower = cMatSpecColor.a / 255.0;
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iVertexLight.a, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iVertexLight.a);
-        #endif
+        float3 finalColor = iVertexLight * diffColor.rgb;
 
 
-        oColor = float4(GetFog(iVertexLight.rgb * diffColor.rgb, fogFactor), 1.0);
+        oColor = float4(GetFog(finalColor, fogFactor), 1.0);
         oAlbedo = fogFactor * float4(diffColor.rgb, specIntensity);
         oAlbedo = fogFactor * float4(diffColor.rgb, specIntensity);
         oNormal = float4(normal * 0.5 + 0.5, specPower);
         oNormal = float4(normal * 0.5 + 0.5, specPower);
-        oDepth = iVertexLight.a;
+        oDepth = iWorldPos.w;
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        float3 finalColor = iVertexLight.rgb * diffColor.rgb;
+        float3 finalColor = iVertexLight * diffColor.rgb;
 
 
         #ifdef MATERIAL
         #ifdef MATERIAL
             // Add light pre-pass accumulation result
             // Add light pre-pass accumulation result
@@ -233,12 +207,6 @@ void PS(float2 iTexCoord : TEXCOORD0,
             finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
             finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
         #endif
         #endif
 
 
-        #ifdef HEIGHTFOG
-            float fogFactor = GetHeightFogFactor(iVertexLight.a, iWorldPos.y);
-        #else
-            float fogFactor = GetFogFactor(iVertexLight.a);
-        #endif
-
         oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
         oColor = float4(GetFog(finalColor, fogFactor), diffColor.a);
     #endif
     #endif
 }
 }

+ 1 - 0
Bin/CoreData/Shaders/HLSL/Uniforms.hlsl

@@ -31,6 +31,7 @@ uniform float4x4 cLightMatrices[4];
 #ifdef COMPILEPS
 #ifdef COMPILEPS
 // Pixel shader uniforms
 // Pixel shader uniforms
 uniform float3 cAmbientColor;
 uniform float3 cAmbientColor;
+uniform float3 cCameraPosPS;
 uniform float cDeltaTimePS;
 uniform float cDeltaTimePS;
 uniform float cElapsedTimePS;
 uniform float cElapsedTimePS;
 uniform float4 cFogParams;
 uniform float4 cFogParams;

+ 7 - 15
Bin/CoreData/Shaders/HLSL/Unlit.hlsl

@@ -19,10 +19,7 @@ void VS(float4 iPos : POSITION,
         float2 iSize : TEXCOORD1,
         float2 iSize : TEXCOORD1,
     #endif
     #endif
     out float2 oTexCoord : TEXCOORD0,
     out float2 oTexCoord : TEXCOORD0,
-    out float oDepth : TEXCOORD1,
-    #ifdef HEIGHTFOG
-        out float3 oWorldPos : TEXCOORD8,
-    #endif
+    out float4 oWorldPos : TEXCOORD2,
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         out float4 oColor : COLOR0,
         out float4 oColor : COLOR0,
     #endif
     #endif
@@ -32,11 +29,7 @@ void VS(float4 iPos : POSITION,
     float3 worldPos = GetWorldPos(modelMatrix);
     float3 worldPos = GetWorldPos(modelMatrix);
     oPos = GetClipPos(worldPos);
     oPos = GetClipPos(worldPos);
     oTexCoord = GetTexCoord(iTexCoord);
     oTexCoord = GetTexCoord(iTexCoord);
-    oDepth = GetDepth(oPos);
-
-    #ifdef HEIGHTFOG
-        oWorldPos = worldPos;
-    #endif
+    oWorldPos = float4(worldPos, GetDepth(oPos));
 
 
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         oColor = iColor;
         oColor = iColor;
@@ -44,10 +37,7 @@ void VS(float4 iPos : POSITION,
 }
 }
 
 
 void PS(float2 iTexCoord : TEXCOORD0,
 void PS(float2 iTexCoord : TEXCOORD0,
-    float iDepth : TEXCOORD1,
-    #ifdef HEIGHTFOG
-        float3 iWorldPos : TEXCOORD8,
-    #endif
+    float4 iWorldPos: TEXCOORD2,
     #ifdef VERTEXCOLOR
     #ifdef VERTEXCOLOR
         float4 iColor : COLOR0,
         float4 iColor : COLOR0,
     #endif
     #endif
@@ -61,6 +51,7 @@ void PS(float2 iTexCoord : TEXCOORD0,
     #endif
     #endif
     out float4 oColor : COLOR0)
     out float4 oColor : COLOR0)
 {
 {
+    // Get material diffuse albedo
     #ifdef DIFFMAP
     #ifdef DIFFMAP
         float4 diffColor = cMatDiffColor * tex2D(sDiffMap, iTexCoord);
         float4 diffColor = cMatDiffColor * tex2D(sDiffMap, iTexCoord);
         #ifdef ALPHAMASK
         #ifdef ALPHAMASK
@@ -75,10 +66,11 @@ void PS(float2 iTexCoord : TEXCOORD0,
         diffColor *= iColor;
         diffColor *= iColor;
     #endif
     #endif
 
 
+    // Get fog factor
     #ifdef HEIGHTFOG
     #ifdef HEIGHTFOG
-        float fogFactor = GetHeightFogFactor(iDepth, iWorldPos.y);
+        float fogFactor = GetHeightFogFactor(iWorldPos.w, iWorldPos.y);
     #else
     #else
-        float fogFactor = GetFogFactor(iDepth);
+        float fogFactor = GetFogFactor(iWorldPos.w);
     #endif
     #endif
 
 
     #if defined(PREPASS)
     #if defined(PREPASS)

+ 39 - 52
Bin/CoreData/Shaders/HLSL/Vegetation.hlsl

@@ -13,7 +13,7 @@ uniform float2 cWindWorldSpacing;
 void VS(float4 iPos : POSITION,
 void VS(float4 iPos : POSITION,
     float3 iNormal : NORMAL,
     float3 iNormal : NORMAL,
     float2 iTexCoord : TEXCOORD0,
     float2 iTexCoord : TEXCOORD0,
-    #ifdef LIGHTMAP
+    #if defined(LIGHTMAP) || defined(AO)
         float2 iTexCoord2 : TEXCOORD1,
         float2 iTexCoord2 : TEXCOORD1,
     #endif
     #endif
     #ifdef NORMALMAP
     #ifdef NORMALMAP
@@ -29,15 +29,15 @@ void VS(float4 iPos : POSITION,
     #ifdef BILLBOARD
     #ifdef BILLBOARD
         float2 iSize : TEXCOORD1,
         float2 iSize : TEXCOORD1,
     #endif
     #endif
-    out float2 oTexCoord : TEXCOORD0,
+    #ifndef NORMALMAP
+        out float2 oTexCoord : TEXCOORD0,
+    #else
+        out float4 oTexCoord : TEXCOORD0,
+        out float4 oTangent : TEXCOORD3,
+    #endif
+    out float3 oNormal : TEXCOORD1,
+    out float4 oWorldPos : TEXCOORD2,
     #ifdef PERPIXEL
     #ifdef PERPIXEL
-        out float4 oLightVec : TEXCOORD1,
-        #ifndef NORMALMAP
-            out float3 oNormal : TEXCOORD2,
-        #endif
-        #ifdef SPECULAR
-            out float3 oEyeVec : TEXCOORD3,
-        #endif
         #ifdef SHADOW
         #ifdef SHADOW
             out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
             out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
         #endif
         #endif
@@ -48,16 +48,14 @@ void VS(float4 iPos : POSITION,
             out float3 oCubeMaskVec : TEXCOORD5,
             out float3 oCubeMaskVec : TEXCOORD5,
         #endif
         #endif
     #else
     #else
-        out float4 oVertexLight : TEXCOORD1,
-        out float3 oNormal : TEXCOORD2,
-        #ifdef NORMALMAP
-            out float3 oTangent : TEXCOORD3,
-            out float3 oBitangent : TEXCOORD4,
-        #endif
+        out float3 oVertexLight : TEXCOORD4,
         out float4 oScreenPos : TEXCOORD5,
         out float4 oScreenPos : TEXCOORD5,
-    #endif
-    #ifdef HEIGHTFOG
-        out float3 oWorldPos : TEXCOORD8,
+        #ifdef ENVCUBEMAP
+            out float3 oReflectionVec : TEXCOORD6,
+        #endif
+        #if defined(LIGHTMAP) || defined(AO)
+            out float2 oTexCoord2 : TEXCOORD7,
+        #endif
     #endif
     #endif
     out float4 oPos : POSITION)
     out float4 oPos : POSITION)
 {
 {
@@ -71,34 +69,22 @@ void VS(float4 iPos : POSITION,
     worldPos.z -= windStrength * cos(windPeriod);
     worldPos.z -= windStrength * cos(windPeriod);
 
 
     oPos = GetClipPos(worldPos);
     oPos = GetClipPos(worldPos);
-    oTexCoord = GetTexCoord(iTexCoord);
-
-    #ifdef HEIGHTFOG
-        oWorldPos = worldPos;
-    #endif
-
-    #if defined(PERPIXEL) && defined(NORMALMAP)
-        float3 oNormal;
-        float3 oTangent;
-        float3 oBitangent;
-    #endif
-
     oNormal = GetWorldNormal(modelMatrix);
     oNormal = GetWorldNormal(modelMatrix);
+    oWorldPos = float4(worldPos, GetDepth(oPos));
+
     #ifdef NORMALMAP
     #ifdef NORMALMAP
-        oTangent = GetWorldTangent(modelMatrix);
-        oBitangent = cross(oTangent, oNormal) * iTangent.w;
+        float3 tangent = GetWorldTangent(modelMatrix);
+        float3 bitangent = cross(tangent, oNormal) * iTangent.w;
+        oTexCoord = float4(GetTexCoord(iTexCoord), bitangent.xy);
+        oTangent = float4(tangent, bitangent.z);
+    #else
+        oTexCoord = GetTexCoord(iTexCoord);
     #endif
     #endif
 
 
     #ifdef PERPIXEL
     #ifdef PERPIXEL
         // Per-pixel forward lighting
         // Per-pixel forward lighting
-        float4 projWorldPos = float4(worldPos, 1.0);
+        float4 projWorldPos = float4(worldPos.xyz, 1.0);
 
 
-        #ifdef DIRLIGHT
-            oLightVec = float4(cLightDir, GetDepth(oPos));
-        #else
-            oLightVec = float4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(oPos));
-        #endif
-    
         #ifdef SHADOW
         #ifdef SHADOW
             // Shadow projection: transform from world space to shadow space
             // Shadow projection: transform from world space to shadow space
             GetShadowPos(projWorldPos, oShadowPos);
             GetShadowPos(projWorldPos, oShadowPos);
@@ -110,27 +96,28 @@ void VS(float4 iPos : POSITION,
         #endif
         #endif
 
 
         #ifdef POINTLIGHT
         #ifdef POINTLIGHT
-            oCubeMaskVec = mul(oLightVec.xyz, (float3x3)cLightMatrices[0]);
-        #endif
-
-        #ifdef NORMALMAP
-            float3x3 tbn = float3x3(oTangent, oBitangent, oNormal);
-            oLightVec.xyz = mul(tbn, oLightVec.xyz);
-            #ifdef SPECULAR
-                oEyeVec = mul(tbn, cCameraPos - worldPos);
-            #endif
-        #elif defined(SPECULAR)
-            oEyeVec = cCameraPos - worldPos;
+            oCubeMaskVec = mul(cLightPos.xyz - worldPos, (float3x3)cLightMatrices[0]);
         #endif
         #endif
     #else
     #else
         // Ambient & per-vertex lighting
         // Ambient & per-vertex lighting
-        oVertexLight = float4(GetAmbient(GetZonePos(worldPos)), GetDepth(oPos));
+        #if defined(LIGHTMAP) || defined(AO)
+            // If using lightmap, disregard zone ambient light
+            // If using AO, calculate ambient in the PS
+            oVertexLight = float3(0.0, 0.0, 0.0);
+            oTexCoord2 = iTexCoord2;
+        #else
+            oVertexLight = GetAmbient(GetZonePos(worldPos));
+        #endif
 
 
         #ifdef NUMVERTEXLIGHTS
         #ifdef NUMVERTEXLIGHTS
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
             for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
-                oVertexLight.rgb += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
+                oVertexLight += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
         #endif
         #endif
         
         
         oScreenPos = GetScreenPos(oPos);
         oScreenPos = GetScreenPos(oPos);
+
+        #ifdef ENVCUBEMAP
+            oReflectionVec = worldPos - cCameraPos;
+        #endif
     #endif
     #endif
 }
 }

+ 1 - 1
Bin/CoreData/Techniques/DiffNormalEnvCube.xml

@@ -2,7 +2,7 @@
     <pass name="base" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="NORMALMAP ENVCUBEMAP" />
     <pass name="base" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="NORMALMAP ENVCUBEMAP" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP" />
-    <pass name="material" vsdefines="ENVCUBEMAP" psdefines="MATERIAL ENVCUBEMAP" depthtest="equal" depthwrite="false" />
+    <pass name="material" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="MATERIAL NORMALMAP ENVCUBEMAP" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="DEFERRED NORMALMAP ENVCUBEMAP" />
     <pass name="deferred" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="DEFERRED NORMALMAP ENVCUBEMAP" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />

+ 1 - 1
Bin/CoreData/Techniques/DiffNormalPackedEnvCube.xml

@@ -2,7 +2,7 @@
     <pass name="base" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="NORMALMAP PACKEDNORMAL ENVCUBEMAP" />
     <pass name="base" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="NORMALMAP PACKEDNORMAL ENVCUBEMAP" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP PACKEDNORMAL" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="light" vsdefines="NORMALMAP" psdefines="NORMALMAP PACKEDNORMAL" depthtest="equal" depthwrite="false" blend="add" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP PACKEDNORMAL" />
     <pass name="prepass" vsdefines="NORMALMAP" psdefines="PREPASS NORMALMAP PACKEDNORMAL" />
-    <pass name="material" vsdefines="ENVCUBEMAP" psdefines="MATERIAL ENVCUBEMAP" depthtest="equal" depthwrite="false" />
+    <pass name="material" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="MATERIAL NORMALMAP PACKEDNORMAL ENVCUBEMAP" depthtest="equal" depthwrite="false" />
     <pass name="deferred" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="DEFERRED NORMALMAP PACKEDNORMAL ENVCUBEMAP" />
     <pass name="deferred" vsdefines="NORMALMAP ENVCUBEMAP" psdefines="DEFERRED NORMALMAP PACKEDNORMAL ENVCUBEMAP" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="depth" vs="Depth" ps="Depth" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />
     <pass name="shadow" vs="Shadow" ps="Shadow" />

+ 6 - 7
Bin/Data/Scripts/Editor.as

@@ -17,8 +17,8 @@
 String configPath;
 String configPath;
 String configFileName;
 String configFileName;
 
 
-// If loaded in OpenGL mode, remember the instancing setting in config instead of auto-disabling it
 bool instancingSetting = true;
 bool instancingSetting = true;
+int shadowQualitySetting = 2;
 
 
 void Start()
 void Start()
 {
 {
@@ -178,7 +178,7 @@ void LoadConfig()
         if (renderingElem.HasAttribute("texturequality")) renderer.textureQuality = renderingElem.GetInt("texturequality");
         if (renderingElem.HasAttribute("texturequality")) renderer.textureQuality = renderingElem.GetInt("texturequality");
         if (renderingElem.HasAttribute("materialquality")) renderer.materialQuality = renderingElem.GetInt("materialquality");
         if (renderingElem.HasAttribute("materialquality")) renderer.materialQuality = renderingElem.GetInt("materialquality");
         if (renderingElem.HasAttribute("shadowresolution")) SetShadowResolution(renderingElem.GetInt("shadowresolution"));
         if (renderingElem.HasAttribute("shadowresolution")) SetShadowResolution(renderingElem.GetInt("shadowresolution"));
-        if (renderingElem.HasAttribute("shadowquality")) renderer.shadowQuality = renderingElem.GetInt("shadowquality");
+        if (renderingElem.HasAttribute("shadowquality")) renderer.shadowQuality = shadowQualitySetting = renderingElem.GetInt("shadowquality");
         if (renderingElem.HasAttribute("maxoccludertriangles")) renderer.maxOccluderTriangles = renderingElem.GetInt("maxoccludertriangles");
         if (renderingElem.HasAttribute("maxoccludertriangles")) renderer.maxOccluderTriangles = renderingElem.GetInt("maxoccludertriangles");
         if (renderingElem.HasAttribute("specularlighting")) renderer.specularLighting = renderingElem.GetBool("specularlighting");
         if (renderingElem.HasAttribute("specularlighting")) renderer.specularLighting = renderingElem.GetBool("specularlighting");
         if (renderingElem.HasAttribute("dynamicinstancing")) renderer.dynamicInstancing = instancingSetting = renderingElem.GetBool("dynamicinstancing");
         if (renderingElem.HasAttribute("dynamicinstancing")) renderer.dynamicInstancing = instancingSetting = renderingElem.GetBool("dynamicinstancing");
@@ -264,18 +264,17 @@ void SaveConfig()
     resourcesElem.SetAttribute("importpath", uiImportPath);
     resourcesElem.SetAttribute("importpath", uiImportPath);
     resourcesElem.SetAttribute("recentscenes", Join(uiRecentScenes, ";"));
     resourcesElem.SetAttribute("recentscenes", Join(uiRecentScenes, ";"));
 
 
-    if (renderer !is null)
+    if (renderer !is null && graphics !is null)
     {
     {
         renderingElem.SetInt("texturequality", renderer.textureQuality);
         renderingElem.SetInt("texturequality", renderer.textureQuality);
         renderingElem.SetInt("materialquality", renderer.materialQuality);
         renderingElem.SetInt("materialquality", renderer.materialQuality);
         renderingElem.SetInt("shadowresolution", GetShadowResolution());
         renderingElem.SetInt("shadowresolution", GetShadowResolution());
-        renderingElem.SetInt("shadowquality", renderer.shadowQuality);
         renderingElem.SetInt("maxoccludertriangles", renderer.maxOccluderTriangles);
         renderingElem.SetInt("maxoccludertriangles", renderer.maxOccluderTriangles);
         renderingElem.SetBool("specularlighting", renderer.specularLighting);
         renderingElem.SetBool("specularlighting", renderer.specularLighting);
-    }
-
-    if (graphics !is null)
+        // If Shader Model 3 is not supported, save the remembered instancing & quality settings instead of reduced settings
+        renderingElem.SetInt("shadowquality", graphics.sm3Support ? renderer.shadowQuality : shadowQualitySetting);
         renderingElem.SetBool("dynamicinstancing", graphics.sm3Support ? renderer.dynamicInstancing : instancingSetting);
         renderingElem.SetBool("dynamicinstancing", graphics.sm3Support ? renderer.dynamicInstancing : instancingSetting);
+    }
 
 
     renderingElem.SetBool("framelimiter", engine.maxFps > 0);
     renderingElem.SetBool("framelimiter", engine.maxFps > 0);
 
 

+ 11 - 5
Docs/Reference.dox

@@ -686,12 +686,18 @@ Screen resolution, fullscreen/windowed, vertical sync and hardware multisampling
 
 
 When setting the initial screen mode, Graphics does a few checks:
 When setting the initial screen mode, Graphics does a few checks:
 
 
-- For Direct3D9, the supported shader model is checked. 2 is minimum, but 3 will be used if available. SM2 can be forced by calling \ref Graphics::SetForceSM2 "SetForceSM2()" before setting the initial screen mode.
+- For Direct3D9, the supported shader model is checked. 2 is minimum, but 3 will be used if available. For testing, SM2 can be forced by calling \ref Graphics::SetForceSM2 "SetForceSM2()" before setting the initial screen mode.
 - For OpenGL, version 2.0 with EXT_framebuffer_object, EXT_packed_depth_stencil and EXT_texture_filter_anisotropic extensions is checked for.
 - For OpenGL, version 2.0 with EXT_framebuffer_object, EXT_packed_depth_stencil and EXT_texture_filter_anisotropic extensions is checked for.
 - Is hardware instancing supported? This requires %Shader %Model 3 on Direct3D9 and the ARB_instanced_arrays extension on OpenGL.
 - Is hardware instancing supported? This requires %Shader %Model 3 on Direct3D9 and the ARB_instanced_arrays extension on OpenGL.
-- Are hardware shadow maps supported? Both ATI & NVIDIA style shadow maps can be used. If neither are available, no shadows will be rendered.
+- Are hardware shadow maps supported? Both AMD & NVIDIA style shadow maps can be used. If neither are available, no shadows will be rendered.
 - Are light pre-pass and deferred rendering modes supported? These require sufficient multiple rendertarget support, and R32F texture format support.
 - Are light pre-pass and deferred rendering modes supported? These require sufficient multiple rendertarget support, and R32F texture format support.
 
 
+%Shader model 2 has the following limitations due to limited pixel shader instruction count:
+
+- Directional light shadows support a maximum of 3 cascade splits instead of 4.
+- High quality (4 samples) shadow mapping is not supported.
+- Height fog is not supported.
+
 \section Rendering_Renderer Renderer
 \section Rendering_Renderer Renderer
 
 
 Renderer implements the actual rendering of 3D views each frame, and controls global settings such as texture quality, material quality, specular lighting and shadow map base resolution.
 Renderer implements the actual rendering of 3D views each frame, and controls global settings such as texture quality, material quality, specular lighting and shadow map base resolution.
@@ -723,7 +729,7 @@ In the default render paths, the rendering operations proceed in the following o
 
 
 \section Rendering_Drawable Rendering components
 \section Rendering_Drawable Rendering components
 
 
-The rendering-related components defined by the %Graphics, %UI and Urho2D libraries are:
+The rendering-related components defined by the %Graphics and %UI libraries are:
 
 
 - Octree: spatial partitioning of Drawables for accelerated visibility queries. Needs to be created to the Scene (root node.)
 - Octree: spatial partitioning of Drawables for accelerated visibility queries. Needs to be created to the Scene (root node.)
 - Camera: describes a viewpoint for rendering, including projection parameters (FOV, near/far distance, perspective/orthographic)
 - Camera: describes a viewpoint for rendering, including projection parameters (FOV, near/far distance, perspective/orthographic)
@@ -742,6 +748,8 @@ The rendering-related components defined by the %Graphics, %UI and Urho2D librar
 - Zone: defines ambient light and fog settings for objects inside the zone volume.
 - Zone: defines ambient light and fog settings for objects inside the zone volume.
 - Text3D: text that is rendered into the 3D view.
 - Text3D: text that is rendered into the 3D view.
 
 
+Additionally there are 2D drawable components defined by the \ref Urho2D "Urho2D" library.
+
 \section Rendering_Optimizations Optimizations
 \section Rendering_Optimizations Optimizations
 
 
 The following techniques will be used to reduce the amount of CPU and GPU work when rendering. By default they are all on:
 The following techniques will be used to reduce the amount of CPU and GPU work when rendering. By default they are all on:
@@ -990,10 +998,8 @@ Vertex shader:
 
 
 - NUMVERTEXLIGHTS=1,2,3 or 4: number of vertex lights influencing the object
 - NUMVERTEXLIGHTS=1,2,3 or 4: number of vertex lights influencing the object
 - DIRLIGHT, SPOTLIGHT, POINTLIGHT: a per-pixel forward light is being used. Accompanied by the define PERPIXEL
 - DIRLIGHT, SPOTLIGHT, POINTLIGHT: a per-pixel forward light is being used. Accompanied by the define PERPIXEL
-- SPEC: the per-pixel forward light has specular calculations
 - SHADOW: the per-pixel forward light has shadowing
 - SHADOW: the per-pixel forward light has shadowing
 - SKINNED, INSTANCED, BILLBOARD: choosing the geometry type
 - SKINNED, INSTANCED, BILLBOARD: choosing the geometry type
-- HEIGHTFOG: object's zone has height fog mode
 
 
 Pixel shader:
 Pixel shader:
 
 

+ 1 - 0
Source/Engine/Graphics/Batch.cpp

@@ -234,6 +234,7 @@ void Batch::Prepare(View* view, bool setModelTransform) const
         
         
         graphics->SetShaderParameter(VSP_CAMERAPOS, cameraEffectiveTransform.Translation());
         graphics->SetShaderParameter(VSP_CAMERAPOS, cameraEffectiveTransform.Translation());
         graphics->SetShaderParameter(VSP_CAMERAROT, cameraEffectiveTransform.RotationMatrix());
         graphics->SetShaderParameter(VSP_CAMERAROT, cameraEffectiveTransform.RotationMatrix());
+        graphics->SetShaderParameter(PSP_CAMERAPOS, cameraEffectiveTransform.Translation());
         
         
         float nearClip = camera_->GetNearClip();
         float nearClip = camera_->GetNearClip();
         float farClip = camera_->GetFarClip();
         float farClip = camera_->GetFarClip();

+ 1 - 0
Source/Engine/Graphics/GraphicsDefs.cpp

@@ -52,6 +52,7 @@ StringHash VSP_LIGHTMATRICES("LightMatrices");
 StringHash VSP_SKINMATRICES("SkinMatrices");
 StringHash VSP_SKINMATRICES("SkinMatrices");
 StringHash VSP_VERTEXLIGHTS("VertexLights");
 StringHash VSP_VERTEXLIGHTS("VertexLights");
 StringHash PSP_AMBIENTCOLOR("AmbientColor");
 StringHash PSP_AMBIENTCOLOR("AmbientColor");
+StringHash PSP_CAMERAPOS("CameraPosPS");
 StringHash PSP_DELTATIME("DeltaTimePS");
 StringHash PSP_DELTATIME("DeltaTimePS");
 StringHash PSP_ELAPSEDTIME("ElapsedTimePS");
 StringHash PSP_ELAPSEDTIME("ElapsedTimePS");
 StringHash PSP_FOGCOLOR("FogColor");
 StringHash PSP_FOGCOLOR("FogColor");

+ 1 - 0
Source/Engine/Graphics/GraphicsDefs.h

@@ -221,6 +221,7 @@ extern StringHash VSP_LIGHTMATRICES;
 extern StringHash VSP_SKINMATRICES;
 extern StringHash VSP_SKINMATRICES;
 extern StringHash VSP_VERTEXLIGHTS;
 extern StringHash VSP_VERTEXLIGHTS;
 extern StringHash PSP_AMBIENTCOLOR;
 extern StringHash PSP_AMBIENTCOLOR;
+extern StringHash PSP_CAMERAPOS;
 extern StringHash PSP_DELTATIME;
 extern StringHash PSP_DELTATIME;
 extern StringHash PSP_ELAPSEDTIME;
 extern StringHash PSP_ELAPSEDTIME;
 extern StringHash PSP_FOGCOLOR;
 extern StringHash PSP_FOGCOLOR;

+ 28 - 0
Source/Engine/Graphics/Light.cpp

@@ -24,6 +24,7 @@
 #include "Camera.h"
 #include "Camera.h"
 #include "Context.h"
 #include "Context.h"
 #include "DebugRenderer.h"
 #include "DebugRenderer.h"
+#include "Graphics.h"
 #include "Light.h"
 #include "Light.h"
 #include "Node.h"
 #include "Node.h"
 #include "OctreeQuery.h"
 #include "OctreeQuery.h"
@@ -386,6 +387,33 @@ Frustum Light::GetFrustum() const
     return ret;
     return ret;
 }
 }
 
 
+int Light::GetNumShadowSplits() const
+{
+    int ret = 1;
+    
+    if (shadowCascade_.splits_[1] > shadowCascade_.splits_[0])
+    {
+        ++ret;
+        if (shadowCascade_.splits_[2] > shadowCascade_.splits_[1])
+        {
+            ++ret;
+            if (shadowCascade_.splits_[3] > shadowCascade_.splits_[2])
+                ++ret;
+        }
+    }
+    
+    ret = Min(ret, MAX_CASCADE_SPLITS);
+    // Shader Model 2 can only support 3 splits max. due to pixel shader instruction count limits
+    if (ret == 4)
+    {
+        Graphics* graphics = GetSubsystem<Graphics>();
+        if (graphics && !graphics->GetSM3Support())
+            --ret;
+    }
+    
+    return ret;
+}
+
 Matrix3x4 Light::GetDirLightTransform(Camera* camera, bool getNearQuad)
 Matrix3x4 Light::GetDirLightTransform(Camera* camera, bool getNearQuad)
 {
 {
     if (!camera)
     if (!camera)

+ 2 - 0
Source/Engine/Graphics/Light.h

@@ -250,6 +250,8 @@ public:
     Texture* GetShapeTexture() const { return shapeTexture_; }
     Texture* GetShapeTexture() const { return shapeTexture_; }
     /// Return spotlight frustum.
     /// Return spotlight frustum.
     Frustum GetFrustum() const;
     Frustum GetFrustum() const;
+    /// Return number of shadow map cascade splits for a directional light, considering also graphics API limitations.
+    int GetNumShadowSplits() const;
     /// Return whether light has negative (darkening) color.
     /// Return whether light has negative (darkening) color.
     bool IsNegative() const { return GetEffectiveColor().SumRGB() < 0.0f; }
     bool IsNegative() const { return GetEffectiveColor().SumRGB() < 0.0f; }
     
     

+ 27 - 56
Source/Engine/Graphics/Renderer.cpp

@@ -200,15 +200,9 @@ static const char* lightVSVariations[] =
     "PERPIXEL DIRLIGHT ",
     "PERPIXEL DIRLIGHT ",
     "PERPIXEL SPOTLIGHT ",
     "PERPIXEL SPOTLIGHT ",
     "PERPIXEL POINTLIGHT ",
     "PERPIXEL POINTLIGHT ",
-    "PERPIXEL DIRLIGHT SPECULAR ",
-    "PERPIXEL SPOTLIGHT SPECULAR ",
-    "PERPIXEL POINTLIGHT SPECULAR ",
     "PERPIXEL DIRLIGHT SHADOW ",
     "PERPIXEL DIRLIGHT SHADOW ",
     "PERPIXEL SPOTLIGHT SHADOW ",
     "PERPIXEL SPOTLIGHT SHADOW ",
     "PERPIXEL POINTLIGHT SHADOW ",
     "PERPIXEL POINTLIGHT SHADOW ",
-    "PERPIXEL DIRLIGHT SPECULAR SHADOW ",
-    "PERPIXEL SPOTLIGHT SPECULAR SHADOW ",
-    "PERPIXEL POINTLIGHT SPECULAR SHADOW "
 };
 };
 
 
 static const char* vertexLightVSVariations[] =
 static const char* vertexLightVSVariations[] =
@@ -268,7 +262,6 @@ Renderer::Renderer(Context* context) :
     shadowMapSize_(1024),
     shadowMapSize_(1024),
     shadowQuality_(SHADOWQUALITY_HIGH_16BIT),
     shadowQuality_(SHADOWQUALITY_HIGH_16BIT),
     maxShadowMaps_(1),
     maxShadowMaps_(1),
-    maxShadowCascades_(MAX_CASCADE_SPLITS),
     minInstances_(2),
     minInstances_(2),
     maxInstanceTriangles_(500),
     maxInstanceTriangles_(500),
     maxSortedInstances_(1000),
     maxSortedInstances_(1000),
@@ -404,6 +397,9 @@ void Renderer::SetShadowQuality(int quality)
         quality |= SHADOWQUALITY_HIGH_16BIT;
         quality |= SHADOWQUALITY_HIGH_16BIT;
     if (!graphics_->GetHiresShadowMapFormat())
     if (!graphics_->GetHiresShadowMapFormat())
         quality &= SHADOWQUALITY_HIGH_16BIT;
         quality &= SHADOWQUALITY_HIGH_16BIT;
+    // Shader Model 2 can not reliably support four samples without exceeding pixel shader instruction count limit
+    if (!graphics_->GetSM3Support())
+        quality &= ~SHADOWQUALITY_HIGH_16BIT;
     
     
     if (quality != shadowQuality_)
     if (quality != shadowQuality_)
     {
     {
@@ -434,17 +430,6 @@ void Renderer::SetMaxShadowMaps(int shadowMaps)
     }
     }
 }
 }
 
 
-void Renderer::SetMaxShadowCascades(int cascades)
-{
-    cascades = Clamp(cascades, 1, MAX_CASCADE_SPLITS);
-    
-    if (cascades != maxShadowCascades_)
-    {
-        maxShadowCascades_ = cascades;
-        ResetShadowMaps();
-    }
-}
-
 void Renderer::SetDynamicInstancing(bool enable)
 void Renderer::SetDynamicInstancing(bool enable)
 {
 {
     if (!instancingBuffer_)
     if (!instancingBuffer_)
@@ -839,9 +824,10 @@ Texture2D* Renderer::GetShadowMap(Light* light, Camera* camera, unsigned viewWid
     // Adjust the size for directional or point light shadow map atlases
     // Adjust the size for directional or point light shadow map atlases
     if (type == LIGHT_DIRECTIONAL)
     if (type == LIGHT_DIRECTIONAL)
     {
     {
-        if (maxShadowCascades_ > 1)
+        unsigned numSplits = light->GetNumShadowSplits();
+        if (numSplits > 1)
             width *= 2;
             width *= 2;
-        if (maxShadowCascades_ > 2)
+        if (numSplits > 2)
             height *= 2;
             height *= 2;
     }
     }
     else if (type == LIGHT_POINT)
     else if (type == LIGHT_POINT)
@@ -1062,7 +1048,8 @@ void Renderer::SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows)
     // Make sure shaders are loaded now
     // Make sure shaders are loaded now
     if (vertexShaders.Size() && pixelShaders.Size())
     if (vertexShaders.Size() && pixelShaders.Size())
     {
     {
-        bool heightFog = graphics_->GetSM3Support() && batch.zone_ && batch.zone_->GetHeightFog();
+        // Height fog is not supported on Shader Model 2 due to possibly exceeding pixel shader instruction limit
+        bool heightFog = batch.zone_ && batch.zone_->GetHeightFog() && graphics_->GetSM3Support();
         
         
         // If instancing is not supported, but was requested, or the object is too large to be instanced,
         // If instancing is not supported, but was requested, or the object is too large to be instanced,
         // choose static geometry vertex shader instead
         // choose static geometry vertex shader instead
@@ -1092,10 +1079,7 @@ void Renderer::SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows)
             
             
             bool materialHasSpecular = batch.material_ ? batch.material_->GetSpecular() : true;
             bool materialHasSpecular = batch.material_ ? batch.material_->GetSpecular() : true;
             if (specularLighting_ && light->GetSpecularIntensity() > 0.0f && materialHasSpecular)
             if (specularLighting_ && light->GetSpecularIntensity() > 0.0f && materialHasSpecular)
-            {
-                vsi += LVS_SPEC;
                 psi += LPS_SPEC;
                 psi += LPS_SPEC;
-            }
             if (allowShadows && lightQueue->shadowMap_)
             if (allowShadows && lightQueue->shadowMap_)
             {
             {
                 vsi += LVS_SHADOW;
                 vsi += LVS_SHADOW;
@@ -1123,10 +1107,7 @@ void Renderer::SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows)
             }
             }
             
             
             if (heightFog)
             if (heightFog)
-            {
-                vsi += MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS;
                 psi += MAX_LIGHT_PS_VARIATIONS;
                 psi += MAX_LIGHT_PS_VARIATIONS;
-            }
             
             
             batch.vertexShader_ = vertexShaders[vsi];
             batch.vertexShader_ = vertexShaders[vsi];
             batch.pixelShader_ = pixelShaders[psi];
             batch.pixelShader_ = pixelShaders[psi];
@@ -1141,17 +1122,11 @@ void Renderer::SetBatchShaders(Batch& batch, Technique* tech, bool allowShadows)
                     numVertexLights = batch.lightQueue_->vertexLights_.Size();
                     numVertexLights = batch.lightQueue_->vertexLights_.Size();
                 
                 
                 unsigned vsi = batch.geometryType_ * MAX_VERTEXLIGHT_VS_VARIATIONS + numVertexLights;
                 unsigned vsi = batch.geometryType_ * MAX_VERTEXLIGHT_VS_VARIATIONS + numVertexLights;
-                if (heightFog)
-                    vsi += MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS;
-                
                 batch.vertexShader_ = vertexShaders[vsi];
                 batch.vertexShader_ = vertexShaders[vsi];
             }
             }
             else
             else
             {
             {
                 unsigned vsi = batch.geometryType_;
                 unsigned vsi = batch.geometryType_;
-                if (heightFog)
-                    vsi += MAX_GEOMETRYTYPES;
-                
                 batch.vertexShader_ = vertexShaders[vsi];
                 batch.vertexShader_ = vertexShaders[vsi];
             }
             }
             
             
@@ -1430,6 +1405,8 @@ void Renderer::Initialize()
     
     
     if (!graphics_->GetShadowMapFormat())
     if (!graphics_->GetShadowMapFormat())
         drawShadows_ = false;
         drawShadows_ = false;
+    // Validate the shadow quality level
+    SetShadowQuality(shadowQuality_);
     
     
     defaultLightRamp_ = cache->GetResource<Texture2D>("Textures/Ramp.png");
     defaultLightRamp_ = cache->GetResource<Texture2D>("Textures/Ramp.png");
     defaultLightSpot_ = cache->GetResource<Texture2D>("Textures/Spot.png");
     defaultLightSpot_ = cache->GetResource<Texture2D>("Textures/Spot.png");
@@ -1503,31 +1480,29 @@ void Renderer::LoadPassShaders(Technique* tech, StringHash type)
     if (pass->GetLightingMode() == LIGHTING_PERPIXEL)
     if (pass->GetLightingMode() == LIGHTING_PERPIXEL)
     {
     {
         // Load forward pixel lit variations
         // Load forward pixel lit variations
-        vertexShaders.Resize(MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS * 2);
+        vertexShaders.Resize(MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS);
         pixelShaders.Resize(MAX_LIGHT_PS_VARIATIONS * 2);
         pixelShaders.Resize(MAX_LIGHT_PS_VARIATIONS * 2);
         
         
-        for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS * 2; ++j)
+        for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS; ++j)
         {
         {
-            unsigned k = j % (MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS);
-            unsigned h = j / (MAX_GEOMETRYTYPES * MAX_LIGHT_VS_VARIATIONS);
-            unsigned g = k / MAX_LIGHT_VS_VARIATIONS;
-            unsigned l = k % MAX_LIGHT_VS_VARIATIONS;
+            unsigned g = j / MAX_LIGHT_VS_VARIATIONS;
+            unsigned l = j % MAX_LIGHT_VS_VARIATIONS;
             
             
             vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
             vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
-                lightVSVariations[l] + geometryVSVariations[g] + heightFogVariations[h]);
+                lightVSVariations[l] + geometryVSVariations[g]);
         }
         }
         for (unsigned j = 0; j < MAX_LIGHT_PS_VARIATIONS * 2; ++j)
         for (unsigned j = 0; j < MAX_LIGHT_PS_VARIATIONS * 2; ++j)
         {
         {
-            unsigned k = j % MAX_LIGHT_PS_VARIATIONS;
+            unsigned l = j % MAX_LIGHT_PS_VARIATIONS;
             unsigned h = j / MAX_LIGHT_PS_VARIATIONS;
             unsigned h = j / MAX_LIGHT_PS_VARIATIONS;
-            if (k & LPS_SHADOW)
+            if (l & LPS_SHADOW)
             {
             {
                 pixelShaders[j] = graphics_->GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines() + " " +
                 pixelShaders[j] = graphics_->GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines() + " " +
-                    lightPSVariations[k] + shadowVariations[shadows] + heightFogVariations[h]);
+                    lightPSVariations[l] + shadowVariations[shadows] + heightFogVariations[h]);
             }
             }
             else
             else
                 pixelShaders[j] = graphics_->GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines() + " " +
                 pixelShaders[j] = graphics_->GetShader(PS, pass->GetPixelShader(), pass->GetPixelShaderDefines() + " " +
-                    lightPSVariations[k] + heightFogVariations[h]);
+                    lightPSVariations[l] + heightFogVariations[h]);
         }
         }
     }
     }
     else
     else
@@ -1535,26 +1510,22 @@ void Renderer::LoadPassShaders(Technique* tech, StringHash type)
         // Load vertex light variations
         // Load vertex light variations
         if (pass->GetLightingMode() == LIGHTING_PERVERTEX)
         if (pass->GetLightingMode() == LIGHTING_PERVERTEX)
         {
         {
-            vertexShaders.Resize(MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS * 2);
-            for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS * 2; ++j)
+            vertexShaders.Resize(MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS);
+            for (unsigned j = 0; j < MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS; ++j)
             {
             {
-                unsigned k = j % (MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS);
-                unsigned h = j / (MAX_GEOMETRYTYPES * MAX_VERTEXLIGHT_VS_VARIATIONS);
-                unsigned g = k / MAX_VERTEXLIGHT_VS_VARIATIONS;
-                unsigned l = k % MAX_VERTEXLIGHT_VS_VARIATIONS;
+                unsigned g = j / MAX_VERTEXLIGHT_VS_VARIATIONS;
+                unsigned l = j % MAX_VERTEXLIGHT_VS_VARIATIONS;
                 vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
                 vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
-                    vertexLightVSVariations[l] + geometryVSVariations[g] + heightFogVariations[h]);
+                    vertexLightVSVariations[l] + geometryVSVariations[g]);
             }
             }
         }
         }
         else
         else
         {
         {
-            vertexShaders.Resize(MAX_GEOMETRYTYPES * 2);
-            for (unsigned j = 0; j < MAX_GEOMETRYTYPES * 2; ++j)
+            vertexShaders.Resize(MAX_GEOMETRYTYPES);
+            for (unsigned j = 0; j < MAX_GEOMETRYTYPES; ++j)
             {
             {
-                unsigned k = j % MAX_GEOMETRYTYPES;
-                unsigned h = j / MAX_GEOMETRYTYPES;
                 vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
                 vertexShaders[j] = graphics_->GetShader(VS, pass->GetVertexShader(), pass->GetVertexShaderDefines() + " " +
-                    geometryVSVariations[k] + heightFogVariations[h]);
+                    geometryVSVariations[j]);
             }
             }
         }
         }
         
         

+ 0 - 12
Source/Engine/Graphics/Renderer.h

@@ -59,15 +59,9 @@ enum LightVSVariation
     LVS_DIR = 0,
     LVS_DIR = 0,
     LVS_SPOT,
     LVS_SPOT,
     LVS_POINT,
     LVS_POINT,
-    LVS_SPEC,
-    LVS_SPOTSPEC,
-    LVS_POINTSPEC,
     LVS_SHADOW,
     LVS_SHADOW,
     LVS_SPOTSHADOW,
     LVS_SPOTSHADOW,
     LVS_POINTSHADOW,
     LVS_POINTSHADOW,
-    LVS_DIRSPECSHADOW,
-    LVS_SPOTSPECSHADOW,
-    LVS_POINTSPECSHADOW,
     MAX_LIGHT_VS_VARIATIONS
     MAX_LIGHT_VS_VARIATIONS
 };
 };
 
 
@@ -193,8 +187,6 @@ public:
     void SetReuseShadowMaps(bool enable);
     void SetReuseShadowMaps(bool enable);
     /// Set maximum number of shadow maps created for one resolution. Only has effect if reuse of shadow maps is disabled.
     /// Set maximum number of shadow maps created for one resolution. Only has effect if reuse of shadow maps is disabled.
     void SetMaxShadowMaps(int shadowMaps);
     void SetMaxShadowMaps(int shadowMaps);
-    /// Set maximum number of directional light shadow map cascades. Affects the size of directional light shadow maps.
-    void SetMaxShadowCascades(int cascades);
     /// Set dynamic instancing on/off.
     /// Set dynamic instancing on/off.
     void SetDynamicInstancing(bool enable);
     void SetDynamicInstancing(bool enable);
     /// Set minimum number of instances required in a batch group to render as instanced.
     /// Set minimum number of instances required in a batch group to render as instanced.
@@ -240,8 +232,6 @@ public:
     bool GetReuseShadowMaps() const { return reuseShadowMaps_; }
     bool GetReuseShadowMaps() const { return reuseShadowMaps_; }
     /// Return maximum number of shadow maps per resolution.
     /// Return maximum number of shadow maps per resolution.
     int GetMaxShadowMaps() const { return maxShadowMaps_; }
     int GetMaxShadowMaps() const { return maxShadowMaps_; }
-    /// Return maximum number of directional light shadow map cascades.
-    int GetMaxShadowCascades() const { return maxShadowCascades_; }
     /// Return whether dynamic instancing is in use.
     /// Return whether dynamic instancing is in use.
     bool GetDynamicInstancing() const { return dynamicInstancing_; }
     bool GetDynamicInstancing() const { return dynamicInstancing_; }
     /// Return minimum number of instances required in a batch group to render as instanced.
     /// Return minimum number of instances required in a batch group to render as instanced.
@@ -443,8 +433,6 @@ private:
     int shadowQuality_;
     int shadowQuality_;
     /// Maximum number of shadow maps per resolution.
     /// Maximum number of shadow maps per resolution.
     int maxShadowMaps_;
     int maxShadowMaps_;
-    /// Maximum number of directional light shadow cascades.
-    int maxShadowCascades_;
     /// Minimum number of instances required in a batch group to render as instanced.
     /// Minimum number of instances required in a batch group to render as instanced.
     int minInstances_;
     int minInstances_;
     /// Maximum triangles per object for instancing.
     /// Maximum triangles per object for instancing.

+ 15 - 9
Source/Engine/Graphics/View.cpp

@@ -1167,6 +1167,9 @@ void View::GetLitBatches(Drawable* drawable, LightBatchQueue& lightQueue, BatchQ
     bool allowTransparentShadows = !renderer_->GetReuseShadowMaps();
     bool allowTransparentShadows = !renderer_->GetReuseShadowMaps();
     bool allowLitBase = useLitBase_ && !light->IsNegative() && light == drawable->GetFirstLight() &&
     bool allowLitBase = useLitBase_ && !light->IsNegative() && light == drawable->GetFirstLight() &&
         drawable->GetVertexLights().Empty() && !hasAmbientGradient;
         drawable->GetVertexLights().Empty() && !hasAmbientGradient;
+    // Ambient + shadowed point light on Shader Model 2 may exceed the pixel shader instruction count
+    if (allowLitBase && !graphics_->GetSM3Support() && light->GetLightType() == LIGHT_POINT && light->GetCastShadows())
+        allowLitBase = false;
     
     
     for (unsigned i = 0; i < batches.Size(); ++i)
     for (unsigned i = 0; i < batches.Size(); ++i)
     {
     {
@@ -2189,18 +2192,20 @@ IntRect View::GetShadowMapViewport(Light* light, unsigned splitIndex, Texture2D*
 {
 {
     unsigned width = shadowMap->GetWidth();
     unsigned width = shadowMap->GetWidth();
     unsigned height = shadowMap->GetHeight();
     unsigned height = shadowMap->GetHeight();
-    int maxCascades = renderer_->GetMaxShadowCascades();
     
     
     switch (light->GetLightType())
     switch (light->GetLightType())
     {
     {
     case LIGHT_DIRECTIONAL:
     case LIGHT_DIRECTIONAL:
-        if (maxCascades == 1)
-            return IntRect(0, 0, width, height);
-        else if (maxCascades == 2)
-            return IntRect(splitIndex * width / 2, 0, (splitIndex + 1) * width / 2, height);
-        else
-            return IntRect((splitIndex & 1) * width / 2, (splitIndex / 2) * height / 2, ((splitIndex & 1) + 1) * width / 2,
-                (splitIndex / 2 + 1) * height / 2);
+        {
+            int numSplits = light->GetNumShadowSplits();
+            if (numSplits == 1)
+                return IntRect(0, 0, width, height);
+            else if (numSplits == 2)
+                return IntRect(splitIndex * width / 2, 0, (splitIndex + 1) * width / 2, height);
+            else
+                return IntRect((splitIndex & 1) * width / 2, (splitIndex / 2) * height / 2, ((splitIndex & 1) + 1) * width / 2,
+                    (splitIndex / 2 + 1) * height / 2);
+        }
         
         
     case LIGHT_SPOT:
     case LIGHT_SPOT:
         return IntRect(0, 0, width, height);
         return IntRect(0, 0, width, height);
@@ -2227,8 +2232,9 @@ void View::SetupShadowCameras(LightQueryResult& query)
             
             
             float nearSplit = camera_->GetNearClip();
             float nearSplit = camera_->GetNearClip();
             float farSplit;
             float farSplit;
+            int numSplits = light->GetNumShadowSplits();
             
             
-            while (splits < renderer_->GetMaxShadowCascades())
+            while (splits < numSplits)
             {
             {
                 // If split is completely beyond camera far clip, we are done
                 // If split is completely beyond camera far clip, we are done
                 if (nearSplit > camera_->GetFarClip())
                 if (nearSplit > camera_->GetFarClip())

+ 2 - 0
Source/Engine/LuaScript/pkgs/Graphics/Light.pkg

@@ -70,6 +70,7 @@ class Light : public Drawable
     Texture* GetRampTexture() const;
     Texture* GetRampTexture() const;
     Texture* GetShapeTexture() const;
     Texture* GetShapeTexture() const;
     Frustum GetFrustum() const;
     Frustum GetFrustum() const;
+    int GetNumShadowSplits() const;
     bool IsNegative() const;
     bool IsNegative() const;
     
     
     tolua_property__get_set LightType lightType;
     tolua_property__get_set LightType lightType;
@@ -91,6 +92,7 @@ class Light : public Drawable
     tolua_property__get_set Texture* rampTexture;
     tolua_property__get_set Texture* rampTexture;
     tolua_property__get_set Texture* shapeTexture;
     tolua_property__get_set Texture* shapeTexture;
     tolua_readonly tolua_property__get_set Frustum frustum;
     tolua_readonly tolua_property__get_set Frustum frustum;
+    tolua_readonly tolua_property__get_set int numShadowSplits;
     tolua_readonly tolua_property__is_set bool negative;
     tolua_readonly tolua_property__is_set bool negative;
     tolua_readonly tolua_property__get_set Color effectiveColor;
     tolua_readonly tolua_property__get_set Color effectiveColor;
     tolua_readonly tolua_property__get_set float effectiveSpecularIntensity;
     tolua_readonly tolua_property__get_set float effectiveSpecularIntensity;

+ 0 - 100
Source/Engine/LuaScript/pkgs/Graphics/Renderer.pkg

@@ -1,102 +1,5 @@
 $#include "Renderer.h"
 $#include "Renderer.h"
 
 
-static const int SHADOW_MIN_PIXELS;
-static const int INSTANCING_BUFFER_DEFAULT_SIZE;
-
-enum LightVSVariation
-{
-    LVS_DIR = 0,
-    LVS_SPOT,
-    LVS_POINT,
-    LVS_SPEC,
-    LVS_SPOTSPEC,
-    LVS_POINTSPEC,
-    LVS_SHADOW,
-    LVS_SPOTSHADOW,
-    LVS_POINTSHADOW,
-    LVS_DIRSPECSHADOW,
-    LVS_SPOTSPECSHADOW,
-    LVS_POINTSPECSHADOW,
-    MAX_LIGHT_VS_VARIATIONS
-};
-
-enum VertexLightVSVariation
-{
-    VLVS_NOLIGHTS = 0,
-    VLVS_1LIGHT,
-    VLVS_2LIGHTS,
-    VLVS_3LIGHTS,
-    VLVS_4LIGHTS,
-    MAX_VERTEXLIGHT_VS_VARIATIONS
-};
-
-enum LightPSVariation
-{
-    LPS_NONE = 0,
-    LPS_SPOT,
-    LPS_POINT,
-    LPS_POINTMASK,
-    LPS_SPEC,
-    LPS_SPOTSPEC,
-    LPS_POINTSPEC,
-    LPS_POINTMASKSPEC,
-    LPS_SHADOW,
-    LPS_SPOTSHADOW,
-    LPS_POINTSHADOW,
-    LPS_POINTMASKSHADOW,
-    LPS_SHADOWSPEC,
-    LPS_SPOTSHADOWSPEC,
-    LPS_POINTSHADOWSPEC,
-    LPS_POINTMASKSHADOWSPEC,
-    MAX_LIGHT_PS_VARIATIONS
-};
-
-enum DeferredLightVSVariation
-{
-    DLVS_NONE = 0,
-    DLVS_DIR,
-    DLVS_ORTHO,
-    DLVS_ORTHODIR,
-    MAX_DEFERRED_LIGHT_VS_VARIATIONS
-};
-
-enum DeferredLightPSVariation
-{
-    DLPS_NONE = 0,
-    DLPS_SPOT,
-    DLPS_POINT,
-    DLPS_POINTMASK,
-    DLPS_SPEC,
-    DLPS_SPOTSPEC,
-    DLPS_POINTSPEC,
-    DLPS_POINTMASKSPEC,
-    DLPS_SHADOW,
-    DLPS_SPOTSHADOW,
-    DLPS_POINTSHADOW,
-    DLPS_POINTMASKSHADOW,
-    DLPS_SHADOWSPEC,
-    DLPS_SPOTSHADOWSPEC,
-    DLPS_POINTSHADOWSPEC,
-    DLPS_POINTMASKSHADOWSPEC,
-    DLPS_ORTHO,
-    DLPS_ORTHOSPOT,
-    DLPS_ORTHOPOINT,
-    DLPS_ORTHOPOINTMASK,
-    DLPS_ORTHOSPEC,
-    DLPS_ORTHOSPOTSPEC,
-    DLPS_ORTHOPOINTSPEC,
-    DLPS_ORTHOPOINTMASKSPEC,
-    DLPS_ORTHOSHADOW,
-    DLPS_ORTHOSPOTSHADOW,
-    DLPS_ORTHOPOINTSHADOW,
-    DLPS_ORTHOPOINTMASKSHADOW,
-    DLPS_ORTHOSHADOWSPEC,
-    DLPS_ORTHOSPOTSHADOWSPEC,
-    DLPS_ORTHOPOINTSHADOWSPEC,
-    DLPS_ORTHOPOINTMASKSHADOWSPEC,
-    MAX_DEFERRED_LIGHT_PS_VARIATIONS
-};
-
 class Renderer
 class Renderer
 {
 {
     void SetNumViewports(unsigned num);
     void SetNumViewports(unsigned num);
@@ -114,7 +17,6 @@ class Renderer
     void SetShadowQuality(int quality);
     void SetShadowQuality(int quality);
     void SetReuseShadowMaps(bool enable);
     void SetReuseShadowMaps(bool enable);
     void SetMaxShadowMaps(int shadowMaps);
     void SetMaxShadowMaps(int shadowMaps);
-    void SetMaxShadowCascades(int cascades);
     void SetDynamicInstancing(bool enable);
     void SetDynamicInstancing(bool enable);
     void SetMinInstances(int instances);
     void SetMinInstances(int instances);
     void SetMaxInstanceTriangles(int triangles);
     void SetMaxInstanceTriangles(int triangles);
@@ -138,7 +40,6 @@ class Renderer
     int GetShadowQuality() const;
     int GetShadowQuality() const;
     bool GetReuseShadowMaps() const;
     bool GetReuseShadowMaps() const;
     int GetMaxShadowMaps() const;
     int GetMaxShadowMaps() const;
-    int GetMaxShadowCascades() const;
     bool GetDynamicInstancing() const;
     bool GetDynamicInstancing() const;
     int GetMinInstances() const;
     int GetMinInstances() const;
     int GetMaxInstanceTriangles() const;
     int GetMaxInstanceTriangles() const;
@@ -178,7 +79,6 @@ class Renderer
     tolua_property__get_set int shadowQuality;
     tolua_property__get_set int shadowQuality;
     tolua_property__get_set bool reuseShadowMaps;
     tolua_property__get_set bool reuseShadowMaps;
     tolua_property__get_set int maxShadowMaps;
     tolua_property__get_set int maxShadowMaps;
-    tolua_property__get_set int maxShadowCascades;
     tolua_property__get_set bool dynamicInstancing;
     tolua_property__get_set bool dynamicInstancing;
     tolua_property__get_set int minInstances;
     tolua_property__get_set int minInstances;
     tolua_property__get_set int maxInstanceTriangles;
     tolua_property__get_set int maxInstanceTriangles;

+ 1 - 2
Source/Engine/Script/GraphicsAPI.cpp

@@ -807,6 +807,7 @@ static void RegisterLight(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Light", "void set_shapeTexture(Texture@+)", asMETHOD(Light, SetShapeTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void set_shapeTexture(Texture@+)", asMETHOD(Light, SetShapeTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Texture@+ get_shapeTexture() const", asMETHOD(Light, GetShapeTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Texture@+ get_shapeTexture() const", asMETHOD(Light, GetShapeTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Frustum get_frustum() const", asMETHOD(Light, GetFrustum), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Frustum get_frustum() const", asMETHOD(Light, GetFrustum), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "int get_numShadowSplits() const", asMETHOD(Light, GetNumShadowSplits), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "bool get_negative() const", asMETHOD(Light, IsNegative), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "bool get_negative() const", asMETHOD(Light, IsNegative), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Color get_effectiveColor() const", asMETHOD(Light, GetEffectiveColor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Color get_effectiveColor() const", asMETHOD(Light, GetEffectiveColor), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "float get_effectiveSpecularIntensity() const", asMETHOD(Light, GetEffectiveSpecularIntensity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "float get_effectiveSpecularIntensity() const", asMETHOD(Light, GetEffectiveSpecularIntensity), asCALL_THISCALL);
@@ -1329,8 +1330,6 @@ static void RegisterRenderer(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Renderer", "int get_shadowMapSize() const", asMETHOD(Renderer, GetShadowMapSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_shadowMapSize() const", asMETHOD(Renderer, GetShadowMapSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_shadowQuality(int)", asMETHOD(Renderer, SetShadowQuality), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_shadowQuality(int)", asMETHOD(Renderer, SetShadowQuality), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_shadowQuality() const", asMETHOD(Renderer, GetShadowQuality), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_shadowQuality() const", asMETHOD(Renderer, GetShadowQuality), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Renderer", "void set_maxShadowCascades(int)", asMETHOD(Renderer, SetMaxShadowCascades), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Renderer", "int get_maxShadowCascades() const", asMETHOD(Renderer, GetMaxShadowCascades), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_maxShadowMaps(int)", asMETHOD(Renderer, SetMaxShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_maxShadowMaps(int)", asMETHOD(Renderer, SetMaxShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_maxShadowMaps() const", asMETHOD(Renderer, GetMaxShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_maxShadowMaps() const", asMETHOD(Renderer, GetMaxShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_reuseShadowMaps(bool)", asMETHOD(Renderer, SetReuseShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_reuseShadowMaps(bool)", asMETHOD(Renderer, SetReuseShadowMaps), asCALL_THISCALL);