Files
2026-11-01 23:39:55 +02:00

33 lines
1.9 KiB
HLSL

// Both functions below are called from outside FEATURES_GRAPH_VERTEX, so the two terrain pass
// templates include this file unconditionally, after the pass structs. Do not move it behind the
// graphVertex feature gate. Keep this comment free of the template command character as well: the
// preprocessor reads commands inside comments and splices an error marker into the shader.
void ApplyTerrainInstancing(inout Attributes input)
{
float4 positionOS = float4(input.positionOS, 1.0);
#if defined(VARYINGS_NEED_TEXCOORD0) && defined(ATTRIBUTES_NEED_NORMAL)
TerrainInstancing(positionOS, input.normalOS, input.uv0.xy);
#elif defined(VARYINGS_NEED_TEXCOORD0)
float3 normal = float3(0, 0, 0);
TerrainInstancing(positionOS, normal, input.uv0.xy);
#elif defined(ATTRIBUTES_NEED_NORMAL)
TerrainInstancing(positionOS, input.normalOS);
#else
TerrainInstancing(positionOS);
#endif
input.positionOS = positionOS.xyz;
}
float4 ConstructTerrainTangent(float3 normal, float3 positiveZ)
{
// Consider a flat terrain. It should have tangent be (1, 0, 0) and bitangent be (0, 0, 1) as the UV of the terrain grid mesh is a scale of the world XZ position.
// In CreateTangentToWorld function (in SpaceTransform.hlsl), it is cross(normal, tangent) * sgn for the bitangent vector.
// It is not true in a left-handed coordinate system for the terrain bitangent, if we provide 1 as the tangent.w. It would produce (0, 0, -1) instead of (0, 0, 1).
// Also terrain's tangent calculation was wrong in a left handed system because cross((0,0,1), terrainNormalOS) points to the wrong direction as negative X.
// Therefore all the 4 xyzw components of the tangent needs to be flipped to correct the tangent frame.
// (See TerrainLitData.hlsl - GetSurfaceAndBuiltinData)
float3 tangent = cross(normal, positiveZ);
return float4(tangent, -1);
}