Refactor material shaders generator to use modular features as extensions
This commit is contained in:
@@ -116,9 +116,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Input macro specified by the material: DECAL_BLEND_MODE
|
// Input macro specified by the material: DECAL_BLEND_MODE
|
||||||
|
|
||||||
#define DECAL_BLEND_MODE_TRANSLUCENT 0
|
#define DECAL_BLEND_MODE_TRANSLUCENT 0
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
@0// Tessellation: Defines
|
@0// Tessellation: Defines
|
||||||
|
#define TessalationProjectOntoPlane(planeNormal, planePosition, pointToProject) pointToProject - dot(pointToProject - planePosition, planeNormal) * planeNormal
|
||||||
@1// Tessellation: Includes
|
@1// Tessellation: Includes
|
||||||
@2// Tessellation: Constants
|
@2// Tessellation: Constants
|
||||||
@3// Tessellation: Resources
|
@3// Tessellation: Resources
|
||||||
@@ -11,22 +12,10 @@
|
|||||||
// Interpolants passed from the hull shader to the domain shader
|
// Interpolants passed from the hull shader to the domain shader
|
||||||
struct TessalationHSToDS
|
struct TessalationHSToDS
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
float3 WorldPosition : TEXCOORD0;
|
GeometryData Geometry;
|
||||||
float2 TexCoord : TEXCOORD1;
|
|
||||||
float2 LightmapUV : TEXCOORD2;
|
|
||||||
#if USE_VERTEX_COLOR
|
|
||||||
half4 VertexColor : COLOR;
|
|
||||||
#endif
|
|
||||||
float3 WorldNormal : TEXCOORD3;
|
|
||||||
float4 WorldTangent : TEXCOORD4;
|
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
|
||||||
float3 InstanceOrigin : TEXCOORD6;
|
|
||||||
float2 InstanceParams : TEXCOORD7;
|
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
float3 PrevWorldPosition : TEXCOORD8;
|
|
||||||
#endif
|
#endif
|
||||||
float TessellationMultiplier : TESS;
|
float TessellationMultiplier : TESS;
|
||||||
};
|
};
|
||||||
@@ -34,41 +23,19 @@ struct TessalationHSToDS
|
|||||||
// Interpolants passed from the domain shader and to the pixel shader
|
// Interpolants passed from the domain shader and to the pixel shader
|
||||||
struct TessalationDSToPS
|
struct TessalationDSToPS
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
float3 WorldPosition : TEXCOORD0;
|
GeometryData Geometry;
|
||||||
float2 TexCoord : TEXCOORD1;
|
|
||||||
float2 LightmapUV : TEXCOORD2;
|
|
||||||
#if USE_VERTEX_COLOR
|
|
||||||
half4 VertexColor : COLOR;
|
|
||||||
#endif
|
|
||||||
float3 WorldNormal : TEXCOORD3;
|
|
||||||
float4 WorldTangent : TEXCOORD4;
|
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
|
||||||
float3 InstanceOrigin : TEXCOORD6;
|
|
||||||
float2 InstanceParams : TEXCOORD7;
|
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
float3 PrevWorldPosition : TEXCOORD8;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
MaterialInput GetMaterialInput(TessalationDSToPS input)
|
MaterialInput GetMaterialInput(TessalationDSToPS input)
|
||||||
{
|
{
|
||||||
MaterialInput result = (MaterialInput)0;
|
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;
|
result.SvPosition = input.Position;
|
||||||
|
GetGeometryMaterialInput(result, input.Geometry);
|
||||||
|
result.TwoSidedSign = WorldDeterminantSign;
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
result.CustomVSToPS = input.CustomVSToPS;
|
result.CustomVSToPS = input.CustomVSToPS;
|
||||||
#endif
|
#endif
|
||||||
@@ -78,7 +45,7 @@ MaterialInput GetMaterialInput(TessalationDSToPS input)
|
|||||||
struct TessalationPatch
|
struct TessalationPatch
|
||||||
{
|
{
|
||||||
float EdgeTessFactor[3] : SV_TessFactor;
|
float EdgeTessFactor[3] : SV_TessFactor;
|
||||||
float InsideTessFactor : SV_InsideTessFactor;
|
float InsideTessFactor : SV_InsideTessFactor;
|
||||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||||
float3 B210 : POSITION4;
|
float3 B210 : POSITION4;
|
||||||
float3 B120 : POSITION5;
|
float3 B120 : POSITION5;
|
||||||
@@ -110,20 +77,19 @@ TessalationPatch HS_PatchConstant(InputPatch<VertexOutput, 3> input)
|
|||||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||||
// Calculate PN Triangle control points
|
// Calculate PN Triangle control points
|
||||||
// Reference: [Vlachos 2001]
|
// Reference: [Vlachos 2001]
|
||||||
float3 p1 = input[0].WorldPosition;
|
float3 p1 = input[0].Geometry.WorldPosition;
|
||||||
float3 p2 = input[1].WorldPosition;
|
float3 p2 = input[1].Geometry.WorldPosition;
|
||||||
float3 p3 = input[2].WorldPosition;
|
float3 p3 = input[2].Geometry.WorldPosition;
|
||||||
float3 n1 = input[0].WorldNormal;
|
float3 n1 = input[0].Geometry.WorldNormal;
|
||||||
float3 n2 = input[1].WorldNormal;
|
float3 n2 = input[1].Geometry.WorldNormal;
|
||||||
float3 n3 = input[2].WorldNormal;
|
float3 n3 = input[2].Geometry.WorldNormal;
|
||||||
output.B210 = (2.0f * p1 + p2 - dot((p2 - p1), n1) * n1) / 3.0f;
|
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.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.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.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.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;
|
output.B201 = (2.0f * p1 + p3 - dot((p3 - p1), n1) * n1) / 3.0f;
|
||||||
float3 e = (output.B210 + output.B120 + output.B021 +
|
float3 e = (output.B210 + output.B120 + output.B021 + output.B012 + output.B102 + output.B201) / 6.0f;
|
||||||
output.B012 + output.B102 + output.B201) / 6.0f;
|
|
||||||
float3 v = (p1 + p2 + p3) / 3.0f;
|
float3 v = (p1 + p2 + p3) / 3.0f;
|
||||||
output.B111 = e + ((e - v) / 2.0f);
|
output.B111 = e + ((e - v) / 2.0f);
|
||||||
#endif
|
#endif
|
||||||
@@ -132,8 +98,6 @@ TessalationPatch HS_PatchConstant(InputPatch<VertexOutput, 3> input)
|
|||||||
}
|
}
|
||||||
|
|
||||||
META_HS(USE_TESSELLATION, FEATURE_LEVEL_SM5)
|
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)
|
META_HS_PATCH(TESSELLATION_IN_CONTROL_POINTS)
|
||||||
[domain("tri")]
|
[domain("tri")]
|
||||||
[partitioning("fractional_odd")]
|
[partitioning("fractional_odd")]
|
||||||
@@ -148,19 +112,7 @@ TessalationHSToDS HS(InputPatch<VertexOutput, TESSELLATION_IN_CONTROL_POINTS> in
|
|||||||
// Pass through shader
|
// Pass through shader
|
||||||
#define COPY(thing) output.thing = input[ControlPointID].thing;
|
#define COPY(thing) output.thing = input[ControlPointID].thing;
|
||||||
COPY(Position);
|
COPY(Position);
|
||||||
COPY(WorldPosition);
|
COPY(Geometry);
|
||||||
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(TessellationMultiplier);
|
COPY(TessellationMultiplier);
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
COPY(CustomVSToPS);
|
COPY(CustomVSToPS);
|
||||||
@@ -170,19 +122,7 @@ TessalationHSToDS HS(InputPatch<VertexOutput, TESSELLATION_IN_CONTROL_POINTS> in
|
|||||||
return output;
|
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_DS(USE_TESSELLATION, FEATURE_LEVEL_SM5)
|
||||||
META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=0)
|
|
||||||
META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=1)
|
|
||||||
[domain("tri")]
|
[domain("tri")]
|
||||||
TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : SV_DomainLocation, const OutputPatch<TessalationHSToDS, 3> input)
|
TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : SV_DomainLocation, const OutputPatch<TessalationHSToDS, 3> input)
|
||||||
{
|
{
|
||||||
@@ -194,22 +134,18 @@ TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : S
|
|||||||
float W = barycentricCoords.z;
|
float W = barycentricCoords.z;
|
||||||
|
|
||||||
// Interpolate patch attributes to generated vertices
|
// 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 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);
|
INTERPOLATE(Position);
|
||||||
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PN
|
||||||
|
// Interpolate using barycentric coordinates and PN Triangle control points
|
||||||
float UU = U * U;
|
float UU = U * U;
|
||||||
float VV = V * V;
|
float VV = V * V;
|
||||||
float WW = W * W;
|
float WW = W * W;
|
||||||
float UU3 = UU * 3.0f;
|
float UU3 = UU * 3.0f;
|
||||||
float VV3 = VV * 3.0f;
|
float VV3 = VV * 3.0f;
|
||||||
float WW3 = WW * 3.0f;
|
float WW3 = WW * 3.0f;
|
||||||
|
float3 offset =
|
||||||
// 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.B210 * UU3 * V +
|
||||||
constantData.B120 * VV3 * U +
|
constantData.B120 * VV3 * U +
|
||||||
constantData.B021 * VV3 * W +
|
constantData.B021 * VV3 * W +
|
||||||
@@ -217,76 +153,31 @@ TessalationDSToPS DS(TessalationPatch constantData, float3 barycentricCoords : S
|
|||||||
constantData.B102 * WW3 * U +
|
constantData.B102 * WW3 * U +
|
||||||
constantData.B201 * UU3 * W +
|
constantData.B201 * UU3 * W +
|
||||||
constantData.B111 * 6.0f * W * U * V;
|
constantData.B111 * 6.0f * W * U * V;
|
||||||
#if IS_MOTION_VECTORS_PASS
|
InterpolateGeometryPositions(output.Geometry, input[0].Geometry, UU * U, input[1].Geometry, VV * V, input[2].Geometry, WW * W, offset);
|
||||||
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
|
|
||||||
#else
|
#else
|
||||||
INTERPOLATE(WorldPosition);
|
InterpolateGeometryPositions(output.Geometry, input[0].Geometry, U, input[1].Geometry, V, input[2].Geometry, W, float3(0, 0, 0));
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
INTERPOLATE(PrevWorldPosition);
|
|
||||||
#endif
|
#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
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
UNROLL
|
UNROLL
|
||||||
for (int i = 0; i < CUSTOM_VERTEX_INTERPOLATORS_COUNT; i++)
|
for (int i = 0; i < CUSTOM_VERTEX_INTERPOLATORS_COUNT; i++)
|
||||||
{
|
|
||||||
INTERPOLATE(CustomVSToPS[i]);
|
INTERPOLATE(CustomVSToPS[i]);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#undef INTERPOLATE
|
#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
|
#if MATERIAL_TESSELLATION == MATERIAL_TESSELLATION_PHONG
|
||||||
// Orthogonal projection in the tangent planes
|
// Orthogonal projection in the tangent planes with interpolation
|
||||||
float3 posProjectedU = ProjectOntoPlane(input[0].WorldNormal, input[0].WorldPosition, output.WorldPosition);
|
ApplyGeometryPositionsPhongTess(output.Geometry, input[0].Geometry, input[1].Geometry, input[2].Geometry, U, V, W);
|
||||||
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
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Perform displacement mapping
|
// Perform displacement mapping
|
||||||
#if USE_DISPLACEMENT
|
#if USE_DISPLACEMENT
|
||||||
MaterialInput materialInput = GetMaterialInput(output);
|
MaterialInput materialInput = GetMaterialInput(output);
|
||||||
Material material = GetMaterialDS(materialInput);
|
Material material = GetMaterialDS(materialInput);
|
||||||
output.WorldPosition += material.WorldDisplacement;
|
OffsetGeometryPositions(output.Geometry, material.WorldDisplacement);
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
output.PrevWorldPosition += material.WorldDisplacement;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Recalculate the clip space position
|
// Recalculate the clip space position
|
||||||
output.Position = mul(float4(output.WorldPosition, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,9 +199,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Vertex Shader function for GUI materials rendering
|
// Vertex Shader function for GUI materials rendering
|
||||||
META_VS(true, FEATURE_LEVEL_ES2)
|
META_VS(true, FEATURE_LEVEL_ES2)
|
||||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||||
|
|||||||
@@ -332,9 +332,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Calculates the transform matrix from mesh tangent space to local space
|
// Calculates the transform matrix from mesh tangent space to local space
|
||||||
half3x3 CalcTangentToLocal(ModelInput input)
|
half3x3 CalcTangentToLocal(ModelInput input)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -136,9 +136,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Pixel Shader function for PostFx materials rendering
|
// Pixel Shader function for PostFx materials rendering
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
float4 PS_PostFx(PixelInput input) : SV_Target0
|
float4 PS_PostFx(PixelInput input) : SV_Target0
|
||||||
|
|||||||
@@ -32,25 +32,30 @@ float Dummy1;
|
|||||||
|
|
||||||
// Material shader resources
|
// Material shader resources
|
||||||
@2
|
@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
|
// Interpolants passed from the vertex shader
|
||||||
struct VertexOutput
|
struct VertexOutput
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
float3 WorldPosition : TEXCOORD0;
|
GeometryData Geometry;
|
||||||
float2 TexCoord : TEXCOORD1;
|
|
||||||
float2 LightmapUV : TEXCOORD2;
|
|
||||||
#if USE_VERTEX_COLOR
|
|
||||||
half4 VertexColor : COLOR;
|
|
||||||
#endif
|
|
||||||
float3 WorldNormal : TEXCOORD3;
|
|
||||||
float4 WorldTangent : TEXCOORD4;
|
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
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
|
#endif
|
||||||
#if USE_TESSELLATION
|
#if USE_TESSELLATION
|
||||||
float TessellationMultiplier : TESS;
|
float TessellationMultiplier : TESS;
|
||||||
@@ -60,24 +65,12 @@ struct VertexOutput
|
|||||||
// Interpolants passed to the pixel shader
|
// Interpolants passed to the pixel shader
|
||||||
struct PixelInput
|
struct PixelInput
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
float3 WorldPosition : TEXCOORD0;
|
GeometryData Geometry;
|
||||||
float2 TexCoord : TEXCOORD1;
|
|
||||||
float2 LightmapUV : TEXCOORD2;
|
|
||||||
#if USE_VERTEX_COLOR
|
|
||||||
half4 VertexColor : COLOR;
|
|
||||||
#endif
|
|
||||||
float3 WorldNormal : TEXCOORD3;
|
|
||||||
float4 WorldTangent : TEXCOORD4;
|
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
float3 InstanceOrigin : TEXCOORD6;
|
bool IsFrontFace : SV_IsFrontFace;
|
||||||
float2 InstanceParams : TEXCOORD7; // x-PerInstanceRandom, y-LODDitherFactor
|
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
float3 PrevWorldPosition : TEXCOORD8;
|
|
||||||
#endif
|
|
||||||
bool IsFrontFace : SV_IsFrontFace;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Material properties generation input
|
// Material properties generation input
|
||||||
@@ -108,24 +101,75 @@ struct MaterialInput
|
|||||||
#endif
|
#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;
|
result.WorldPosition = geometry.WorldPosition;
|
||||||
return float3x3(tangent.xyz, bitangent, normal);
|
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 GetMaterialInput(ModelInput input, VertexOutput output, float3 localNormal)
|
||||||
{
|
{
|
||||||
MaterialInput result = (MaterialInput)0;
|
MaterialInput result = (MaterialInput)0;
|
||||||
result.WorldPosition = output.WorldPosition;
|
result.WorldPosition = output.Geometry.WorldPosition;
|
||||||
result.TexCoord = output.TexCoord;
|
result.TexCoord = output.Geometry.TexCoord;
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
result.LightmapUV = output.LightmapUV;
|
result.LightmapUV = output.Geometry.LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = output.VertexColor;
|
result.VertexColor = output.Geometry.VertexColor;
|
||||||
#endif
|
#endif
|
||||||
result.TBN = CalcTangentBasis(output.WorldNormal, output.WorldTangent);
|
result.TBN = CalcTangentBasis(output.Geometry.WorldNormal, output.Geometry.WorldTangent);
|
||||||
result.TwoSidedSign = WorldDeterminantSign;
|
result.TwoSidedSign = WorldDeterminantSign;
|
||||||
result.SvPosition = output.Position;
|
result.SvPosition = output.Position;
|
||||||
result.PreSkinnedPosition = input.Position.xyz;
|
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 GetMaterialInput(VertexOutput output, float3 localPosition, float3 localNormal)
|
||||||
{
|
{
|
||||||
MaterialInput result = (MaterialInput)0;
|
MaterialInput result = (MaterialInput)0;
|
||||||
result.WorldPosition = output.WorldPosition;
|
result.WorldPosition = output.Geometry.WorldPosition;
|
||||||
result.TexCoord = output.TexCoord;
|
result.TexCoord = output.Geometry.TexCoord;
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
result.LightmapUV = output.LightmapUV;
|
result.LightmapUV = output.Geometry.LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = output.VertexColor;
|
result.VertexColor = output.Geometry.VertexColor;
|
||||||
#endif
|
#endif
|
||||||
result.TBN = CalcTangentBasis(output.WorldNormal, output.WorldTangent);
|
result.TBN = CalcTangentBasis(output.Geometry.WorldNormal, output.Geometry.WorldTangent);
|
||||||
result.TwoSidedSign = WorldDeterminantSign;
|
result.TwoSidedSign = WorldDeterminantSign;
|
||||||
result.InstanceOrigin = WorldMatrix[3].xyz;
|
result.InstanceOrigin = WorldMatrix[3].xyz;
|
||||||
result.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
result.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||||
@@ -167,18 +211,18 @@ MaterialInput GetMaterialInput(VertexOutput output, float3 localPosition, float3
|
|||||||
MaterialInput GetMaterialInput(PixelInput input)
|
MaterialInput GetMaterialInput(PixelInput input)
|
||||||
{
|
{
|
||||||
MaterialInput result = (MaterialInput)0;
|
MaterialInput result = (MaterialInput)0;
|
||||||
result.WorldPosition = input.WorldPosition;
|
result.WorldPosition = input.Geometry.WorldPosition;
|
||||||
result.TexCoord = input.TexCoord;
|
result.TexCoord = input.Geometry.TexCoord;
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
result.LightmapUV = input.LightmapUV;
|
result.LightmapUV = input.Geometry.LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
result.VertexColor = input.VertexColor;
|
result.VertexColor = input.Geometry.VertexColor;
|
||||||
#endif
|
#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.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||||
result.InstanceOrigin = input.InstanceOrigin;
|
result.InstanceOrigin = input.Geometry.InstanceOrigin;
|
||||||
result.InstanceParams = input.InstanceParams;
|
result.InstanceParams = input.Geometry.InstanceParams;
|
||||||
result.SvPosition = input.Position;
|
result.SvPosition = input.Position;
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
result.CustomVSToPS = input.CustomVSToPS;
|
result.CustomVSToPS = input.CustomVSToPS;
|
||||||
@@ -330,9 +374,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Calculates the transform matrix from mesh tangent space to local space
|
// Calculates the transform matrix from mesh tangent space to local space
|
||||||
float3x3 CalcTangentToLocal(ModelInput input)
|
float3x3 CalcTangentToLocal(ModelInput input)
|
||||||
{
|
{
|
||||||
@@ -353,7 +394,6 @@ float3x3 CalcTangentToWorld(float4x4 world, float3x3 tangentToLocal)
|
|||||||
META_VS(IS_SURFACE, FEATURE_LEVEL_ES2)
|
META_VS(IS_SURFACE, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_1(USE_INSTANCING=0)
|
META_PERMUTATION_1(USE_INSTANCING=0)
|
||||||
META_PERMUTATION_1(USE_INSTANCING=1)
|
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(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(TEXCOORD, 0, R16G16_FLOAT, 1, 0, PER_VERTEX, 0, true)
|
||||||
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 1, ALIGN, 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
|
// Compute world space vertex position
|
||||||
float4x4 world = GetInstanceTransform(input);
|
float4x4 world = GetInstanceTransform(input);
|
||||||
output.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
||||||
#if IS_MOTION_VECTORS_PASS
|
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
|
||||||
output.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Compute clip space position
|
// 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
|
// Pass vertex attributes
|
||||||
output.TexCoord = input.TexCoord;
|
output.Geometry.TexCoord = input.TexCoord;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = input.Color;
|
output.Geometry.VertexColor = input.Color;
|
||||||
#endif
|
#endif
|
||||||
output.InstanceOrigin = world[3].xyz;
|
output.Geometry.InstanceOrigin = world[3].xyz;
|
||||||
#if USE_INSTANCING
|
#if USE_INSTANCING
|
||||||
output.LightmapUV = input.LightmapUV * input.InstanceLightmapArea.zw + input.InstanceLightmapArea.xy;
|
output.Geometry.LightmapUV = input.LightmapUV * input.InstanceLightmapArea.zw + input.InstanceLightmapArea.xy;
|
||||||
output.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
||||||
#else
|
#else
|
||||||
output.LightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy;
|
output.Geometry.LightmapUV = input.LightmapUV * LightmapArea.zw + LightmapArea.xy;
|
||||||
output.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||||
float3x3 tangentToLocal = CalcTangentToLocal(input);
|
float3x3 tangentToLocal = CalcTangentToLocal(input);
|
||||||
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||||
output.WorldNormal = tangentToWorld[2];
|
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||||
output.WorldTangent.xyz = tangentToWorld[0];
|
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||||
output.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||||
|
|
||||||
// Get material input params if need to evaluate any material property
|
// Get material input params if need to evaluate any material property
|
||||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
@@ -408,8 +446,8 @@ VertexOutput VS(ModelInput input)
|
|||||||
|
|
||||||
// Apply world position offset per-vertex
|
// Apply world position offset per-vertex
|
||||||
#if USE_POSITION_OFFSET
|
#if USE_POSITION_OFFSET
|
||||||
output.WorldPosition += material.PositionOffset;
|
output.Geometry.WorldPosition += material.PositionOffset;
|
||||||
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get tessalation multiplier (per vertex)
|
// Get tessalation multiplier (per vertex)
|
||||||
@@ -439,7 +477,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
|
|||||||
{
|
{
|
||||||
float4x4 world = GetInstanceTransform(input);
|
float4x4 world = GetInstanceTransform(input);
|
||||||
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
|
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;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,8 +562,7 @@ float3x3 SkinTangents(ModelInput_Skinned input, SkinningData data)
|
|||||||
// Vertex Shader function for GBuffers/Depth Pass (skinned mesh rendering)
|
// Vertex Shader function for GBuffers/Depth Pass (skinned mesh rendering)
|
||||||
META_VS(IS_SURFACE, FEATURE_LEVEL_ES2)
|
META_VS(IS_SURFACE, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_1(USE_SKINNING=1)
|
META_PERMUTATION_1(USE_SKINNING=1)
|
||||||
META_PERMUTATION_2(USE_SKINNING=1, IS_MOTION_VECTORS_PASS=1)
|
META_PERMUTATION_2(USE_SKINNING=1, PER_BONE_MOTION_BLUR=1)
|
||||||
META_PERMUTATION_3(USE_SKINNING=1, IS_MOTION_VECTORS_PASS=1, PER_BONE_MOTION_BLUR=1)
|
|
||||||
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, 0, PER_VERTEX, 0, true)
|
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(TEXCOORD, 0, R16G16_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
||||||
META_VS_IN_ELEMENT(NORMAL, 0, R10G10B10A2_UNORM, 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
|
// Compute world space vertex position
|
||||||
float4x4 world = GetInstanceTransform(input);
|
float4x4 world = GetInstanceTransform(input);
|
||||||
output.WorldPosition = mul(float4(position, 1), world).xyz;
|
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
#if PER_BONE_MOTION_BLUR
|
#if PER_BONE_MOTION_BLUR
|
||||||
float3 prevPosition = SkinPrevPosition(input);
|
float3 prevPosition = SkinPrevPosition(input);
|
||||||
output.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
|
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
|
||||||
#else
|
#else
|
||||||
output.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
|
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compute clip space position
|
// 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
|
// Pass vertex attributes
|
||||||
output.TexCoord = input.TexCoord;
|
output.Geometry.TexCoord = input.TexCoord;
|
||||||
#if USE_VERTEX_COLOR
|
#if USE_VERTEX_COLOR
|
||||||
output.VertexColor = float4(0, 0, 0, 1);
|
output.Geometry.VertexColor = float4(0, 0, 0, 1);
|
||||||
#endif
|
#endif
|
||||||
output.LightmapUV = float2(0, 0);
|
output.Geometry.LightmapUV = float2(0, 0);
|
||||||
output.InstanceOrigin = world[3].xyz;
|
output.Geometry.InstanceOrigin = world[3].xyz;
|
||||||
#if USE_INSTANCING
|
#if USE_INSTANCING
|
||||||
output.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
output.Geometry.InstanceParams = float2(input.InstanceOrigin.w, input.InstanceTransform1.w);
|
||||||
#else
|
#else
|
||||||
output.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
output.Geometry.InstanceParams = float2(PerInstanceRandom, LODDitherFactor);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate tanget space to world space transformation matrix for unit vectors
|
// Calculate tanget space to world space transformation matrix for unit vectors
|
||||||
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
float3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
|
||||||
output.WorldNormal = tangentToWorld[2];
|
output.Geometry.WorldNormal = tangentToWorld[2];
|
||||||
output.WorldTangent.xyz = tangentToWorld[0];
|
output.Geometry.WorldTangent.xyz = tangentToWorld[0];
|
||||||
output.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
output.Geometry.WorldTangent.w = input.Tangent.w ? -1.0f : +1.0f;
|
||||||
|
|
||||||
// Get material input params if need to evaluate any material property
|
// Get material input params if need to evaluate any material property
|
||||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
#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
|
// Apply world position offset per-vertex
|
||||||
#if USE_POSITION_OFFSET
|
#if USE_POSITION_OFFSET
|
||||||
output.WorldPosition += material.PositionOffset;
|
output.Geometry.WorldPosition += material.PositionOffset;
|
||||||
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get tessalation multiplier (per vertex)
|
// Get tessalation multiplier (per vertex)
|
||||||
@@ -721,10 +756,8 @@ void PS_Depth(PixelInput input
|
|||||||
|
|
||||||
// Pixel Shader function for Motion Vectors Pass
|
// Pixel Shader function for Motion Vectors Pass
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_1(IS_MOTION_VECTORS_PASS=1)
|
|
||||||
float4 PS_MotionVectors(PixelInput input) : SV_Target0
|
float4 PS_MotionVectors(PixelInput input) : SV_Target0
|
||||||
{
|
{
|
||||||
#if IS_MOTION_VECTORS_PASS
|
|
||||||
// LOD masking
|
// LOD masking
|
||||||
ClipLODTransition(input);
|
ClipLODTransition(input);
|
||||||
|
|
||||||
@@ -736,8 +769,8 @@ float4 PS_MotionVectors(PixelInput input) : SV_Target0
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Calculate this and previosu frame pixel locations in clip space
|
// Calculate this and previosu frame pixel locations in clip space
|
||||||
float4 prevClipPos = mul(float4(input.PrevWorldPosition, 1), PrevViewProjectionMatrix);
|
float4 prevClipPos = mul(float4(input.Geometry.PrevWorldPosition, 1), PrevViewProjectionMatrix);
|
||||||
float4 curClipPos = mul(float4(input.WorldPosition, 1), ViewProjectionMatrix);
|
float4 curClipPos = mul(float4(input.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
float2 prevHPos = prevClipPos.xy / prevClipPos.w;
|
float2 prevHPos = prevClipPos.xy / prevClipPos.w;
|
||||||
float2 curHPos = curClipPos.xy / curClipPos.w;
|
float2 curHPos = curClipPos.xy / curClipPos.w;
|
||||||
|
|
||||||
@@ -753,9 +786,6 @@ float4 PS_MotionVectors(PixelInput input) : SV_Target0
|
|||||||
|
|
||||||
// Calculate per-pixel motion vector
|
// Calculate per-pixel motion vector
|
||||||
return float4(vPosCur - vPosPrev, 0, 1);
|
return float4(vPosCur - vPosPrev, 0, 1);
|
||||||
#else
|
|
||||||
return float4(0, 0, 0, 1);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@9
|
@9
|
||||||
|
|||||||
@@ -338,9 +338,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Calculates the transform matrix from mesh tangent space to local space
|
// Calculates the transform matrix from mesh tangent space to local space
|
||||||
half3x3 CalcTangentToLocal(ModelInput input)
|
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)
|
// The skeletal bones matrix buffer (stored as 4x3, 3 float4 behind each other)
|
||||||
Buffer<float4> BoneMatrices : register(t0);
|
Buffer<float4> BoneMatrices : register(t0);
|
||||||
|
|
||||||
#if PER_BONE_MOTION_BLUR
|
|
||||||
|
|
||||||
// The skeletal bones matrix buffer from the previous frame
|
|
||||||
Buffer<float4> 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
|
// Cached skinning data to avoid multiple calculation
|
||||||
struct SkinningData
|
struct SkinningData
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#define MATERIAL 1
|
#define MATERIAL 1
|
||||||
@3
|
@3
|
||||||
|
|
||||||
// Enables/disables smooth terrain chunks LOD transitions (with morphing higher LOD near edges to the lower LOD in the neighbour)
|
// 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
|
#define USE_SMOOTH_LOD_TRANSITION 1
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@ float3 ViewDir;
|
|||||||
float TimeParam;
|
float TimeParam;
|
||||||
float4 ViewInfo;
|
float4 ViewInfo;
|
||||||
float4 ScreenSize;
|
float4 ScreenSize;
|
||||||
float4 LightmapArea;
|
|
||||||
float3 WorldInvScale;
|
float3 WorldInvScale;
|
||||||
float WorldDeterminantSign;
|
float WorldDeterminantSign;
|
||||||
float PerInstanceRandom;
|
float PerInstanceRandom;
|
||||||
@@ -39,31 +37,32 @@ float2 OffsetUV;
|
|||||||
float2 Dummy0;
|
float2 Dummy0;
|
||||||
@1META_CB_END
|
@1META_CB_END
|
||||||
|
|
||||||
// Irradiance and directionality prebaked lightmaps
|
|
||||||
Texture2D Lightmap0 : register(t0);
|
|
||||||
Texture2D Lightmap1 : register(t1);
|
|
||||||
Texture2D Lightmap2 : register(t2);
|
|
||||||
|
|
||||||
// Terrain data
|
// Terrain data
|
||||||
Texture2D Heightmap : register(t3);
|
Texture2D Heightmap : register(t0);
|
||||||
Texture2D Splatmap0 : register(t4);
|
Texture2D Splatmap0 : register(t1);
|
||||||
Texture2D Splatmap1 : register(t5);
|
Texture2D Splatmap1 : register(t2);
|
||||||
|
|
||||||
// Material shader resources
|
// Material shader resources
|
||||||
@2
|
@2
|
||||||
|
|
||||||
// Interpolants passed from the vertex shader
|
// Geometry data passed though the graphics rendering stages up to the pixel shader
|
||||||
struct VertexOutput
|
struct GeometryData
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float3 WorldPosition : TEXCOORD0;
|
||||||
float3 WorldPosition : TEXCOORD0;
|
float2 TexCoord : TEXCOORD1;
|
||||||
float2 TexCoord : TEXCOORD1;
|
float2 LightmapUV : TEXCOORD2;
|
||||||
float2 LightmapUV : TEXCOORD2;
|
float3 WorldNormal : TEXCOORD3;
|
||||||
float3 WorldNormal : TEXCOORD3;
|
float HolesMask : TEXCOORD4;
|
||||||
float HolesMask : TEXCOORD4;
|
|
||||||
#if USE_TERRAIN_LAYERS
|
#if USE_TERRAIN_LAYERS
|
||||||
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
float4 Layers[TERRAIN_LAYERS_DATA_SIZE] : TEXCOORD5;
|
||||||
#endif
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interpolants passed from the vertex shader
|
||||||
|
struct VertexOutput
|
||||||
|
{
|
||||||
|
float4 Position : SV_Position;
|
||||||
|
GeometryData Geometry;
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
@@ -75,19 +74,12 @@ struct VertexOutput
|
|||||||
// Interpolants passed to the pixel shader
|
// Interpolants passed to the pixel shader
|
||||||
struct PixelInput
|
struct PixelInput
|
||||||
{
|
{
|
||||||
float4 Position : SV_Position;
|
float4 Position : SV_Position;
|
||||||
float3 WorldPosition : TEXCOORD0;
|
GeometryData Geometry;
|
||||||
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
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
float4 CustomVSToPS[CUSTOM_VERTEX_INTERPOLATORS_COUNT] : TEXCOORD9;
|
||||||
#endif
|
#endif
|
||||||
bool IsFrontFace : SV_IsFrontFace;
|
bool IsFrontFace : SV_IsFrontFace;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Material properties generation input
|
// Material properties generation input
|
||||||
@@ -112,20 +104,69 @@ struct MaterialInput
|
|||||||
#endif
|
#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 GetMaterialInput(PixelInput input)
|
||||||
{
|
{
|
||||||
MaterialInput result = (MaterialInput)0;
|
MaterialInput result = (MaterialInput)0;
|
||||||
result.WorldPosition = input.WorldPosition;
|
result.WorldPosition = input.Geometry.WorldPosition;
|
||||||
result.TexCoord = input.TexCoord;
|
result.TexCoord = input.Geometry.TexCoord;
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
result.LightmapUV = input.LightmapUV;
|
result.LightmapUV = input.Geometry.LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
result.TBN = CalcTangentBasisFromWorldNormal(input.WorldNormal);
|
result.TBN = CalcTangentBasisFromWorldNormal(input.Geometry.WorldNormal);
|
||||||
result.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
result.TwoSidedSign = WorldDeterminantSign * (input.IsFrontFace ? 1.0 : -1.0);
|
||||||
result.SvPosition = input.Position;
|
result.SvPosition = input.Position;
|
||||||
result.HolesMask = input.HolesMask;
|
result.HolesMask = input.Geometry.HolesMask;
|
||||||
#if USE_TERRAIN_LAYERS
|
#if USE_TERRAIN_LAYERS
|
||||||
result.Layers = input.Layers;
|
result.Layers = input.Geometry.Layers;
|
||||||
#endif
|
#endif
|
||||||
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
result.CustomVSToPS = input.CustomVSToPS;
|
result.CustomVSToPS = input.CustomVSToPS;
|
||||||
@@ -212,20 +253,6 @@ float4 GetVertexColor(MaterialInput input)
|
|||||||
return 1;
|
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
|
@8
|
||||||
|
|
||||||
// Get material properties function (for vertex shader)
|
// Get material properties function (for vertex shader)
|
||||||
@@ -246,9 +273,6 @@ Material GetMaterialPS(MaterialInput input)
|
|||||||
@4
|
@4
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix line for errors/warnings for shader code from template
|
|
||||||
#line 1000
|
|
||||||
|
|
||||||
// Calculates LOD value (with fractional part for blending)
|
// Calculates LOD value (with fractional part for blending)
|
||||||
float CalcLOD(float2 xy, float4 morph)
|
float CalcLOD(float2 xy, float4 morph)
|
||||||
{
|
{
|
||||||
@@ -297,7 +321,7 @@ float3x3 CalcTangentToWorld(float4x4 world, float3x3 tangentToLocal)
|
|||||||
struct TerrainVertexInput
|
struct TerrainVertexInput
|
||||||
{
|
{
|
||||||
float2 TexCoord : TEXCOORD0;
|
float2 TexCoord : TEXCOORD0;
|
||||||
float4 Morph : TEXCOORD1;
|
float4 Morph : TEXCOORD1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vertex Shader function for terrain rendering
|
// 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;
|
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);
|
float3 normal = float3(normalTemp.x, sqrt(1.0 - saturate(dot(normalTemp, normalTemp))), normalTemp.y);
|
||||||
normal = normalize(normal);
|
normal = normalize(normal);
|
||||||
output.HolesMask = isHole ? 0 : 1;
|
output.Geometry.HolesMask = isHole ? 0 : 1;
|
||||||
if (isHole)
|
if (isHole)
|
||||||
{
|
{
|
||||||
normal = float3(0, 1, 0);
|
normal = float3(0, 1, 0);
|
||||||
@@ -365,10 +389,10 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
float3 position = float3(positionXZ.x, height, positionXZ.y);
|
float3 position = float3(positionXZ.x, height, positionXZ.y);
|
||||||
|
|
||||||
// Compute world space vertex position
|
// 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
|
// 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
|
// Pass vertex attributes
|
||||||
#if USE_SMOOTH_LOD_TRANSITION
|
#if USE_SMOOTH_LOD_TRANSITION
|
||||||
@@ -376,46 +400,46 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
#else
|
#else
|
||||||
float2 texCoord = input.TexCoord;
|
float2 texCoord = input.TexCoord;
|
||||||
#endif
|
#endif
|
||||||
output.TexCoord = positionXZ * (1.0f / TerrainChunkSizeLOD0) + OffsetUV;
|
output.Geometry.TexCoord = positionXZ * (1.0f / TerrainChunkSizeLOD0) + OffsetUV;
|
||||||
output.LightmapUV = texCoord * LightmapArea.zw + LightmapArea.xy;
|
output.Geometry.LightmapUV = texCoord * LightmapArea.zw + LightmapArea.xy;
|
||||||
|
|
||||||
// Extract terrain layers weights from the splatmap
|
// Extract terrain layers weights from the splatmap
|
||||||
#if USE_TERRAIN_LAYERS
|
#if USE_TERRAIN_LAYERS
|
||||||
output.Layers[0] = splatmap0Value;
|
output.Geometry.Layers[0] = splatmap0Value;
|
||||||
#if TERRAIN_LAYERS_DATA_SIZE > 1
|
#if TERRAIN_LAYERS_DATA_SIZE > 1
|
||||||
output.Layers[1] = splatmap1Value;
|
output.Geometry.Layers[1] = splatmap1Value;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compute world space normal vector
|
// Compute world space normal vector
|
||||||
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
|
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
|
||||||
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
|
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
|
// Get material input params if need to evaluate any material property
|
||||||
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
#if USE_POSITION_OFFSET || USE_TESSELLATION || USE_CUSTOM_VERTEX_INTERPOLATORS
|
||||||
MaterialInput materialInput = (MaterialInput)0;
|
MaterialInput materialInput = (MaterialInput)0;
|
||||||
materialInput.WorldPosition = output.WorldPosition;
|
materialInput.WorldPosition = output.Geometry.WorldPosition;
|
||||||
materialInput.TexCoord = output.TexCoord;
|
materialInput.TexCoord = output.Geometry.TexCoord;
|
||||||
#if USE_LIGHTMAP
|
#if USE_LIGHTMAP
|
||||||
materialInput.LightmapUV = output.LightmapUV;
|
materialInput.LightmapUV = output.Geometry.LightmapUV;
|
||||||
#endif
|
#endif
|
||||||
materialInput.TBN = CalcTangentBasisFromWorldNormal(output.WorldNormal);
|
materialInput.TBN = CalcTangentBasisFromWorldNormal(output.Geometry.WorldNormal);
|
||||||
materialInput.TwoSidedSign = WorldDeterminantSign;
|
materialInput.TwoSidedSign = WorldDeterminantSign;
|
||||||
materialInput.SvPosition = output.Position;
|
materialInput.SvPosition = output.Position;
|
||||||
materialInput.PreSkinnedPosition = position;
|
materialInput.PreSkinnedPosition = position;
|
||||||
materialInput.PreSkinnedNormal = normal;
|
materialInput.PreSkinnedNormal = normal;
|
||||||
materialInput.HolesMask = output.HolesMask;
|
materialInput.HolesMask = output.Geometry.HolesMask;
|
||||||
#if USE_TERRAIN_LAYERS
|
#if USE_TERRAIN_LAYERS
|
||||||
materialInput.Layers = output.Layers;
|
materialInput.Layers = output.Geometry.Layers;
|
||||||
#endif
|
#endif
|
||||||
Material material = GetMaterialVS(materialInput);
|
Material material = GetMaterialVS(materialInput);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Apply world position offset per-vertex
|
// Apply world position offset per-vertex
|
||||||
#if USE_POSITION_OFFSET
|
#if USE_POSITION_OFFSET
|
||||||
output.WorldPosition += material.PositionOffset;
|
output.Geometry.WorldPosition += material.PositionOffset;
|
||||||
output.Position = mul(float4(output.WorldPosition.xyz, 1), ViewProjectionMatrix);
|
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get tessalation multiplier (per vertex)
|
// Get tessalation multiplier (per vertex)
|
||||||
@@ -431,277 +455,6 @@ VertexOutput VS(TerrainVertexInput input)
|
|||||||
return output;
|
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<VertexOutput, 3> 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<VertexOutput, TESSELLATION_IN_CONTROL_POINTS> 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<TessalationHSToDS, 3> 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
|
// Pixel Shader function for GBuffer Pass
|
||||||
META_PS(true, FEATURE_LEVEL_ES2)
|
META_PS(true, FEATURE_LEVEL_ES2)
|
||||||
META_PERMUTATION_1(USE_LIGHTMAP=0)
|
META_PERMUTATION_1(USE_LIGHTMAP=0)
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ bool DeferredMaterialShader::Load()
|
|||||||
psDesc.VS = _shader->GetVS("VS", 1);
|
psDesc.VS = _shader->GetVS("VS", 1);
|
||||||
_cacheInstanced.Default.Init(psDesc);
|
_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.VS = _shader->GetVS("VS");
|
||||||
psDesc.PS = _shader->GetPS("PS_GBuffer", 1);
|
psDesc.PS = _shader->GetPS("PS_GBuffer", 1);
|
||||||
_cache.DefaultLightmap.Init(psDesc);
|
_cache.DefaultLightmap.Init(psDesc);
|
||||||
@@ -210,21 +210,16 @@ bool DeferredMaterialShader::Load()
|
|||||||
psDesc.DepthWriteEnable = false;
|
psDesc.DepthWriteEnable = false;
|
||||||
psDesc.DepthTestEnable = true;
|
psDesc.DepthTestEnable = true;
|
||||||
psDesc.DepthFunc = ComparisonFunc::LessEqual;
|
psDesc.DepthFunc = ComparisonFunc::LessEqual;
|
||||||
if (useTess)
|
psDesc.VS = _shader->GetVS("VS");
|
||||||
{
|
|
||||||
psDesc.HS = _shader->GetHS("HS", 1);
|
|
||||||
psDesc.DS = _shader->GetDS("DS", 1);
|
|
||||||
}
|
|
||||||
psDesc.VS = _shader->GetVS("VS", 2);
|
|
||||||
psDesc.PS = _shader->GetPS("PS_MotionVectors");
|
psDesc.PS = _shader->GetPS("PS_MotionVectors");
|
||||||
_cache.MotionVectors.Init(psDesc);
|
_cache.MotionVectors.Init(psDesc);
|
||||||
|
|
||||||
// Motion Vectors pass with skinning
|
// Motion Vectors pass with skinning
|
||||||
psDesc.VS = _shader->GetVS("VS_Skinned", 1);
|
psDesc.VS = _shader->GetVS("VS_Skinned");
|
||||||
_cache.MotionVectorsSkinned.Init(psDesc);
|
_cache.MotionVectorsSkinned.Init(psDesc);
|
||||||
|
|
||||||
// Motion Vectors pass with skinning (with per-bone motion blur)
|
// 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);
|
_cache.MotionVectorsSkinnedPerBone.Init(psDesc);
|
||||||
|
|
||||||
// Depth Pass
|
// Depth Pass
|
||||||
|
|||||||
@@ -139,13 +139,13 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, byte*& cb, in
|
|||||||
{
|
{
|
||||||
// Bind lightmap textures
|
// Bind lightmap textures
|
||||||
GPUTexture *lightmap0, *lightmap1, *lightmap2;
|
GPUTexture *lightmap0, *lightmap1, *lightmap2;
|
||||||
drawCall.Surface.Lightmap->GetTextures(&lightmap0, &lightmap1, &lightmap2);
|
drawCall.Features.Lightmap->GetTextures(&lightmap0, &lightmap1, &lightmap2);
|
||||||
context->BindSR(0, lightmap0);
|
context->BindSR(srv + 0, lightmap0);
|
||||||
context->BindSR(1, lightmap1);
|
context->BindSR(srv + 1, lightmap1);
|
||||||
context->BindSR(2, lightmap2);
|
context->BindSR(srv + 2, lightmap2);
|
||||||
|
|
||||||
// Set lightmap data
|
// Set lightmap data
|
||||||
data.LightmapArea = drawCall.Surface.LightmapUVsArea;
|
data.LightmapArea = drawCall.Features.LightmapUVsArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
srv += SRVs;
|
srv += SRVs;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "TerrainMaterialShader.h"
|
#include "TerrainMaterialShader.h"
|
||||||
|
#include "MaterialShaderFeatures.h"
|
||||||
#include "MaterialParams.h"
|
#include "MaterialParams.h"
|
||||||
#include "Engine/Engine/Time.h"
|
#include "Engine/Engine/Time.h"
|
||||||
#include "Engine/Graphics/GPUContext.h"
|
#include "Engine/Graphics/GPUContext.h"
|
||||||
@@ -25,7 +26,6 @@ PACK_STRUCT(struct TerrainMaterialShaderData {
|
|||||||
float TimeParam;
|
float TimeParam;
|
||||||
Vector4 ViewInfo;
|
Vector4 ViewInfo;
|
||||||
Vector4 ScreenSize;
|
Vector4 ScreenSize;
|
||||||
Rectangle LightmapArea;
|
|
||||||
Vector3 WorldInvScale;
|
Vector3 WorldInvScale;
|
||||||
float WorldDeterminantSign;
|
float WorldDeterminantSign;
|
||||||
float PerInstanceRandom;
|
float PerInstanceRandom;
|
||||||
@@ -56,11 +56,21 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
|||||||
auto& drawCall = *params.FirstDrawCall;
|
auto& drawCall = *params.FirstDrawCall;
|
||||||
const auto cb0 = _shader->GetCB(0);
|
const auto cb0 = _shader->GetCB(0);
|
||||||
const bool hasCb0 = cb0->GetSize() != 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<TerrainMaterialShaderData*>(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
|
// Setup parameters
|
||||||
MaterialParameter::BindMeta bindMeta;
|
MaterialParameter::BindMeta bindMeta;
|
||||||
bindMeta.Context = context;
|
bindMeta.Context = context;
|
||||||
bindMeta.Constants = hasCb0 ? _cb0Data.Get() + sizeof(TerrainMaterialShaderData) : nullptr;
|
bindMeta.Constants = cb;
|
||||||
bindMeta.Input = nullptr;
|
bindMeta.Input = nullptr;
|
||||||
bindMeta.Buffers = nullptr;
|
bindMeta.Buffers = nullptr;
|
||||||
bindMeta.CanSampleDepth = false;
|
bindMeta.CanSampleDepth = false;
|
||||||
@@ -68,64 +78,42 @@ void TerrainMaterialShader::Bind(BindParameters& params)
|
|||||||
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
MaterialParams::Bind(params.ParamsLink, bindMeta);
|
||||||
|
|
||||||
// Setup material constants data
|
// Setup material constants data
|
||||||
auto data = reinterpret_cast<TerrainMaterialShaderData*>(_cb0Data.Get());
|
|
||||||
if (hasCb0)
|
if (hasCb0)
|
||||||
{
|
{
|
||||||
Matrix::Transpose(view.Frustum.GetMatrix(), data->ViewProjectionMatrix);
|
Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix);
|
||||||
Matrix::Transpose(drawCall.World, data->WorldMatrix);
|
Matrix::Transpose(drawCall.World, materialData->WorldMatrix);
|
||||||
Matrix::Transpose(view.View, data->ViewMatrix);
|
Matrix::Transpose(view.View, materialData->ViewMatrix);
|
||||||
|
|
||||||
data->ViewPos = view.Position;
|
materialData->ViewPos = view.Position;
|
||||||
data->ViewFar = view.Far;
|
materialData->ViewFar = view.Far;
|
||||||
data->ViewDir = view.Direction;
|
materialData->ViewDir = view.Direction;
|
||||||
data->TimeParam = Time::Draw.UnscaledTime.GetTotalSeconds();
|
materialData->TimeParam = Time::Draw.UnscaledTime.GetTotalSeconds();
|
||||||
data->ViewInfo = view.ViewInfo;
|
materialData->ViewInfo = view.ViewInfo;
|
||||||
data->ScreenSize = view.ScreenSize;
|
materialData->ScreenSize = view.ScreenSize;
|
||||||
|
|
||||||
// Extract per axis scales from LocalToWorld transform
|
|
||||||
const float scaleX = Vector3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
|
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 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();
|
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,
|
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
|
||||||
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
|
||||||
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
|
||||||
|
materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign;
|
||||||
data->WorldDeterminantSign = drawCall.WorldDeterminantSign;
|
materialData->PerInstanceRandom = drawCall.PerInstanceRandom;
|
||||||
data->PerInstanceRandom = drawCall.PerInstanceRandom;
|
materialData->CurrentLOD = drawCall.Terrain.CurrentLOD;
|
||||||
data->CurrentLOD = drawCall.Terrain.CurrentLOD;
|
materialData->ChunkSizeNextLOD = drawCall.Terrain.ChunkSizeNextLOD;
|
||||||
data->ChunkSizeNextLOD = drawCall.Terrain.ChunkSizeNextLOD;
|
materialData->TerrainChunkSizeLOD0 = drawCall.Terrain.TerrainChunkSizeLOD0;
|
||||||
data->TerrainChunkSizeLOD0 = drawCall.Terrain.TerrainChunkSizeLOD0;
|
materialData->HeightmapUVScaleBias = drawCall.Terrain.HeightmapUVScaleBias;
|
||||||
data->HeightmapUVScaleBias = drawCall.Terrain.HeightmapUVScaleBias;
|
materialData->NeighborLOD = drawCall.Terrain.NeighborLOD;
|
||||||
data->NeighborLOD = drawCall.Terrain.NeighborLOD;
|
materialData->OffsetUV = drawCall.Terrain.OffsetUV;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind terrain textures
|
// 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 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;
|
const auto splatmap1 = drawCall.Terrain.Patch->Splatmap[1] ? drawCall.Terrain.Patch->Splatmap[1]->GetTexture() : nullptr;
|
||||||
context->BindSR(3, heightmap);
|
context->BindSR(0, heightmap);
|
||||||
context->BindSR(4, splatmap0);
|
context->BindSR(1, splatmap0);
|
||||||
context->BindSR(5, splatmap1);
|
context->BindSR(2, splatmap1);
|
||||||
|
|
||||||
// Bind constants
|
// Bind constants
|
||||||
if (hasCb0)
|
if (hasCb0)
|
||||||
|
|||||||
@@ -167,8 +167,14 @@ struct DrawCall
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
const Lightmap* Lightmap;
|
const Lightmap* Lightmap;
|
||||||
SkinnedMeshDrawData* Skinning;
|
|
||||||
Rectangle LightmapUVsArea;
|
Rectangle LightmapUVsArea;
|
||||||
|
} Features;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const Lightmap* Lightmap;
|
||||||
|
Rectangle LightmapUVsArea;
|
||||||
|
SkinnedMeshDrawData* Skinning;
|
||||||
Vector3 GeometrySize; // Object geometry size in the world (unscaled).
|
Vector3 GeometrySize; // Object geometry size in the world (unscaled).
|
||||||
float LODDitherFactor; // The model LOD transition dither progress.
|
float LODDitherFactor; // The model LOD transition dither progress.
|
||||||
Matrix PrevWorld;
|
Matrix PrevWorld;
|
||||||
@@ -176,15 +182,15 @@ struct DrawCall
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
const Lightmap* Lightmap;
|
||||||
|
Rectangle LightmapUVsArea;
|
||||||
Vector4 HeightmapUVScaleBias;
|
Vector4 HeightmapUVScaleBias;
|
||||||
Vector4 NeighborLOD;
|
Vector4 NeighborLOD;
|
||||||
Vector2 OffsetUV;
|
Vector2 OffsetUV;
|
||||||
float CurrentLOD;
|
float CurrentLOD;
|
||||||
float ChunkSizeNextLOD;
|
float ChunkSizeNextLOD;
|
||||||
float TerrainChunkSizeLOD0;
|
float TerrainChunkSizeLOD0;
|
||||||
Rectangle LightmapUVsArea;
|
|
||||||
const class TerrainPatch* Patch;
|
const class TerrainPatch* Patch;
|
||||||
const Lightmap* Lightmap;
|
|
||||||
} Terrain;
|
} Terrain;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
|||||||
@@ -187,6 +187,11 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
|
if (materialInfo.BlendMode == MaterialBlendMode::Opaque)
|
||||||
ADD_FEATURE(LightmapFeature);
|
ADD_FEATURE(LightmapFeature);
|
||||||
break;
|
break;
|
||||||
|
case MaterialDomain::Terrain:
|
||||||
|
if (materialInfo.TessellationMode != TessellationMethod::None)
|
||||||
|
ADD_FEATURE(TessellationFeature);
|
||||||
|
ADD_FEATURE(LightmapFeature);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -387,7 +392,7 @@ bool MaterialGenerator::Generate(WriteStream& source, MaterialInfo& materialInfo
|
|||||||
srv = 1;
|
srv = 1;
|
||||||
break;
|
break;
|
||||||
case MaterialDomain::Terrain:
|
case MaterialDomain::Terrain:
|
||||||
srv = 6;
|
srv = 3; // Heightmap + 2 splatmaps
|
||||||
break;
|
break;
|
||||||
case MaterialDomain::Particle:
|
case MaterialDomain::Particle:
|
||||||
srv = 5;
|
srv = 5;
|
||||||
|
|||||||
@@ -61,9 +61,6 @@
|
|||||||
#ifndef MAX_TESSELLATION_FACTOR
|
#ifndef MAX_TESSELLATION_FACTOR
|
||||||
#define MAX_TESSELLATION_FACTOR 15
|
#define MAX_TESSELLATION_FACTOR 15
|
||||||
#endif
|
#endif
|
||||||
#ifndef IS_MOTION_VECTORS_PASS
|
|
||||||
#define IS_MOTION_VECTORS_PASS 0
|
|
||||||
#endif
|
|
||||||
#ifndef PER_BONE_MOTION_BLUR
|
#ifndef PER_BONE_MOTION_BLUR
|
||||||
#define PER_BONE_MOTION_BLUR 0
|
#define PER_BONE_MOTION_BLUR 0
|
||||||
#endif
|
#endif
|
||||||
@@ -164,6 +161,12 @@ float3x3 CalcTangentBasisFromWorldNormal(float3 normal)
|
|||||||
return float3x3(tangent, bitangent, 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"]
|
// [Jimenez et al. 2016, "Practical Realtime Strategies for Accurate Indirect Occlusion"]
|
||||||
float3 AOMultiBounce(float visibility, float3 albedo)
|
float3 AOMultiBounce(float visibility, float3 albedo)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user