From e0a2904dbf6f8c6f1d0dd8ef903ed1efd31c8c58 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 30 Jun 2021 14:13:37 +0200 Subject: [PATCH] Fix terrain normal mapping issue #562 --- Content/Editor/MaterialTemplates/Terrain.shader | 4 ++-- .../Engine/Graphics/Materials/MaterialShader.h | 2 +- Source/Shaders/MaterialCommon.hlsl | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader index b1c3a2910..a7172e381 100644 --- a/Content/Editor/MaterialTemplates/Terrain.shader +++ b/Content/Editor/MaterialTemplates/Terrain.shader @@ -112,7 +112,7 @@ MaterialInput GetGeometryMaterialInput(GeometryData geometry) #if USE_LIGHTMAP output.LightmapUV = geometry.LightmapUV; #endif - output.TBN = CalcTangentBasisFromWorldNormal(geometry.WorldNormal); + output.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldPosition, geometry.TexCoord); output.HolesMask = geometry.HolesMask; #if USE_TERRAIN_LAYERS output.Layers = geometry.Layers; @@ -415,7 +415,7 @@ VertexOutput VS(TerrainVertexInput input) #if USE_LIGHTMAP materialInput.LightmapUV = output.Geometry.LightmapUV; #endif - materialInput.TBN = CalcTangentBasisFromWorldNormal(output.Geometry.WorldNormal); + materialInput.TBN = tangentToWorld; materialInput.TwoSidedSign = WorldDeterminantSign; materialInput.SvPosition = output.Position; materialInput.PreSkinnedPosition = position; diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index 3eb6a45f8..270c60548 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 148 +#define MATERIAL_GRAPH_VERSION 149 class Material; class GPUShader; diff --git a/Source/Shaders/MaterialCommon.hlsl b/Source/Shaders/MaterialCommon.hlsl index 8fc981cd7..bc8aa66ac 100644 --- a/Source/Shaders/MaterialCommon.hlsl +++ b/Source/Shaders/MaterialCommon.hlsl @@ -154,6 +154,22 @@ struct GBufferOutput float4 RT3 : SV_Target4; }; +float3x3 CalcTangentBasis(float3 normal, float3 pos, float2 uv) +{ + // References: + // http://www.thetenthplanet.de/archives/1180 + // https://zhangdoa.com/posts/normal-and-normal-mapping + float3 dp1 = ddx(pos); + float3 dp2 = ddy(pos); + float2 duv1 = ddx(uv); + float2 duv2 = ddy(uv); + float3 dp2perp = cross(dp2, normal); + float3 dp1perp = cross(normal, dp1); + float3 tangent = normalize(dp2perp * duv1.x + dp1perp * duv2.x); + float3 bitangent = normalize(dp2perp * duv1.y + dp1perp * duv2.y); + return float3x3(tangent, bitangent, normal); +} + float3x3 CalcTangentBasisFromWorldNormal(float3 normal) { float3 tangent = cross(normal, float3(1, 0, 0));