diff --git a/binaries/data/mods/mod/art/materials/terrain_normstrong_spec.xml b/binaries/data/mods/mod/art/materials/terrain_normstrong_spec.xml
index c26627cb25..abafc3562e 100644
--- a/binaries/data/mods/mod/art/materials/terrain_normstrong_spec.xml
+++ b/binaries/data/mods/mod/art/materials/terrain_normstrong_spec.xml
@@ -5,5 +5,5 @@
-
+
diff --git a/binaries/data/mods/mod/shaders/glsl/common/shading.h b/binaries/data/mods/mod/shaders/glsl/common/shading.h
new file mode 100644
index 0000000000..26cb256ca1
--- /dev/null
+++ b/binaries/data/mods/mod/shaders/glsl/common/shading.h
@@ -0,0 +1,23 @@
+#ifndef INCLUDED_COMMON_SHADING
+#define INCLUDED_COMMON_SHADING
+
+vec3 calculateNormal(vec3 surfaceNormal, vec3 packedTextureNormal, mat3 tangentBitangentNormal, float textureNormalStrength)
+{
+ vec3 localNormal = packedTextureNormal.rgb * 2.0 - 1.0;
+ localNormal.y = -localNormal.y;
+ vec3 normal = normalize(tangentBitangentNormal * localNormal);
+#if USE_NORMAL_MAP
+ if (textureNormalStrength <= 1.0)
+ normal = normalize(mix(surfaceNormal, normal, textureNormalStrength));
+ else
+ normal = normalize(normal - surfaceNormal * min(1.0, textureNormalStrength - 1.0));
+#endif
+ return normal;
+}
+
+vec3 calculateShading(vec3 albedo, vec3 sunDiffuse, vec3 specular, vec3 ambient, float shadow, float ao)
+{
+ return (albedo * sunDiffuse + specular.rgb) * shadow + albedo * ambient * ao;
+}
+
+#endif // INCLUDED_COMMON_SHADING
diff --git a/binaries/data/mods/mod/shaders/glsl/terrain_common.fs b/binaries/data/mods/mod/shaders/glsl/terrain_common.fs
index f274c9404d..45d1ab15a9 100644
--- a/binaries/data/mods/mod/shaders/glsl/terrain_common.fs
+++ b/binaries/data/mods/mod/shaders/glsl/terrain_common.fs
@@ -6,6 +6,7 @@
#include "common/fog.h"
#include "common/fragment.h"
#include "common/los_fragment.h"
+#include "common/shading.h"
#include "common/shadows_fragment.h"
#if USE_TRIPLANAR
@@ -91,13 +92,12 @@ void main()
float sign = v_tangent.w;
mat3 tbn = mat3(v_tangent.xyz, v_bitangent * -sign, v_normal);
#if USE_TRIPLANAR
- vec3 ntex = triplanarNormals(GET_DRAW_TEXTURE_2D(normTex), v_tex).rgb * 2.0 - 1.0;
+ vec3 ntex = triplanarNormals(GET_DRAW_TEXTURE_2D(normTex), v_tex).rgb;
#else
- vec3 ntex = SAMPLE_2D(GET_DRAW_TEXTURE_2D(normTex), v_tex).rgb * 2.0 - 1.0;
+ vec3 ntex = SAMPLE_2D(GET_DRAW_TEXTURE_2D(normTex), v_tex).rgb;
#endif
- normal = normalize(tbn * ntex);
- vec3 bumplight = max(dot(-sunDir, normal), 0.0) * sunColor;
- vec3 sundiffuse = (bumplight - v_lighting.rgb) * effectSettings.x + v_lighting.rgb;
+ normal = calculateNormal(normal, ntex, tbn, effectSettings.x);
+ vec3 sundiffuse = max(dot(-sunDir, normal), 0.0) * sunColor;
#else
vec3 sundiffuse = v_lighting;
#endif
@@ -117,7 +117,7 @@ void main()
specular.rgb = sunColor * specCol * pow(max(0.001, dot(normalize(normal), v_half)), specPow);
#endif
- vec3 color = (texdiffuse * sundiffuse + specular.rgb) * getShadowOnLandscape() + texdiffuse * ambient;
+ vec3 color = calculateShading(texdiffuse, sundiffuse, specular.rgb, ambient, getShadowOnLandscape(), 1.0);
#if USE_SPECULAR_MAP && USE_SELF_LIGHT
color = mix(texdiffuse, color, specular.a);
diff --git a/binaries/data/mods/public/art/materials/rock_norm_spec.xml b/binaries/data/mods/public/art/materials/rock_norm_spec.xml
index bb24721a6b..4df8107813 100644
--- a/binaries/data/mods/public/art/materials/rock_norm_spec.xml
+++ b/binaries/data/mods/public/art/materials/rock_norm_spec.xml
@@ -6,5 +6,5 @@
-
+
diff --git a/binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml b/binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml
index 3b17d6eb5a..db78425a9a 100644
--- a/binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml
+++ b/binaries/data/mods/public/art/materials/rock_norm_spec_ao.xml
@@ -7,5 +7,5 @@
-
+
diff --git a/binaries/data/mods/public/art/materials/terrain_normstrong_spec.xml b/binaries/data/mods/public/art/materials/terrain_normstrong_spec.xml
index c26627cb25..abafc3562e 100644
--- a/binaries/data/mods/public/art/materials/terrain_normstrong_spec.xml
+++ b/binaries/data/mods/public/art/materials/terrain_normstrong_spec.xml
@@ -5,5 +5,5 @@
-
+
diff --git a/binaries/data/mods/public/shaders/glsl/model_common.fs b/binaries/data/mods/public/shaders/glsl/model_common.fs
index 91e6f8d893..0bf33ed216 100644
--- a/binaries/data/mods/public/shaders/glsl/model_common.fs
+++ b/binaries/data/mods/public/shaders/glsl/model_common.fs
@@ -6,6 +6,7 @@
#include "common/fog.h"
#include "common/fragment.h"
#include "common/los_fragment.h"
+#include "common/shading.h"
#include "common/shadows_fragment.h"
void main()
@@ -78,15 +79,12 @@ void main()
#endif
#if USE_SPECULAR || USE_SPECULAR_MAP || USE_NORMAL_MAP
- vec3 normal = v_normal.xyz;
+ vec3 normal = normalize(v_normal.xyz);
#endif
#if (USE_INSTANCING || USE_GPU_SKINNING) && USE_NORMAL_MAP
- vec3 ntex = SAMPLE_2D(GET_DRAW_TEXTURE_2D(normTex), coord).rgb * 2.0 - 1.0;
- ntex.y = -ntex.y;
- normal = normalize(tbn * ntex);
- vec3 bumplight = max(dot(-sunDir, normal), 0.0) * sunColor;
- vec3 sundiffuse = (bumplight - v_lighting.rgb) * effectSettings.x + v_lighting.rgb;
+ normal = calculateNormal(normal, SAMPLE_2D(GET_DRAW_TEXTURE_2D(normTex), coord).rgb, tbn, effectSettings.x);
+ vec3 sundiffuse = max(dot(-sunDir, normal), 0.0) * sunColor;
#else
vec3 sundiffuse = v_lighting.rgb;
#endif
@@ -113,8 +111,7 @@ void main()
float ao = 1.0;
#endif
- vec3 ambientColor = texdiffuse * ambient * ao;
- vec3 color = (texdiffuse * sundiffuse + specular.rgb) * getShadow() + ambientColor;
+ vec3 color = calculateShading(texdiffuse, sundiffuse, specular.rgb, ambient, getShadow(), ao);
#if USE_SPECULAR_MAP && USE_SELF_LIGHT
color = mix(texdiffuse, color, specular.a);