From 556e4db9fbfbcb9ca32f58d134e291a2a199d850 Mon Sep 17 00:00:00 2001 From: wheatleymf <20972271+wheatleymf@users.noreply.github.com> Date: Sat, 29 Nov 2025 18:28:28 +0300 Subject: [PATCH] Transform tangent normal along seamless UV angle Previous implementation of seamless UV was sampling tangent normal map 'as is', without transforming vectors to be inline with the UV rotation angle - which resulted into NdotL shading errors. This is now corrected and tangent vector accounts for UV rotation. --- game/addons/base/Assets/shaders/terrain.shader | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/game/addons/base/Assets/shaders/terrain.shader b/game/addons/base/Assets/shaders/terrain.shader index 593ebe5b..012c181f 100644 --- a/game/addons/base/Assets/shaders/terrain.shader +++ b/game/addons/base/Assets/shaders/terrain.shader @@ -173,7 +173,9 @@ PS for ( int i = 0; i < 4; i++ ) { float2 layerUV = texUV * g_TerrainMaterials[ i ].uvscale; - float2 seamlessUV = Terrain_SampleSeamlessUV( layerUV ); + + float2x2 uvRotation; + float2 seamlessUV = Terrain_SampleSeamlessUV( layerUV, uvRotation ); Texture2D tBcr = Bindless::GetTexture2D( g_TerrainMaterials[ i ].bcr_texid ); Texture2D tNho = Bindless::GetTexture2D( g_TerrainMaterials[ i ].nho_texid ); @@ -183,6 +185,10 @@ PS float3 normal = ComputeNormalFromRGTexture( nho.rg ); normal.xz *= g_TerrainMaterials[ i ].normalstrength; + + // Rotate normal map to match seamless UV angle and avoid shading errors + normal.xy = mul( uvRotation, normal.xy ); + normal = normalize( normal ); albedos[i] = SrgbGammaToLinear( bcr.rgb );