diff --git a/Content/Editor/MaterialTemplates/Decal.shader b/Content/Editor/MaterialTemplates/Decal.shader index 35446b7e2..452937955 100644 --- a/Content/Editor/MaterialTemplates/Decal.shader +++ b/Content/Editor/MaterialTemplates/Decal.shader @@ -116,9 +116,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Input macro specified by the material: DECAL_BLEND_MODE #define DECAL_BLEND_MODE_TRANSLUCENT 0 diff --git a/Content/Editor/MaterialTemplates/Features/Tessellation.hlsl b/Content/Editor/MaterialTemplates/Features/Tessellation.hlsl index c5ebbba92..f2fc714ee 100644 --- a/Content/Editor/MaterialTemplates/Features/Tessellation.hlsl +++ b/Content/Editor/MaterialTemplates/Features/Tessellation.hlsl @@ -1,6 +1,7 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. @0// Tessellation: Defines +#define TessalationProjectOntoPlane(planeNormal, planePosition, pointToProject) pointToProject - dot(pointToProject - planePosition, planeNormal) * planeNormal @1// Tessellation: Includes @2// Tessellation: Constants @3// Tessellation: Resources @@ -11,22 +12,10 @@ // Interpolants passed from the hull shader to the domain shader struct TessalationHSToDS { - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; -#if USE_VERTEX_COLOR - half4 VertexColor : COLOR; -#endif - float3 WorldNormal : TEXCOORD3; - float4 WorldTangent : TEXCOORD4; + float4 Position : SV_Position; + GeometryData Geometry; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; -#endif - float3 InstanceOrigin : TEXCOORD6; - float2 InstanceParams : TEXCOORD7; -#if IS_MOTION_VECTORS_PASS - float3 PrevWorldPosition : TEXCOORD8; #endif float TessellationMultiplier : TESS; }; @@ -34,41 +23,19 @@ struct TessalationHSToDS // Interpolants passed from the domain shader and to the pixel shader struct TessalationDSToPS { - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; -#if USE_VERTEX_COLOR - half4 VertexColor : COLOR; -#endif - float3 WorldNormal : TEXCOORD3; - float4 WorldTangent : TEXCOORD4; + float4 Position : SV_Position; + GeometryData Geometry; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; -#endif - float3 InstanceOrigin : TEXCOORD6; - float2 InstanceParams : TEXCOORD7; -#if IS_MOTION_VECTORS_PASS - float3 PrevWorldPosition : TEXCOORD8; #endif }; MaterialInput GetMaterialInput(TessalationDSToPS input) { MaterialInput result = (MaterialInput)0; - result.WorldPosition = input.WorldPosition; - result.TexCoord = input.TexCoord; -#if USE_LIGHTMAP - result.LightmapUV = input.LightmapUV; -#endif -#if USE_VERTEX_COLOR - result.VertexColor = input.VertexColor; -#endif - result.TBN = CalcTangentBasis(input.WorldNormal, input.WorldTangent); - result.TwoSidedSign = WorldDeterminantSign; - result.InstanceOrigin = input.InstanceOrigin; - result.InstanceParams = input.InstanceParams; result.SvPosition = input.Position; + GetGeometryMaterialInput(result, input.Geometry); + result.TwoSidedSign = WorldDeterminantSign; #if USE_CUSTOM_VERTEX_INTERPOLATORS result.CustomVSToPS = input.CustomVSToPS; #endif @@ -78,7 +45,7 @@ MaterialInput GetMaterialInput(TessalationDSToPS input) struct TessalationPatch { float EdgeTessFactor[3] : SV_TessFactor; - float InsideTessFactor : SV_InsideTessFactor; + float InsideTessFactor : SV_InsideTessFactor; #if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN float3 B210 : POSITION4; float3 B120 : POSITION5; @@ -110,20 +77,19 @@ TessalationPatch HS_PatchConstant(InputPatch input) #if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN // Calculate PN Triangle control points // Reference: [Vlachos 2001] - float3 p1 = input[0].WorldPosition; - float3 p2 = input[1].WorldPosition; - float3 p3 = input[2].WorldPosition; - float3 n1 = input[0].WorldNormal; - float3 n2 = input[1].WorldNormal; - float3 n3 = input[2].WorldNormal; + float3 p1 = input[0].Geometry.WorldPosition; + float3 p2 = input[1].Geometry.WorldPosition; + float3 p3 = input[2].Geometry.WorldPosition; + float3 n1 = input[0].Geometry.WorldNormal; + float3 n2 = input[1].Geometry.WorldNormal; + float3 n3 = input[2].Geometry.WorldNormal; output.B210 = (2.0f * p1 + p2 - dot((p2 - p1), n1) * n1) / 3.0f; output.B120 = (2.0f * p2 + p1 - dot((p1 - p2), n2) * n2) / 3.0f; output.B021 = (2.0f * p2 + p3 - dot((p3 - p2), n2) * n2) / 3.0f; output.B012 = (2.0f * p3 + p2 - dot((p2 - p3), n3) * n3) / 3.0f; output.B102 = (2.0f * p3 + p1 - dot((p1 - p3), n3) * n3) / 3.0f; output.B201 = (2.0f * p1 + p3 - dot((p3 - p1), n1) * n1) / 3.0f; - float3 e = (output.B210 + output.B120 + output.B021 + - output.B012 + output.B102 + output.B201) / 6.0f; + float3 e = (output.B210 + output.B120 + output.B021 + output.B012 + output.B102 + output.B201) / 6.0f; float3 v = (p1 + p2 + p3) / 3.0f; output.B111 = e + ((e - v) / 2.0f); #endif @@ -132,8 +98,6 @@ TessalationPatch HS_PatchConstant(InputPatch input) } META_HS(USE_TESSELLATION, FEATURE_LEVEL_SM5) -META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=0) -META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=1) META_HS_PATCH(TESSELLATION_IN_CONTROL_POINTS) [domain("tri")] [partitioning("fractional_odd")] @@ -148,19 +112,7 @@ TessalationHSToDS HS(InputPatch in // Pass through shader #define COPY(thing) output.thing = input[ControlPointID].thing; COPY(Position); - COPY(WorldPosition); - COPY(TexCoord); - COPY(LightmapUV); -#if USE_VERTEX_COLOR - COPY(VertexColor); -#endif - COPY(WorldNormal); - COPY(WorldTangent); - COPY(InstanceOrigin); - COPY(InstanceParams); -#if IS_MOTION_VECTORS_PASS - COPY(PrevWorldPosition); -#endif + COPY(Geometry); COPY(TessellationMultiplier); #if USE_CUSTOM_VERTEX_INTERPOLATORS COPY(CustomVSToPS); @@ -170,19 +122,7 @@ TessalationHSToDS HS(InputPatch in return output; } -#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG - -// Orthogonal projection on to plane -float3 ProjectOntoPlane(float3 planeNormal, float3 planePosition, float3 pointToProject) -{ - return pointToProject - dot(pointToProject - planePosition, planeNormal) * planeNormal; -} - -#endif - META_DS(USE_TESSELLATION, FEATURE_LEVEL_SM5) -META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=0) -META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=1) [domain("tri")] TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : SV_DomainLocation, const OutputPatch input) { @@ -194,22 +134,18 @@ TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : S float W = barycentricCoords.z; // Interpolate patch attributes to generated vertices + output.Geometry = InterpolateGeometry(input[0].Geometry, U, input[1].Geometry, V, input[2].Geometry, W); #define INTERPOLATE(thing) output.thing = U * input[0].thing + V * input[1].thing + W * input[2].thing -#define COPY(thing) output.thing = input[0].thing INTERPOLATE(Position); #if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN + // Interpolate using barycentric coordinates and PN Triangle control points float UU = U * U; float VV = V * V; float WW = W * W; float UU3 = UU * 3.0f; float VV3 = VV * 3.0f; float WW3 = WW * 3.0f; - - // Interpolate using barycentric coordinates and PN Triangle control points - output.WorldPosition = - input[0].WorldPosition * UU * U + - input[1].WorldPosition * VV * V + - input[2].WorldPosition * WW * W + + float3 offset = constantData.B210 * UU3 * V + constantData.B120 * VV3 * U + constantData.B021 * VV3 * W + @@ -217,76 +153,31 @@ TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : S constantData.B102 * WW3 * U + constantData.B201 * UU3 * W + constantData.B111 * 6.0f * W * U * V; -#if IS_MOTION_VECTORS_PASS - output.PrevWorldPosition = - input[0].PrevWorldPosition * UU * U + - input[1].PrevWorldPosition * VV * V + - input[2].PrevWorldPosition * WW * W + - constantData.B210 * UU3 * V + - constantData.B120 * VV3 * U + - constantData.B021 * VV3 * W + - constantData.B012 * WW3 * V + - constantData.B102 * WW3 * U + - constantData.B201 * UU3 * W + - constantData.B111 * 6.0f * W * U * V; -#endif + InterpolateGeometryPositions(output.Geometry, input[0].Geometry, UU * U, input[1].Geometry, VV * V, input[2].Geometry, WW * W, offset); #else - INTERPOLATE(WorldPosition); -#if IS_MOTION_VECTORS_PASS - INTERPOLATE(PrevWorldPosition); + InterpolateGeometryPositions(output.Geometry, input[0].Geometry, U, input[1].Geometry, V, input[2].Geometry, W, float3(0, 0, 0)); #endif -#endif - INTERPOLATE(TexCoord); - INTERPOLATE(LightmapUV); -#if USE_VERTEX_COLOR - INTERPOLATE(VertexColor); -#endif - INTERPOLATE(WorldNormal); - INTERPOLATE(WorldTangent); - COPY(InstanceOrigin); - COPY(InstanceParams); #if USE_CUSTOM_VERTEX_INTERPOLATORS UNROLL for (int i = 0; i < CUSTOM_VERTEX_INTERPOLATORS_COUNT; i++) - { INTERPOLATE(CustomVSToPS[i]); - } #endif #undef INTERPOLATE -#undef COPY - - // Interpolating tangents can unnormalize it, so normalize it - output.WorldNormal = normalize(output.WorldNormal); - output.WorldTangent.xyz = normalize(output.WorldTangent.xyz); #if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG - // Orthogonal projection in the tangent planes - float3 posProjectedU = ProjectOntoPlane(input[0].WorldNormal, input[0].WorldPosition, output.WorldPosition); - float3 posProjectedV = ProjectOntoPlane(input[1].WorldNormal, input[1].WorldPosition, output.WorldPosition); - float3 posProjectedW = ProjectOntoPlane(input[2].WorldNormal, input[2].WorldPosition, output.WorldPosition); - - // Interpolate the projected points - output.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW; -#if IS_MOTION_VECTORS_PASS - posProjectedU = ProjectOntoPlane(input[0].WorldNormal, input[0].PrevWorldPosition, output.PrevWorldPosition); - posProjectedV = ProjectOntoPlane(input[1].WorldNormal, input[1].PrevWorldPosition, output.PrevWorldPosition); - posProjectedW = ProjectOntoPlane(input[2].WorldNormal, input[2].PrevWorldPosition, output.PrevWorldPosition); - output.PrevWorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW; -#endif + // Orthogonal projection in the tangent planes with interpolation + ApplyGeometryPositionsPhongTess(output.Geometry, input[0].Geometry, input[1].Geometry, input[2].Geometry, U, V, W); #endif // Perform displacement mapping #if USE_DISPLACEMENT MaterialInput materialInput = GetMaterialInput(output); Material material = GetMaterialDS(materialInput); - output.WorldPosition += material.WorldDisplacement; -#if IS_MOTION_VECTORS_PASS - output.PrevWorldPosition += material.WorldDisplacement; -#endif + OffsetGeometryPositions(output.Geometry, material.WorldDisplacement); #endif // Recalculate the clip space position - output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix); + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); return output; } diff --git a/Content/Editor/MaterialTemplates/GUI.shader b/Content/Editor/MaterialTemplates/GUI.shader index 08fddde79..b927755ad 100644 --- a/Content/Editor/MaterialTemplates/GUI.shader +++ b/Content/Editor/MaterialTemplates/GUI.shader @@ -199,9 +199,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Vertex Shader function for GUI materials rendering META_VS(true, FEATURE_LEVEL_ES2) META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) diff --git a/Content/Editor/MaterialTemplates/Particle.shader b/Content/Editor/MaterialTemplates/Particle.shader index e8d00d1db..f3121b6b0 100644 --- a/Content/Editor/MaterialTemplates/Particle.shader +++ b/Content/Editor/MaterialTemplates/Particle.shader @@ -332,9 +332,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Calculates the transform matrix from mesh tangent space to local space half3x3 CalcTangentToLocal(ModelInput input) { diff --git a/Content/Editor/MaterialTemplates/PostProcess.shader b/Content/Editor/MaterialTemplates/PostProcess.shader index a3e5e42c7..681a04248 100644 --- a/Content/Editor/MaterialTemplates/PostProcess.shader +++ b/Content/Editor/MaterialTemplates/PostProcess.shader @@ -136,9 +136,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Pixel Shader function for PostFx materials rendering META_PS(true, FEATURE_LEVEL_ES2) float4 PS_PostFx(PixelInput input) : SV_Target0 diff --git a/Content/Editor/MaterialTemplates/SurfaceDeferred.shader b/Content/Editor/MaterialTemplates/SurfaceDeferred.shader index 303cb2fee..dcee96822 100644 --- a/Content/Editor/MaterialTemplates/SurfaceDeferred.shader +++ b/Content/Editor/MaterialTemplates/SurfaceDeferred.shader @@ -32,25 +32,30 @@ float Dummy1; // Material shader resources @2 + +// Geometry data passed though the graphics rendering stages up to the pixel shader +struct GeometryData +{ + float3 WorldPosition : TEXCOORD0; + float2 TexCoord : TEXCOORD1; + float2 LightmapUV : TEXCOORD2; +#if USE_VERTEX_COLOR + half4 VertexColor : COLOR; +#endif + float3 WorldNormal : TEXCOORD3; + float4 WorldTangent : TEXCOORD4; + float3 InstanceOrigin : TEXCOORD6; + float2 InstanceParams : TEXCOORD7; // x-PerInstanceRandom, y-LODDitherFactor + float3 PrevWorldPosition : TEXCOORD8; +}; + // Interpolants passed from the vertex shader struct VertexOutput { - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; -#if USE_VERTEX_COLOR - half4 VertexColor : COLOR; -#endif - float3 WorldNormal : TEXCOORD3; - float4 WorldTangent : TEXCOORD4; + float4 Position : SV_Position; + GeometryData Geometry; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; -#endif - float3 InstanceOrigin : TEXCOORD6; - float2 InstanceParams : TEXCOORD7; // x-PerInstanceRandom, y-LODDitherFactor -#if IS_MOTION_VECTORS_PASS - float3 PrevWorldPosition : TEXCOORD8; #endif #if USE_TESSELLATION float TessellationMultiplier : TESS; @@ -60,24 +65,12 @@ struct VertexOutput // Interpolants passed to the pixel shader struct PixelInput { - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; -#if USE_VERTEX_COLOR - half4 VertexColor : COLOR; -#endif - float3 WorldNormal : TEXCOORD3; - float4 WorldTangent : TEXCOORD4; + float4 Position : SV_Position; + GeometryData Geometry; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; #endif - float3 InstanceOrigin : TEXCOORD6; - float2 InstanceParams : TEXCOORD7; // x-PerInstanceRandom, y-LODDitherFactor -#if IS_MOTION_VECTORS_PASS - float3 PrevWorldPosition : TEXCOORD8; -#endif - bool IsFrontFace : SV_IsFrontFace; + bool IsFrontFace : SV_IsFrontFace; }; // Material properties generation input @@ -108,24 +101,75 @@ struct MaterialInput #endif }; -float3x3 CalcTangentBasis(float3 normal, float4 tangent) +// Extracts geometry data to the material input +void GetGeometryMaterialInput(inout MaterialInput result, in GeometryData geometry) { - float3 bitangent = cross(normal, tangent.xyz) * tangent.w; - return float3x3(tangent.xyz, bitangent, normal); + result.WorldPosition = geometry.WorldPosition; + result.TexCoord = geometry.TexCoord; +#if USE_LIGHTMAP + result.LightmapUV = geometry.LightmapUV; +#endif +#if USE_VERTEX_COLOR + result.VertexColor = geometry.VertexColor; +#endif + result.TBN = CalcTangentBasis(geometry.WorldNormal, geometry.WorldTangent); + result.InstanceOrigin = geometry.InstanceOrigin; + result.InstanceParams = geometry.InstanceParams; } +#if USE_TESSELLATION + +// Interpolates the geometry positions data only (used by the tessallation when generating vertices) +#define InterpolateGeometryPositions(output, p0, w0, p1, w1, p2, w2, offset) output.WorldPosition = p0.WorldPosition * w0 + p1.WorldPosition * w1 + p2.WorldPosition * w2 + offset; output.PrevWorldPosition = p0.PrevWorldPosition * w0 + p1.PrevWorldPosition * w1 + p2.PrevWorldPosition * w2 + offset + +// Offsets the geometry positions data only (used by the tessallation when generating vertices) +#define OffsetGeometryPositions(geometry, offset) geometry.WorldPosition += offset; geometry.PrevWorldPosition += offset + +// Applies the Phong tessallation to the geometry positions (used by the tessallation when doing Phong tess) +#define ApplyGeometryPositionsPhongTess(geometry, p0, p1, p2, U, V, W) \ + float3 posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.WorldPosition, geometry.WorldPosition); \ + float3 posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.WorldPosition, geometry.WorldPosition); \ + float3 posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.WorldPosition, geometry.WorldPosition); \ + geometry.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW; \ + posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.PrevWorldPosition, geometry.PrevWorldPosition); \ + posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.PrevWorldPosition, geometry.PrevWorldPosition); \ + posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.PrevWorldPosition, geometry.PrevWorldPosition); \ + geometry.PrevWorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW + +// Interpolates the geometry data except positions (used by the tessallation when generating vertices) +GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2) +{ + GeometryData output = (GeometryData)0; + output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2; +#if USE_LIGHTMAP + output.LightmapUV = p0.LightmapUV * w0 + p1.LightmapUV * w1 + p2.LightmapUV * w2; +#endif +#if USE_VERTEX_COLOR + output.VertexColor = p0.VertexColor * w0 + p1.VertexColor * w1 + p2.VertexColor * w2; +#endif + output.WorldNormal = p0.WorldNormal * w0 + p1.WorldNormal * w1 + p2.WorldNormal * w2; + output.WorldNormal = normalize(output.WorldNormal); + output.WorldTangent = p0.WorldTangent * w0 + p1.WorldTangent * w1 + p2.WorldTangent * w2; + output.WorldTangent.xyz = normalize(output.WorldTangent.xyz); + output.InstanceOrigin = p0.InstanceOrigin; + output.InstanceParams = p0.InstanceParams; + return output; +} + +#endif + MaterialInput GetMaterialInput(ModelInput input, VertexOutput output, float3 localNormal) { MaterialInput result = (MaterialInput)0; - result.WorldPosition = output.WorldPosition; - result.TexCoord = output.TexCoord; + result.WorldPosition = output.Geometry.WorldPosition; + result.TexCoord = output.Geometry.TexCoord; #if USE_LIGHTMAP - result.LightmapUV = output.LightmapUV; + result.LightmapUV = output.Geometry.LightmapUV; #endif #if USE_VERTEX_COLOR - result.VertexColor = output.VertexColor; + result.VertexColor = output.Geometry.VertexColor; #endif - result.TBN = CalcTangentBasis(output.WorldNormal, output.WorldTangent); + result.TBN = CalcTangentBasis(output.Geometry.WorldNormal, output.Geometry.WorldTangent); result.TwoSidedSign = WorldDeterminantSign; result.SvPosition = output.Position; result.PreSkinnedPosition = input.Position.xyz; @@ -146,15 +190,15 @@ MaterialInput GetMaterialInput(ModelInput input, VertexOutput output, float3 loc MaterialInput GetMaterialInput(VertexOutput output, float3 localPosition, float3 localNormal) { MaterialInput result = (MaterialInput)0; - result.WorldPosition = output.WorldPosition; - result.TexCoord = output.TexCoord; + result.WorldPosition = output.Geometry.WorldPosition; + result.TexCoord = output.Geometry.TexCoord; #if USE_LIGHTMAP - result.LightmapUV = output.LightmapUV; + result.LightmapUV = output.Geometry.LightmapUV; #endif #if USE_VERTEX_COLOR - result.VertexColor = output.VertexColor; + result.VertexColor = output.Geometry.VertexColor; #endif - result.TBN = CalcTangentBasis(output.WorldNormal, output.WorldTangent); + result.TBN = CalcTangentBasis(output.Geometry.WorldNormal, output.Geometry.WorldTangent); result.TwoSidedSign = WorldDeterminantSign; result.InstanceOrigin = WorldMatrix[3].xyz; result.InstanceParams = float2(PerInstanceRandom, LODDitherFactor); @@ -167,18 +211,18 @@ MaterialInput GetMaterialInput(VertexOutput output, float3 localPosition, float3 MaterialInput GetMaterialInput(PixelInput input) { MaterialInput result = (MaterialInput)0; - result.WorldPosition = input.WorldPosition; - result.TexCoord = input.TexCoord; + result.WorldPosition = input.Geometry.WorldPosition; + result.TexCoord = input.Geometry.TexCoord; #if USE_LIGHTMAP - result.LightmapUV = input.LightmapUV; + result.LightmapUV = input.Geometry.LightmapUV; #endif #if USE_VERTEX_COLOR - result.VertexColor = input.VertexColor; + result.VertexColor = input.Geometry.VertexColor; #endif - result.TBN = CalcTangentBasis(input.WorldNormal, input.WorldTangent); + result.TBN = CalcTangentBasis(input.Geometry.WorldNormal, input.Geometry.WorldTangent); result.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0); - result.InstanceOrigin = input.InstanceOrigin; - result.InstanceParams = input.InstanceParams; + result.InstanceOrigin = input.Geometry.InstanceOrigin; + result.InstanceParams = input.Geometry.InstanceParams; result.SvPosition = input.Position; #if USE_CUSTOM_VERTEX_INTERPOLATORS result.CustomVSToPS = input.CustomVSToPS; @@ -330,9 +374,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Calculates the transform matrix from mesh tangent space to local space float3x3 CalcTangentToLocal(ModelInput input) { @@ -353,7 +394,6 @@ float3x3 CalcTangentToWorld(float4x4 world, float3x3 tangentToLocal) META_VS(IS_SURFACE, FEATURE_LEVEL_ES2) META_PERMUTATION_1(USE_INSTANCING=0) META_PERMUTATION_1(USE_INSTANCING=1) -META_PERMUTATION_2(USE_INSTANCING=0, IS_MOTION_VECTORS_PASS=1) META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true) META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 1, 0, PER_VERTEX, 0, true) META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 1, ALIGN, PER_VERTEX, 0, true) @@ -371,34 +411,32 @@ VertexOutput VS(ModelInput input) // Compute world space vertex position float4x4 world = GetInstanceTransform(input); - output.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz; -#if IS_MOTION_VECTORS_PASS - output.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz; -#endif + output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz; + output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz; // Compute clip space position - output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); // Pass vertex attributes - output.TexCoord = input.TexCoord; + output.Geometry.TexCoord = input.TexCoord; #if USE_VERTEX_COLOR - output.VertexColor = input.Color; + output.Geometry.VertexColor = input.Color; #endif - output.InstanceOrigin = world[3].xyz; + output.Geometry.InstanceOrigin = world[3].xyz; #if USE_INSTANCING - output.LightmapUV = input.LightmapUV * input.InstanceLightmapArea.zw + input.InstanceLightmapArea.xy; - output.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w); + output.Geometry.LightmapUV = input.LightmapUV * input.InstanceLightmapArea.zw + input.InstanceLightmapArea.xy; + output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w); #else - output.LightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy; - output.InstanceParams = float2(PerInstanceRandom, LODDitherFactor); + output.Geometry.LightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy; + output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor); #endif // Calculate tanget space to world space transformation matrix for unit vectors float3x3 tangentToLocal = CalcTangentToLocal(input); float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal); - output.WorldNormal = tangentToWorld[2]; - output.WorldTangent.xyz = tangentToWorld[0]; - output.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f; + output.Geometry.WorldNormal = tangentToWorld[2]; + output.Geometry.WorldTangent.xyz = tangentToWorld[0]; + output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f; // Get material input params if need to evaluate any material property #if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS @@ -408,8 +446,8 @@ VertexOutput VS(ModelInput input) // Apply world position offset per-vertex #if USE_POSITION_OFFSET - output.WorldPosition += material.PositionOffset; - output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); + output.Geometry.WorldPosition += material.PositionOffset; + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); #endif // Get tessalation multiplier (per vertex) @@ -439,7 +477,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position { float4x4 world = GetInstanceTransform(input); float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz; - float4 position = mul(float4(worldPosition.xyz, 1), ViewProjectionMatrix); + float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix); return position; } @@ -524,8 +562,7 @@ float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data) // Vertex Shader function for GBuffers/Depth Pass (skinned mesh rendering) META_VS(IS_SURFACE, FEATURE_LEVEL_ES2) META_PERMUTATION_1(USE_SKINNING=1) -META_PERMUTATION_2(USE_SKINNING=1, IS_MOTION_VECTORS_PASS=1) -META_PERMUTATION_3(USE_SKINNING=1, IS_MOTION_VECTORS_PASS=1, PER_BONE_MOTION_BLUR=1) +META_PERMUTATION_2(USE_SKINNING=1, PER_BONE_MOTION_BLUR=1) META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true) META_VS_IN_ELEMENT(TEXCOORD, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0, true) META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 0, ALIGN, PER_VERTEX, 0, true) @@ -544,37 +581,35 @@ VertexOutput VS_Skinned(ModelInput_Skinned input) // Compute world space vertex position float4x4 world = GetInstanceTransform(input); - output.WorldPosition = mul(float4(position, 1), world).xyz; -#if IS_MOTION_VECTORS_PASS + output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz; #if PER_BONE_MOTION_BLUR float3 prevPosition = SkinPrevPosition(input); - output.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz; + output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz; #else - output.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz; -#endif + output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz; #endif // Compute clip space position - output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); // Pass vertex attributes - output.TexCoord = input.TexCoord; + output.Geometry.TexCoord = input.TexCoord; #if USE_VERTEX_COLOR - output.VertexColor = float4(0, 0, 0, 1); + output.Geometry.VertexColor = float4(0, 0, 0, 1); #endif - output.LightmapUV = float2(0, 0); - output.InstanceOrigin = world[3].xyz; + output.Geometry.LightmapUV = float2(0, 0); + output.Geometry.InstanceOrigin = world[3].xyz; #if USE_INSTANCING - output.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w); + output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w); #else - output.InstanceParams = float2(PerInstanceRandom, LODDitherFactor); + output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor); #endif // Calculate tanget space to world space transformation matrix for unit vectors float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal); - output.WorldNormal = tangentToWorld[2]; - output.WorldTangent.xyz = tangentToWorld[0]; - output.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f; + output.Geometry.WorldNormal = tangentToWorld[2]; + output.Geometry.WorldTangent.xyz = tangentToWorld[0]; + output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f; // Get material input params if need to evaluate any material property #if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS @@ -584,8 +619,8 @@ VertexOutput VS_Skinned(ModelInput_Skinned input) // Apply world position offset per-vertex #if USE_POSITION_OFFSET - output.WorldPosition += material.PositionOffset; - output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); + output.Geometry.WorldPosition += material.PositionOffset; + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); #endif // Get tessalation multiplier (per vertex) @@ -721,10 +756,8 @@ void PS_Depth(PixelInput input // Pixel Shader function for Motion Vectors Pass META_PS(true, FEATURE_LEVEL_ES2) -META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=1) float4 PS_MotionVectors(PixelInput input) : SV_Target0 { -#if IS_MOTION_VECTORS_PASS // LOD masking ClipLODTransition(input); @@ -736,8 +769,8 @@ float4 PS_MotionVectors(PixelInput input) : SV_Target0 #endif // Calculate this and previosu frame pixel locations in clip space - float4 prevClipPos = mul(float4(input.PrevWorldPosition, 1), PrevViewProjectionMatrix); - float4 curClipPos = mul(float4(input.WorldPosition, 1), ViewProjectionMatrix); + float4 prevClipPos = mul(float4(input.Geometry.PrevWorldPosition, 1), PrevViewProjectionMatrix); + float4 curClipPos = mul(float4(input.Geometry.WorldPosition, 1), ViewProjectionMatrix); float2 prevHPos = prevClipPos.xy / prevClipPos.w; float2 curHPos = curClipPos.xy / curClipPos.w; @@ -753,9 +786,6 @@ float4 PS_MotionVectors(PixelInput input) : SV_Target0 // Calculate per-pixel motion vector return float4(vPosCur - vPosPrev, 0, 1); -#else - return float4(0, 0, 0, 1); -#endif } @9 diff --git a/Content/Editor/MaterialTemplates/SurfaceForward.shader b/Content/Editor/MaterialTemplates/SurfaceForward.shader index 9ce0a5f5a..0e9c6db5f 100644 --- a/Content/Editor/MaterialTemplates/SurfaceForward.shader +++ b/Content/Editor/MaterialTemplates/SurfaceForward.shader @@ -338,9 +338,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Calculates the transform matrix from mesh tangent space to local space half3x3 CalcTangentToLocal(ModelInput input) { @@ -432,31 +429,6 @@ VertexOutput VS(ModelInput input) // The skeletal bones matrix buffer (stored as 4x3, 3 float4 behind each other) Buffer BoneMatrices : register(t0); -#if PER_BONE_MOTION_BLUR - -// The skeletal bones matrix buffer from the previous frame -Buffer PrevBoneMatrices : register(t1); - -float3x4 GetPrevBoneMatrix(int index) -{ - float4 a = PrevBoneMatrices[index * 3]; - float4 b = PrevBoneMatrices[index * 3 + 1]; - float4 c = PrevBoneMatrices[index * 3 + 2]; - return float3x4(a, b, c); -} - -float3 SkinPrevPosition(ModelInput_Skinned input) -{ - float4 position = float4(input.Position.xyz, 1); - float3x4 boneMatrix = input.BlendWeights.x * GetPrevBoneMatrix(input.BlendIndices.x); - boneMatrix += input.BlendWeights.y * GetPrevBoneMatrix(input.BlendIndices.y); - boneMatrix += input.BlendWeights.z * GetPrevBoneMatrix(input.BlendIndices.z); - boneMatrix += input.BlendWeights.w * GetPrevBoneMatrix(input.BlendIndices.w); - return mul(boneMatrix, position); -} - -#endif - // Cached skinning data to avoid multiple calculation struct SkinningData { diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader index 0a6cb8028..c36d7f0c5 100644 --- a/Content/Editor/MaterialTemplates/Terrain.shader +++ b/Content/Editor/MaterialTemplates/Terrain.shader @@ -3,7 +3,6 @@ #define MATERIAL 1 @3 - // Enables/disables smooth terrain chunks LOD transitions (with morphing higher LOD near edges to the lower LOD in the neighbour) #define USE_SMOOTH_LOD_TRANSITION 1 @@ -26,7 +25,6 @@ float3 ViewDir; float TimeParam; float4 ViewInfo; float4 ScreenSize; -float4 LightmapArea; float3 WorldInvScale; float WorldDeterminantSign; float PerInstanceRandom; @@ -39,31 +37,32 @@ float2 OffsetUV; float2 Dummy0; @1META_CB_END -// Irradiance and directionality prebaked lightmaps -Texture2D Lightmap0 : register(t0); -Texture2D Lightmap1 : register(t1); -Texture2D Lightmap2 : register(t2); - // Terrain data -Texture2D Heightmap : register(t3); -Texture2D Splatmap0 : register(t4); -Texture2D Splatmap1 : register(t5); +Texture2D Heightmap : register(t0); +Texture2D Splatmap0 : register(t1); +Texture2D Splatmap1 : register(t2); // Material shader resources @2 -// Interpolants passed from the vertex shader -struct VertexOutput +// Geometry data passed though the graphics rendering stages up to the pixel shader +struct GeometryData { - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; - float3 WorldNormal : TEXCOORD3; - float HolesMask : TEXCOORD4; + float3 WorldPosition : TEXCOORD0; + float2 TexCoord : TEXCOORD1; + float2 LightmapUV : TEXCOORD2; + float3 WorldNormal : TEXCOORD3; + float HolesMask : TEXCOORD4; #if USE_TERRAIN_LAYERS float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5; #endif +}; + +// Interpolants passed from the vertex shader +struct VertexOutput +{ + float4 Position : SV_Position; + GeometryData Geometry; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; #endif @@ -75,19 +74,12 @@ struct VertexOutput // Interpolants passed to the pixel shader struct PixelInput { - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; - float3 WorldNormal : TEXCOORD3; - float HolesMask : TEXCOORD4; -#if USE_TERRAIN_LAYERS - float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5; -#endif + float4 Position : SV_Position; + GeometryData Geometry; #if USE_CUSTOM_VERTEX_INTERPOLATORS float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; #endif - bool IsFrontFace : SV_IsFrontFace; + bool IsFrontFace : SV_IsFrontFace; }; // Material properties generation input @@ -112,20 +104,69 @@ struct MaterialInput #endif }; +// Extracts geometry data to the material input +void GetGeometryMaterialInput(inout MaterialInput result, in GeometryData geometry) +{ + result.WorldPosition = geometry.WorldPosition; + result.TexCoord = geometry.TexCoord; +#if USE_LIGHTMAP + result.LightmapUV = geometry.LightmapUV; +#endif + result.TBN = CalcTangentBasisFromWorldNormal(geometry.WorldNormal); + result.HolesMask = geometry.HolesMask; +#if USE_TERRAIN_LAYERS + result.Layers = geometry.Layers; +#endif +} + +#if USE_TESSELLATION + +// Interpolates the geometry positions data only (used by the tessallation when generating vertices) +#define InterpolateGeometryPositions(output, p0, w0, p1, w1, p2, w2, offset) output.WorldPosition = p0.WorldPosition * w0 + p1.WorldPosition * w1 + p2.WorldPosition * w2 + offset + +// Offsets the geometry positions data only (used by the tessallation when generating vertices) +#define OffsetGeometryPositions(geometry, offset) geometry.WorldPosition += offset + +// Applies the Phong tessallation to the geometry positions (used by the tessallation when doing Phong tess) +#define ApplyGeometryPositionsPhongTess(geometry, p0, p1, p2, U, V, W) \ + float3 posProjectedU = TessalationProjectOntoPlane(p0.WorldNormal, p0.WorldPosition, geometry.WorldPosition); \ + float3 posProjectedV = TessalationProjectOntoPlane(p1.WorldNormal, p1.WorldPosition, geometry.WorldPosition); \ + float3 posProjectedW = TessalationProjectOntoPlane(p2.WorldNormal, p2.WorldPosition, geometry.WorldPosition); \ + geometry.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW + +// Interpolates the geometry data except positions (used by the tessallation when generating vertices) +GeometryData InterpolateGeometry(GeometryData p0, float w0, GeometryData p1, float w1, GeometryData p2, float w2) +{ + GeometryData output = (GeometryData)0; + output.TexCoord = p0.TexCoord * w0 + p1.TexCoord * w1 + p2.TexCoord * w2; + output.LightmapUV = p0.LightmapUV * w0 + p1.LightmapUV * w1 + p2.LightmapUV * w2; + output.WorldNormal = p0.WorldNormal * w0 + p1.WorldNormal * w1 + p2.WorldNormal * w2; + output.WorldNormal = normalize(output.WorldNormal); + output.HolesMask = p0.HolesMask * w0 + p1.HolesMask * w1 + p2.HolesMask * w2; +#if USE_TERRAIN_LAYERS + UNROLL + for (int i = 0; i < TERRAIN_LAYERS_DATA_SIZE; i++) + output.Layers[i] = p0.Layers[i] * w0 + p1.Layers[i] * w1 + p2.Layers[i] * w2; +#endif + return output; +} + +#endif + MaterialInput GetMaterialInput(PixelInput input) { MaterialInput result = (MaterialInput)0; - result.WorldPosition = input.WorldPosition; - result.TexCoord = input.TexCoord; + result.WorldPosition = input.Geometry.WorldPosition; + result.TexCoord = input.Geometry.TexCoord; #if USE_LIGHTMAP - result.LightmapUV = input.LightmapUV; + result.LightmapUV = input.Geometry.LightmapUV; #endif - result.TBN = CalcTangentBasisFromWorldNormal(input.WorldNormal); + result.TBN = CalcTangentBasisFromWorldNormal(input.Geometry.WorldNormal); result.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0); result.SvPosition = input.Position; - result.HolesMask = input.HolesMask; + result.HolesMask = input.Geometry.HolesMask; #if USE_TERRAIN_LAYERS - result.Layers = input.Layers; + result.Layers = input.Geometry.Layers; #endif #if USE_CUSTOM_VERTEX_INTERPOLATORS result.CustomVSToPS = input.CustomVSToPS; @@ -212,20 +253,6 @@ float4 GetVertexColor(MaterialInput input) return 1; } -// Evaluates the H-Basis coefficients in the tangent space normal direction -float3 GetHBasisIrradiance(float3 n, float3 h0, float3 h1, float3 h2, float3 h3) -{ - // Band 0 - float3 color = h0 * (1.0f / sqrt(2.0f * PI)); - - // Band 1 - color += h1 * -sqrt(1.5f / PI) * n.y; - color += h2 * sqrt(1.5f / PI) * (2 * n.z - 1.0f); - color += h3 * -sqrt(1.5f / PI) * n.x; - - return color; -} - @8 // Get material properties function (for vertex shader) @@ -246,9 +273,6 @@ Material GetMaterialPS(MaterialInput input) @4 } -// Fix line for errors/warnings for shader code from template -#line 1000 - // Calculates LOD value (with fractional part for blending) float CalcLOD(float2 xy, float4 morph) { @@ -297,7 +321,7 @@ float3x3 CalcTangentToWorld(float4x4 world, float3x3 tangentToLocal) struct TerrainVertexInput { float2 TexCoord : TEXCOORD0; - float4 Morph : TEXCOORD1; + float4 Morph : TEXCOORD1; }; // Vertex Shader function for terrain rendering @@ -348,7 +372,7 @@ VertexOutput VS(TerrainVertexInput input) float2 normalTemp = float2(heightmapValue.b, heightmapValue.a) * 2.0f - 1.0f; float3 normal = float3(normalTemp.x, sqrt(1.0 - saturate(dot(normalTemp, normalTemp))), normalTemp.y); normal = normalize(normal); - output.HolesMask = isHole ? 0 : 1; + output.Geometry.HolesMask = isHole ? 0 : 1; if (isHole) { normal = float3(0, 1, 0); @@ -365,10 +389,10 @@ VertexOutput VS(TerrainVertexInput input) float3 position = float3(positionXZ.x, height, positionXZ.y); // Compute world space vertex position - output.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz; + output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz; // Compute clip space position - output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); // Pass vertex attributes #if USE_SMOOTH_LOD_TRANSITION @@ -376,46 +400,46 @@ VertexOutput VS(TerrainVertexInput input) #else float2 texCoord = input.TexCoord; #endif - output.TexCoord = positionXZ * (1.0f / TerrainChunkSizeLOD0) + OffsetUV; - output.LightmapUV = texCoord * LightmapArea.zw + LightmapArea.xy; + output.Geometry.TexCoord = positionXZ * (1.0f / TerrainChunkSizeLOD0) + OffsetUV; + output.Geometry.LightmapUV = texCoord * LightmapArea.zw + LightmapArea.xy; // Extract terrain layers weights from the splatmap #if USE_TERRAIN_LAYERS - output.Layers[0] = splatmap0Value; + output.Geometry.Layers[0] = splatmap0Value; #if TERRAIN_LAYERS_DATA_SIZE > 1 - output.Layers[1] = splatmap1Value; + output.Geometry.Layers[1] = splatmap1Value; #endif #endif // Compute world space normal vector float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal); float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal); - output.WorldNormal = tangentToWorld[2]; + output.Geometry.WorldNormal = tangentToWorld[2]; // Get material input params if need to evaluate any material property #if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS MaterialInput materialInput = (MaterialInput)0; - materialInput.WorldPosition = output.WorldPosition; - materialInput.TexCoord = output.TexCoord; + materialInput.WorldPosition = output.Geometry.WorldPosition; + materialInput.TexCoord = output.Geometry.TexCoord; #if USE_LIGHTMAP - materialInput.LightmapUV = output.LightmapUV; + materialInput.LightmapUV = output.Geometry.LightmapUV; #endif - materialInput.TBN = CalcTangentBasisFromWorldNormal(output.WorldNormal); + materialInput.TBN = CalcTangentBasisFromWorldNormal(output.Geometry.WorldNormal); materialInput.TwoSidedSign = WorldDeterminantSign; materialInput.SvPosition = output.Position; materialInput.PreSkinnedPosition = position; materialInput.PreSkinnedNormal = normal; - materialInput.HolesMask = output.HolesMask; + materialInput.HolesMask = output.Geometry.HolesMask; #if USE_TERRAIN_LAYERS - materialInput.Layers = output.Layers; + materialInput.Layers = output.Geometry.Layers; #endif Material material = GetMaterialVS(materialInput); #endif // Apply world position offset per-vertex #if USE_POSITION_OFFSET - output.WorldPosition += material.PositionOffset; - output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix); + output.Geometry.WorldPosition += material.PositionOffset; + output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix); #endif // Get tessalation multiplier (per vertex) @@ -431,277 +455,6 @@ VertexOutput VS(TerrainVertexInput input) return output; } -#if USE_TESSELLATION - -// Interpolants passed from the hull shader to the domain shader -struct TessalationHSToDS -{ - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; - float3 WorldNormal : TEXCOORD3; - float HolesMask : TEXCOORD4; -#if USE_TERRAIN_LAYERS - float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5; -#endif -#if USE_CUSTOM_VERTEX_INTERPOLATORS - float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; -#endif - float TessellationMultiplier : TESS; -}; - -// Interpolants passed from the domain shader and to the pixel shader -struct TessalationDSToPS -{ - float4 Position : SV_Position; - float3 WorldPosition : TEXCOORD0; - float2 TexCoord : TEXCOORD1; - float2 LightmapUV : TEXCOORD2; - float3 WorldNormal : TEXCOORD3; - float HolesMask : TEXCOORD4; -#if USE_TERRAIN_LAYERS - float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5; -#endif -#if USE_CUSTOM_VERTEX_INTERPOLATORS - float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9; -#endif -}; - -MaterialInput GetMaterialInput(TessalationDSToPS input) -{ - MaterialInput result = (MaterialInput)0; - result.WorldPosition = input.WorldPosition; - result.TexCoord = input.TexCoord; -#if USE_LIGHTMAP - result.LightmapUV = input.LightmapUV; -#endif - result.TBN = CalcTangentBasisFromWorldNormal(input.WorldNormal); - result.TwoSidedSign = WorldDeterminantSign; - result.SvPosition = input.Position; - result.HolesMask = input.HolesMask; -#if USE_TERRAIN_LAYERS - result.Layers = input.Layers; -#endif -#if USE_CUSTOM_VERTEX_INTERPOLATORS - result.CustomVSToPS = input.CustomVSToPS; -#endif - return result; -} - -struct TessalationPatch -{ - float EdgeTessFactor[3] : SV_TessFactor; - float InsideTessFactor : SV_InsideTessFactor; -#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN - float3 B210 : POSITION4; - float3 B120 : POSITION5; - float3 B021 : POSITION6; - float3 B012 : POSITION7; - float3 B102 : POSITION8; - float3 B201 : POSITION9; - float3 B111 : CENTER; -#endif -}; - -TessalationPatch HS_PatchConstant(InputPatch input) -{ - TessalationPatch output; - - // Average tess factors along edges, and pick an edge tess factor for the interior tessellation - float4 TessellationMultipliers; - TessellationMultipliers.x = 0.5f * (input[1].TessellationMultiplier + input[2].TessellationMultiplier); - TessellationMultipliers.y = 0.5f * (input[2].TessellationMultiplier + input[0].TessellationMultiplier); - TessellationMultipliers.z = 0.5f * (input[0].TessellationMultiplier + input[1].TessellationMultiplier); - TessellationMultipliers.w = 0.333f * (input[0].TessellationMultiplier + input[1].TessellationMultiplier + input[2].TessellationMultiplier); - - TessellationMultipliers = clamp(TessellationMultipliers, 1, MAX_TESSELLATION_FACTOR); - - output.EdgeTessFactor[0] = TessellationMultipliers.x; // 1->2 edge - output.EdgeTessFactor[1] = TessellationMultipliers.y; // 2->0 edge - output.EdgeTessFactor[2] = TessellationMultipliers.z; // 0->1 edge - output.InsideTessFactor = TessellationMultipliers.w; - -#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN - // Calculate PN-Triangle coefficients - // Refer to Vlachos 2001 for the original formula - float3 p1 = input[0].WorldPosition; - float3 p2 = input[1].WorldPosition; - float3 p3 = input[2].WorldPosition; - float3 n1 = input[0].WorldNormal; - float3 n2 = input[1].WorldNormal; - float3 n3 = input[2].WorldNormal; - - // Calculate control points - output.B210 = (2.0f * p1 + p2 - dot((p2 - p1), n1) * n1) / 3.0f; - output.B120 = (2.0f * p2 + p1 - dot((p1 - p2), n2) * n2) / 3.0f; - output.B021 = (2.0f * p2 + p3 - dot((p3 - p2), n2) * n2) / 3.0f; - output.B012 = (2.0f * p3 + p2 - dot((p2 - p3), n3) * n3) / 3.0f; - output.B102 = (2.0f * p3 + p1 - dot((p1 - p3), n3) * n3) / 3.0f; - output.B201 = (2.0f * p1 + p3 - dot((p3 - p1), n1) * n1) / 3.0f; - float3 e = (output.B210 + output.B120 + output.B021 + - output.B012 + output.B102 + output.B201) / 6.0f; - float3 v = (p1 + p2 + p3) / 3.0f; - output.B111 = e + ((e - v) / 2.0f); -#endif - - return output; -} - -META_HS(USE_TESSELLATION, FEATURE_LEVEL_SM5) -META_HS_PATCH(TESSELLATION_IN_CONTROL_POINTS) -[domain("tri")] -[partitioning("fractional_odd")] -[outputtopology("triangle_cw")] -[maxtessfactor(MAX_TESSELLATION_FACTOR)] -[outputcontrolpoints(3)] -[patchconstantfunc("HS_PatchConstant")] -TessalationHSToDS HS(InputPatch input, uint ControlPointID : SV_OutputControlPointID) -{ - TessalationHSToDS output; - - // Pass through shader -#define COPY(thing) output.thing = input[ControlPointID].thing; - COPY(Position); - COPY(WorldPosition); - COPY(TexCoord); - COPY(LightmapUV); - COPY(WorldNormal); - COPY(HolesMask); - COPY(TessellationMultiplier); -#if USE_TERRAIN_LAYERS - COPY(Layers); -#endif -#if USE_CUSTOM_VERTEX_INTERPOLATORS - COPY(CustomVSToPS); -#endif -#undef COPY - - return output; -} - -#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG - -// Orthogonal projection on to plane -float3 ProjectOntoPlane(float3 planeNormal, float3 planePoint, float3 pointToProject) -{ - return pointToProject - dot(pointToProject-planePoint, planeNormal) * planeNormal; -} - -#endif - -META_DS(USE_TESSELLATION, FEATURE_LEVEL_SM5) -[domain("tri")] -TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : SV_DomainLocation, const OutputPatch input) -{ - TessalationDSToPS output; - - // Get the barycentric coords - float U = barycentricCoords.x; - float V = barycentricCoords.y; - float W = barycentricCoords.z; - - // Interpolate patch attributes to generated vertices -#define INTERPOLATE(thing) output.thing = U * input[0].thing + V * input[1].thing + W * input[2].thing -#define COPY(thing) output.thing = input[0].thing - INTERPOLATE(Position); -#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN - float UU = U * U; - float VV = V * V; - float WW = W * W; - float UU3 = UU * 3.0f; - float VV3 = VV * 3.0f; - float WW3 = WW * 3.0f; - - // Interpolate using barycentric coordinates and PN Triangle control points - output.WorldPosition = - input[0].WorldPosition * UU * U + - input[1].WorldPosition * VV * V + - input[2].WorldPosition * WW * W + - constantData.B210 * UU3 * V + - constantData.B120 * VV3 * U + - constantData.B021 * VV3 * W + - constantData.B012 * WW3 * V + - constantData.B102 * WW3 * U + - constantData.B201 * UU3 * W + - constantData.B111 * 6.0f * W * U * V; -#else - INTERPOLATE(WorldPosition); -#endif - INTERPOLATE(TexCoord); - INTERPOLATE(LightmapUV); - INTERPOLATE(WorldNormal); - INTERPOLATE(HolesMask); -#if USE_TERRAIN_LAYERS - UNROLL - for (int i = 0; i < TERRAIN_LAYERS_DATA_SIZE; i++) - { - INTERPOLATE(Layers[i]); - } -#endif -#if USE_CUSTOM_VERTEX_INTERPOLATORS - UNROLL - for (int i = 0; i < CUSTOM_VERTEX_INTERPOLATORS_COUNT; i++) - { - INTERPOLATE(CustomVSToPS[i]); - } -#endif -#undef INTERPOLATE -#undef COPY - - // Interpolating normal can unnormalize it, so normalize it - output.WorldNormal = normalize(output.WorldNormal); - -#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG - // Orthogonal projection in the tangent planes - float3 posProjectedU = ProjectOntoPlane(input[0].WorldNormal, input[0].WorldPosition, output.WorldPosition); - float3 posProjectedV = ProjectOntoPlane(input[1].WorldNormal, input[1].WorldPosition, output.WorldPosition); - float3 posProjectedW = ProjectOntoPlane(input[2].WorldNormal, input[2].WorldPosition, output.WorldPosition); - - // Interpolate the projected points - output.WorldPosition = U * posProjectedU + V * posProjectedV + W * posProjectedW; -#endif - - // Perform displacement mapping -#if USE_DISPLACEMENT - MaterialInput materialInput = GetMaterialInput(output); - Material material = GetMaterialDS(materialInput); - output.WorldPosition += material.WorldDisplacement; -#endif - - // Recalculate the clip space position - output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix); - - return output; -} - -#endif - -#if USE_LIGHTMAP - -float3 SampleLightmap(Material material, MaterialInput materialInput) -{ - // Sample lightmaps - float4 lightmap0 = Lightmap0.Sample(SamplerLinearClamp, materialInput.LightmapUV); - float4 lightmap1 = Lightmap1.Sample(SamplerLinearClamp, materialInput.LightmapUV); - float4 lightmap2 = Lightmap2.Sample(SamplerLinearClamp, materialInput.LightmapUV); - - // Unpack H-basis - float3 h0 = float3(lightmap0.x, lightmap1.x, lightmap2.x); - float3 h1 = float3(lightmap0.y, lightmap1.y, lightmap2.y); - float3 h2 = float3(lightmap0.z, lightmap1.z, lightmap2.z); - float3 h3 = float3(lightmap0.w, lightmap1.w, lightmap2.w); - - // Sample baked diffuse irradiance from the H-basis coefficients - float3 normal = material.TangentNormal; -#if MATERIAL_SHADING_MODEL == SHADING_MODEL_FOLIAGE - normal *= material.TangentNormal; -#endif - return GetHBasisIrradiance(normal, h0, h1, h2, h3) / PI; -} - -#endif - // Pixel Shader function for GBuffer Pass META_PS(true, FEATURE_LEVEL_ES2) META_PERMUTATION_1(USE_LIGHTMAP=0) diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp index 322726a3e..585f4f1fd 100644 --- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp @@ -194,7 +194,7 @@ bool DeferredMaterialShader::Load() psDesc.VS = _shader->GetVS("VS", 1); _cacheInstanced.Default.Init(psDesc); - // GBuffer Pass with lightmap (use pixel shader permutation for USE_LIGHTMAP=1) + // GBuffer Pass with lightmap (pixel shader permutation for USE_LIGHTMAP=1) psDesc.VS = _shader->GetVS("VS"); psDesc.PS = _shader->GetPS("PS_GBuffer", 1); _cache.DefaultLightmap.Init(psDesc); @@ -210,21 +210,16 @@ bool DeferredMaterialShader::Load() psDesc.DepthWriteEnable = false; psDesc.DepthTestEnable = true; psDesc.DepthFunc = ComparisonFunc::LessEqual; - if (useTess) - { - psDesc.HS = _shader->GetHS("HS", 1); - psDesc.DS = _shader->GetDS("DS", 1); - } - psDesc.VS = _shader->GetVS("VS", 2); + psDesc.VS = _shader->GetVS("VS"); psDesc.PS = _shader->GetPS("PS_MotionVectors"); _cache.MotionVectors.Init(psDesc); // Motion Vectors pass with skinning - psDesc.VS = _shader->GetVS("VS_Skinned", 1); + psDesc.VS = _shader->GetVS("VS_Skinned"); _cache.MotionVectorsSkinned.Init(psDesc); // Motion Vectors pass with skinning (with per-bone motion blur) - psDesc.VS = _shader->GetVS("VS_Skinned", 2); + psDesc.VS = _shader->GetVS("VS_Skinned", 1); _cache.MotionVectorsSkinnedPerBone.Init(psDesc); // Depth Pass diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index a07e740f8..0355b7435 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -139,13 +139,13 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, byte*& cb, in { // Bind lightmap textures GPUTexture *lightmap0, *lightmap1, *lightmap2; - drawCall.Surface.Lightmap->GetTextures(&lightmap0, &lightmap1, &lightmap2); - context->BindSR(0, lightmap0); - context->BindSR(1, lightmap1); - context->BindSR(2, lightmap2); + drawCall.Features.Lightmap->GetTextures(&lightmap0, &lightmap1, &lightmap2); + context->BindSR(srv + 0, lightmap0); + context->BindSR(srv + 1, lightmap1); + context->BindSR(srv + 2, lightmap2); // Set lightmap data - data.LightmapArea = drawCall.Surface.LightmapUVsArea; + data.LightmapArea = drawCall.Features.LightmapUVsArea; } srv += SRVs; diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp index 68c5fbd20..633448fb5 100644 --- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2021 Wojciech Figat. All rights reserved. #include "TerrainMaterialShader.h" +#include "MaterialShaderFeatures.h" #include "MaterialParams.h" #include "Engine/Engine/Time.h" #include "Engine/Graphics/GPUContext.h" @@ -25,7 +26,6 @@ PACK_STRUCT(struct TerrainMaterialShaderData { float TimeParam; Vector4 ViewInfo; Vector4 ScreenSize; - Rectangle LightmapArea; Vector3 WorldInvScale; float WorldDeterminantSign; float PerInstanceRandom; @@ -56,11 +56,21 @@ void TerrainMaterialShader::Bind(BindParameters& params) auto& drawCall = *params.FirstDrawCall; const auto cb0 = _shader->GetCB(0); const bool hasCb0 = cb0->GetSize() != 0; + ASSERT(hasCb0 && "TODO: fix it"); // TODO: always make cb pointer valid even if cb is missing + byte* cb = _cb0Data.Get(); + auto materialData = reinterpret_cast(cb); + cb += sizeof(TerrainMaterialShaderData); + int32 srv = 3; + + // Setup features + if (_info.TessellationMode != TessellationMethod::None) + TessellationFeature::Bind(params, cb, srv); + const bool useLightmap = LightmapFeature::Bind(params, cb, srv); // Setup parameters MaterialParameter::BindMeta bindMeta; bindMeta.Context = context; - bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(TerrainMaterialShaderData) : nullptr; + bindMeta.Constants = cb; bindMeta.Input = nullptr; bindMeta.Buffers = nullptr; bindMeta.CanSampleDepth = false; @@ -68,64 +78,42 @@ void TerrainMaterialShader::Bind(BindParameters& params) MaterialParams::Bind(params.ParamsLink, bindMeta); // Setup material constants data - auto data = reinterpret_cast(_cb0Data.Get()); if (hasCb0) { - Matrix::Transpose(view.Frustum.GetMatrix(), data->ViewProjectionMatrix); - Matrix::Transpose(drawCall.World, data->WorldMatrix); - Matrix::Transpose(view.View, data->ViewMatrix); + Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); + Matrix::Transpose(drawCall.World, materialData->WorldMatrix); + Matrix::Transpose(view.View, materialData->ViewMatrix); - data->ViewPos = view.Position; - data->ViewFar = view.Far; - data->ViewDir = view.Direction; - data->TimeParam = Time::Draw.UnscaledTime.GetTotalSeconds(); - data->ViewInfo = view.ViewInfo; - data->ScreenSize = view.ScreenSize; - - // Extract per axis scales from LocalToWorld transform + materialData->ViewPos = view.Position; + materialData->ViewFar = view.Far; + materialData->ViewDir = view.Direction; + materialData->TimeParam = Time::Draw.UnscaledTime.GetTotalSeconds(); + materialData->ViewInfo = view.ViewInfo; + materialData->ScreenSize = view.ScreenSize; const float scaleX = Vector3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length(); const float scaleY = Vector3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length(); const float scaleZ = Vector3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length(); - data->WorldInvScale = Vector3( + materialData->WorldInvScale = Vector3( scaleX > 0.00001f ? 1.0f / scaleX : 0.0f, scaleY > 0.00001f ? 1.0f / scaleY : 0.0f, scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f); - - data->WorldDeterminantSign = drawCall.WorldDeterminantSign; - data->PerInstanceRandom = drawCall.PerInstanceRandom; - data->CurrentLOD = drawCall.Terrain.CurrentLOD; - data->ChunkSizeNextLOD = drawCall.Terrain.ChunkSizeNextLOD; - data->TerrainChunkSizeLOD0 = drawCall.Terrain.TerrainChunkSizeLOD0; - data->HeightmapUVScaleBias = drawCall.Terrain.HeightmapUVScaleBias; - data->NeighborLOD = drawCall.Terrain.NeighborLOD; - data->OffsetUV = drawCall.Terrain.OffsetUV; - } - const bool useLightmap = view.Flags & ViewFlags::GI -#if USE_EDITOR - && EnableLightmapsUsage -#endif - && view.Pass == DrawPass::GBuffer - && drawCall.Terrain.Lightmap != nullptr; - if (useLightmap) - { - // Bind lightmap textures - GPUTexture *lightmap0, *lightmap1, *lightmap2; - drawCall.Terrain.Lightmap->GetTextures(&lightmap0, &lightmap1, &lightmap2); - context->BindSR(0, lightmap0); - context->BindSR(1, lightmap1); - context->BindSR(2, lightmap2); - - // Set lightmap data - data->LightmapArea = drawCall.Terrain.LightmapUVsArea; + materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; + materialData->PerInstanceRandom = drawCall.PerInstanceRandom; + materialData->CurrentLOD = drawCall.Terrain.CurrentLOD; + materialData->ChunkSizeNextLOD = drawCall.Terrain.ChunkSizeNextLOD; + materialData->TerrainChunkSizeLOD0 = drawCall.Terrain.TerrainChunkSizeLOD0; + materialData->HeightmapUVScaleBias = drawCall.Terrain.HeightmapUVScaleBias; + materialData->NeighborLOD = drawCall.Terrain.NeighborLOD; + materialData->OffsetUV = drawCall.Terrain.OffsetUV; } // Bind terrain textures - const auto heightmap = drawCall.Terrain.Patch->Heightmap.Get()->GetTexture(); + const auto heightmap = drawCall.Terrain.Patch->Heightmap->GetTexture(); const auto splatmap0 = drawCall.Terrain.Patch->Splatmap[0] ? drawCall.Terrain.Patch->Splatmap[0]->GetTexture() : nullptr; const auto splatmap1 = drawCall.Terrain.Patch->Splatmap[1] ? drawCall.Terrain.Patch->Splatmap[1]->GetTexture() : nullptr; - context->BindSR(3, heightmap); - context->BindSR(4, splatmap0); - context->BindSR(5, splatmap1); + context->BindSR(0, heightmap); + context->BindSR(1, splatmap0); + context->BindSR(2, splatmap1); // Bind constants if (hasCb0) diff --git a/Source/Engine/Renderer/DrawCall.h b/Source/Engine/Renderer/DrawCall.h index 31656145b..0e91366e2 100644 --- a/Source/Engine/Renderer/DrawCall.h +++ b/Source/Engine/Renderer/DrawCall.h @@ -167,8 +167,14 @@ struct DrawCall struct { const Lightmap* Lightmap; - SkinnedMeshDrawData* Skinning; Rectangle LightmapUVsArea; + } Features; + + struct + { + const Lightmap* Lightmap; + Rectangle LightmapUVsArea; + SkinnedMeshDrawData* Skinning; Vector3 GeometrySize; // Object geometry size in the world (unscaled). float LODDitherFactor; // The model LOD transition dither progress. Matrix PrevWorld; @@ -176,15 +182,15 @@ struct DrawCall struct { + const Lightmap* Lightmap; + Rectangle LightmapUVsArea; Vector4 HeightmapUVScaleBias; Vector4 NeighborLOD; Vector2 OffsetUV; float CurrentLOD; float ChunkSizeNextLOD; float TerrainChunkSizeLOD0; - Rectangle LightmapUVsArea; const class TerrainPatch* Patch; - const Lightmap* Lightmap; } Terrain; struct diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp index 61c05149d..b6b1b55e1 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.cpp @@ -187,6 +187,11 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo if (materialInfo.BlendMode == MaterialBlendMode::Opaque) ADD_FEATURE(LightmapFeature); break; + case MaterialDomain::Terrain: + if (materialInfo.TessellationMode != TessellationMethod::None) + ADD_FEATURE(TessellationFeature); + ADD_FEATURE(LightmapFeature); + break; default: break; } @@ -387,7 +392,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo srv = 1; break; case MaterialDomain::Terrain: - srv = 6; + srv = 3; // Heightmap + 2 splatmaps break; case MaterialDomain::Particle: srv = 5; diff --git a/Source/Shaders/MaterialCommon.hlsl b/Source/Shaders/MaterialCommon.hlsl index aef3fc579..8fc981cd7 100644 --- a/Source/Shaders/MaterialCommon.hlsl +++ b/Source/Shaders/MaterialCommon.hlsl @@ -61,9 +61,6 @@ #ifndef MAX_TESSELLATION_FACTOR #define MAX_TESSELLATION_FACTOR 15 #endif -#ifndef IS_MOTION_VECTORS_PASS - #define IS_MOTION_VECTORS_PASS 0 -#endif #ifndef PER_BONE_MOTION_BLUR #define PER_BONE_MOTION_BLUR 0 #endif @@ -164,6 +161,12 @@ float3x3 CalcTangentBasisFromWorldNormal(float3 normal) return float3x3(tangent, bitangent, normal); } +float3x3 CalcTangentBasis(float3 normal, float4 tangent) +{ + float3 bitangent = cross(normal, tangent.xyz) * tangent.w; + return float3x3(tangent.xyz, bitangent, normal); +} + // [Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion"] float3 AOMultiBounce(float visibility, float3 albedo) {