148 lines
5.9 KiB
HLSL

#ifndef LIL_TESSELLATION_INCLUDED
#define LIL_TESSELLATION_INCLUDED
//------------------------------------------------------------------------------------------------------------------------------
// Tessellation
//------------------------------------------------------------------------------------------------------------------------------
// Structure
struct lilTessellationFactors {
float edge[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
//------------------------------------------------------------------------------------------------------------------------------
// Vertex Shader
appdata vertTess(appdata input)
{
return input;
}
//------------------------------------------------------------------------------------------------------------------------------
// Hull Shader
[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[patchconstantfunc("hullConst")]
[outputcontrolpoints(3)]
appdata hull(InputPatch<appdata, 3> input, uint id : SV_OutputControlPointID)
{
return input[id];
}
lilTessellationFactors hullConst(InputPatch<appdata, 3> input)
{
lilTessellationFactors output;
LIL_INITIALIZE_STRUCT(lilTessellationFactors, output);
LIL_SETUP_INSTANCE_ID(input[0]);
if(_Invisible) return output;
LIL_VERTEX_POSITION_INPUTS(input[0].positionOS, vertexInput_0);
LIL_VERTEX_POSITION_INPUTS(input[1].positionOS, vertexInput_1);
LIL_VERTEX_POSITION_INPUTS(input[2].positionOS, vertexInput_2);
LIL_VERTEX_NORMAL_INPUTS(input[0].normalOS, vertexNormalInput_0);
LIL_VERTEX_NORMAL_INPUTS(input[1].normalOS, vertexNormalInput_1);
LIL_VERTEX_NORMAL_INPUTS(input[2].normalOS, vertexNormalInput_2);
float4 tessFactor;
tessFactor.x = lilCalcEdgeTessFactor(vertexInput_1.positionWS, vertexInput_2.positionWS, _TessEdge);
tessFactor.y = lilCalcEdgeTessFactor(vertexInput_2.positionWS, vertexInput_0.positionWS, _TessEdge);
tessFactor.z = lilCalcEdgeTessFactor(vertexInput_0.positionWS, vertexInput_1.positionWS, _TessEdge);
tessFactor.xyz = min(tessFactor.xyz, _TessFactorMax);
// Rim
float3 nv = float3(abs(dot(vertexNormalInput_0.normalWS, lilViewDirection(lilToAbsolutePositionWS(vertexInput_0.positionWS)))),
abs(dot(vertexNormalInput_1.normalWS, lilViewDirection(lilToAbsolutePositionWS(vertexInput_1.positionWS)))),
abs(dot(vertexNormalInput_2.normalWS, lilViewDirection(lilToAbsolutePositionWS(vertexInput_2.positionWS)))));
nv = saturate(1.0 - float3(nv.y + nv.z, nv.z + nv.x, nv.x + nv.y) * 0.5);
tessFactor.xyz = max(tessFactor.xyz * nv * nv, 1.0);
tessFactor.w = (tessFactor.x+tessFactor.y+tessFactor.z) / 3.0;
// Cull out of screen
float4 pos[3] = {vertexInput_0.positionCS, vertexInput_1.positionCS, vertexInput_2.positionCS};
pos[0].xy = pos[0].xy/abs(pos[0].w);
pos[1].xy = pos[1].xy/abs(pos[1].w);
pos[2].xy = pos[2].xy/abs(pos[2].w);
tessFactor = (pos[0].x > 1.01 && pos[1].x > 1.01 && pos[2].x > 1.01) ||
(pos[0].x < -1.01 && pos[1].x < -1.01 && pos[2].x < -1.01) ||
(pos[0].y > 1.01 && pos[1].y > 1.01 && pos[2].y > 1.01) ||
(pos[0].y < -1.01 && pos[1].y < -1.01 && pos[2].y < -1.01) ? 0.0 : tessFactor;
output.edge[0] = tessFactor.x;
output.edge[1] = tessFactor.y;
output.edge[2] = tessFactor.z;
output.inside = tessFactor.w;
return output;
}
//------------------------------------------------------------------------------------------------------------------------------
// Domain Shader
[domain("tri")]
#if defined(LIL_ONEPASS_OUTLINE)
v2g domain(lilTessellationFactors hsConst, const OutputPatch<appdata, 3> input, float3 bary : SV_DomainLocation)
#else
v2f domain(lilTessellationFactors hsConst, const OutputPatch<appdata, 3> input, float3 bary : SV_DomainLocation)
#endif
{
appdata output;
LIL_INITIALIZE_STRUCT(appdata, output);
LIL_TRANSFER_INSTANCE_ID(input[0], output);
#if defined(LIL_APP_POSITION)
LIL_TRI_INTERPOLATION(input,output,bary,positionOS);
#endif
#if defined(LIL_APP_TEXCOORD0)
LIL_TRI_INTERPOLATION(input,output,bary,uv0);
#endif
#if defined(LIL_APP_TEXCOORD1)
LIL_TRI_INTERPOLATION(input,output,bary,uv1);
#endif
#if defined(LIL_APP_TEXCOORD2)
LIL_TRI_INTERPOLATION(input,output,bary,uv2);
#endif
#if defined(LIL_APP_TEXCOORD3)
LIL_TRI_INTERPOLATION(input,output,bary,uv3);
#endif
#if defined(LIL_APP_TEXCOORD4)
LIL_TRI_INTERPOLATION(input,output,bary,uv4);
#endif
#if defined(LIL_APP_TEXCOORD5)
LIL_TRI_INTERPOLATION(input,output,bary,uv5);
#endif
#if defined(LIL_APP_TEXCOORD6)
LIL_TRI_INTERPOLATION(input,output,bary,uv6);
#endif
#if defined(LIL_APP_TEXCOORD7)
LIL_TRI_INTERPOLATION(input,output,bary,uv7);
#endif
#if defined(LIL_APP_COLOR)
LIL_TRI_INTERPOLATION(input,output,bary,color);
#endif
#if defined(LIL_APP_NORMAL)
LIL_TRI_INTERPOLATION(input,output,bary,normalOS);
#endif
#if defined(LIL_APP_TANGENT)
LIL_TRI_INTERPOLATION(input,output,bary,tangentOS);
#endif
#if defined(LIL_APP_VERTEXID)
output.vertexID = input[0].vertexID;
#endif
#if defined(LIL_APP_PREVPOS)
LIL_TRI_INTERPOLATION(input,output,bary,previousPositionOS);
#endif
#if defined(LIL_APP_PREVEL)
LIL_TRI_INTERPOLATION(input,output,bary,precomputedVelocity);
#endif
output.normalOS = normalize(output.normalOS);
float3 pt[3];
for(int i = 0; i < 3; i++)
pt[i] = input[i].normalOS * (dot(input[i].positionOS.xyz, input[i].normalOS) - dot(output.positionOS.xyz, input[i].normalOS) - _TessShrink*0.01);
output.positionOS.xyz += (pt[0] * bary.x + pt[1] * bary.y + pt[2] * bary.z) * _TessStrength;
return vert(output);
}
#endif