168 lines
4.7 KiB
HLSL
168 lines
4.7 KiB
HLSL
|
|
//Stylized Water 2
|
|
//Staggart Creations (http://staggart.xyz)
|
|
//Copyright protected under Unity Asset Store EULA
|
|
|
|
#if defined(SHADER_API_XBOXONE) || defined(SHADER_API_PSSL)
|
|
// AMD recommends this value for GCN http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/05/GCNPerformanceTweets.pdf
|
|
#define MAX_TESSELLATION_FACTORS 15.0
|
|
#else
|
|
#define MAX_TESSELLATION_FACTORS 64.0
|
|
#endif
|
|
|
|
#if defined(SHADER_API_GLES2)
|
|
#warning Current graphics API does not support tessellation, falling back to non-tessellated shader automatically.
|
|
#else
|
|
#define UNITY_CAN_COMPILE_TESSELLATION
|
|
#endif
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float4 normalOS : NORMAL;
|
|
float4 tangentOS : TANGENT;
|
|
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
half4 fogFactorAndVertexLight : TEXCOORD1; // x: fogFactor, yzw: vertex light
|
|
|
|
//wPos.x in w-component
|
|
float4 normalWS : NORMAL;
|
|
//wPos.y in w-component
|
|
float4 tangent : TANGENT;
|
|
//wPos.z in w-component
|
|
float4 bitangent : TEXCOORD4;
|
|
|
|
float4 positionNDC : TEXCOORD5;
|
|
|
|
float4 positionCS : SV_POSITION;
|
|
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct TessellationFactors
|
|
{
|
|
float edge[3] : SV_TessFactor;
|
|
float inside : SV_InsideTessFactor;
|
|
};
|
|
|
|
struct VertexControl
|
|
{
|
|
float4 positionOS : INTERNALTESSPOS;
|
|
float4 normalOS : NORMAL;
|
|
float4 tangentOS : TANGENT;
|
|
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
VertexControl VertexTessellation(Attributes input)
|
|
{
|
|
VertexControl output;
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_TRANSFER_INSTANCE_ID(input, output);
|
|
|
|
output.positionOS = input.positionOS;
|
|
output.normalOS = input.normalOS;
|
|
output.tangentOS = input.tangentOS;
|
|
|
|
return output;
|
|
}
|
|
|
|
float CalcDistanceTessFactor(float4 positionOS, float minDist, float maxDist, float tess)
|
|
{
|
|
float3 positionWS = TransformObjectToWorld(positionOS.xyz).xyz;
|
|
float dist = distance(positionWS, GetCurrentViewPosition());
|
|
float f = (1.0-saturate((dist - minDist) / (maxDist - minDist)) + 0.001) * tess;
|
|
|
|
return f;
|
|
}
|
|
|
|
float4 CalcTriEdgeTessFactors (float3 triVertexFactors)
|
|
{
|
|
float4 tess;
|
|
tess.x = 0.5 * (triVertexFactors.y + triVertexFactors.z);
|
|
tess.y = 0.5 * (triVertexFactors.x + triVertexFactors.z);
|
|
tess.z = 0.5 * (triVertexFactors.x + triVertexFactors.y);
|
|
tess.w = (triVertexFactors.x + triVertexFactors.y + triVertexFactors.z) / 3.0f;
|
|
return tess;
|
|
}
|
|
|
|
float4 DistanceBasedTess(float4 v0, float4 v1, float4 v2, float tess, float minDist, float maxDist)
|
|
{
|
|
float3 f;
|
|
f.x = CalcDistanceTessFactor(v0, minDist, maxDist, tess);
|
|
f.y = CalcDistanceTessFactor(v1, minDist, maxDist, tess);
|
|
f.z = CalcDistanceTessFactor(v2, minDist, maxDist, tess);
|
|
|
|
//Don't use the Core RP version, creates cracks on edges
|
|
return CalcTriEdgeTessFactors(f);
|
|
}
|
|
|
|
TessellationFactors HullConstant(InputPatch<VertexControl, 3> patch)
|
|
{
|
|
TessellationFactors output;
|
|
|
|
float4 tf = DistanceBasedTess(patch[0].positionOS, patch[1].positionOS, patch[2].positionOS, _TessValue, _TessMin, _TessMax);
|
|
|
|
UNITY_SETUP_INSTANCE_ID(patch[0]);
|
|
|
|
output.edge[0] = tf.x;
|
|
output.edge[1] = tf.y;
|
|
output.edge[2] = tf.z;
|
|
output.inside = tf.w;
|
|
|
|
return output;
|
|
}
|
|
|
|
[maxtessfactor(MAX_TESSELLATION_FACTORS)]
|
|
[domain("tri")]
|
|
[partitioning("fractional_odd")]
|
|
[outputtopology("triangle_cw")]
|
|
[patchconstantfunc("HullConstant")]
|
|
[outputcontrolpoints(3)]
|
|
VertexControl Hull(InputPatch<VertexControl, 3> input, uint id : SV_OutputControlPointID)
|
|
{
|
|
return input[id];
|
|
}
|
|
|
|
#define TESSELLATION_INTERPOLATE_BARY_URP(name, bary) IN.name = input[0].name * bary.x + input[1].name * bary.y + input[2].name * bary.z
|
|
|
|
[domain("tri")]
|
|
Varyings Domain(TessellationFactors factors, OutputPatch<VertexControl, 3> input, float3 baryCoords : SV_DomainLocation)
|
|
{
|
|
Attributes IN = (Attributes)0;
|
|
Varyings output = (Varyings)0;
|
|
|
|
TESSELLATION_INTERPOLATE_BARY_URP(positionOS, baryCoords);
|
|
TESSELLATION_INTERPOLATE_BARY_URP(normalOS, baryCoords);
|
|
TESSELLATION_INTERPOLATE_BARY_URP(tangentOS, baryCoords);
|
|
|
|
//Tessellation does not work entirely correct with GPU instancing
|
|
UNITY_TRANSFER_INSTANCE_ID(input[0], output);
|
|
|
|
VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normalOS.xyz, IN.tangentOS);
|
|
float3 positionWS = TransformObjectToWorld(IN.positionOS.xyz);
|
|
|
|
WaveInfo waves = GetWaveInfo(positionWS.xz, TIME_VERTEX * _WaveSpeed, _WaveHeight, 1, _WaveFadeDistance.x, _WaveFadeDistance.y);
|
|
|
|
positionWS += waves.position;
|
|
|
|
float4 positionCS = TransformWorldToHClip(positionWS);
|
|
|
|
output.positionCS = positionCS;
|
|
|
|
float4 ndc = positionCS * 0.5f;
|
|
ndc.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
|
|
ndc.zw = positionCS.zw;
|
|
output.positionNDC = ndc;
|
|
|
|
output.normalWS = float4(waves.normal, positionWS.x);
|
|
output.tangent = float4(normalInput.tangentWS, positionWS.y);
|
|
output.bitangent = float4(normalInput.bitangentWS, positionWS.z);
|
|
|
|
return output;
|
|
}
|