Files
Fishing2/Assets/ThirdParty/LuxWater/Shaders/Includes/LuxWater_Tess.cginc
2025-05-10 12:49:47 +08:00

134 lines
4.6 KiB
HLSL

// ------------------------------------------------------------------
// Tessellation
// Tess additional Inputs
half _LuxWater_EdgeLength;
//float _TessMaxDisp;
#ifdef UNITY_CAN_COMPILE_TESSELLATION
#include "Tessellation.cginc"
struct TessVertex {
float4 vertex : INTERNALTESSPOS;
float4 color : COLOR;
// Projectors
//float3 normal : NORMAL;
#if !defined(ISWATERVOLUME)
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
struct OutputPatchConstant {
float edge[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
TessVertex tessvert (appdata_water v) {
UNITY_SETUP_INSTANCE_ID(v);
TessVertex o = (TessVertex)0;
UNITY_TRANSFER_INSTANCE_ID(v,o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
// We transfer the position to WS here to reduce cracks
o.vertex = mul(unity_ObjectToWorld, v.vertex); //v.vertex;
o.color = v.color;
// Projectors
//o.normal = v.normal;
#if !defined(ISWATERVOLUME)
o.normal = v.normal;
o.tangent = v.tangent;
o.texcoord = v.texcoord;
#endif
return o;
}
float4 LuxEdgeLengthBasedTess (float4 v0, float4 v1, float4 v2, float edgeLength)
{
// Input is in WS already!
float3 pos0 = v0.xyz;
float3 pos1 = v1.xyz;
float3 pos2 = v2.xyz;
float4 tess;
tess.x = UnityCalcEdgeTessFactor (pos1, pos2, edgeLength);
tess.y = UnityCalcEdgeTessFactor (pos2, pos0, edgeLength);
tess.z = UnityCalcEdgeTessFactor (pos0, pos1, edgeLength);
tess.w = (tess.x + tess.y + tess.z) / 3.0f;
return tess;
}
float4 Tessellation(TessVertex v, TessVertex v1, TessVertex v2) {
if (v.color.r + v1.color.r + v2.color.r == 0) {
return float4(1,1,1,1);
}
return LuxEdgeLengthBasedTess(v.vertex, v1.vertex, v2.vertex, _LuxWater_EdgeLength);
// 4.3ms ocean on GTX 970M
// return UnityEdgeLengthBasedTess(v.vertex, v1.vertex, v2.vertex, _LuxWater_EdgeLength);
// 4.0ms ocean on GTX 970M
// return UnityEdgeLengthBasedTessCull(v.vertex, v1.vertex, v2.vertex, _LuxWater_EdgeLength, _TessMaxDisp);
}
OutputPatchConstant hullconst (InputPatch<TessVertex,3> v) {
OutputPatchConstant o;
float4 ts = Tessellation( v[0], v[1], v[2] );
ts = clamp(ts, float4(1,1,1,1), float4(31,31,31,31));
o.edge[0] = ts.x;
o.edge[1] = ts.y;
o.edge[2] = ts.z;
o.inside = ts.w;
return o;
}
// Tessellation hull shader
[UNITY_domain("tri")]
[UNITY_partitioning("fractional_odd")]
[UNITY_outputtopology("triangle_cw")]
[UNITY_patchconstantfunc("hullconst")]
[UNITY_outputcontrolpoints(3)]
TessVertex hs_surf (InputPatch<TessVertex,3> v, uint id : SV_OutputControlPointID) {
return v[id];
}
// tessellation domain shader
[UNITY_domain("tri")]
v2f ds_surf (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3> vi, float3 bary : SV_DomainLocation) {
appdata_water v = (appdata_water)0;
UNITY_TRANSFER_INSTANCE_ID(vi[0], v); // important
v.vertex = vi[0].vertex*bary.x + vi[1].vertex*bary.y + vi[2].vertex*bary.z;
v.color = vi[0].color*bary.x + vi[1].color*bary.y + vi[2].color*bary.z;
// Projectors
// v.normal = vi[0].normal*bary.x + vi[1].normal*bary.y + vi[2].normal*bary.z;
#if !defined(ISWATERVOLUME)
v.normal = vi[0].normal*bary.x + vi[1].normal*bary.y + vi[2].normal*bary.z;
v.texcoord = vi[0].texcoord*bary.x + vi[1].texcoord*bary.y + vi[2].texcoord*bary.z;
//#ifdef UNITY_PASS_FORWARDADD
//v.texcoord1 = vi[0].texcoord1*bary.x + vi[1].texcoord1*bary.y + vi[2].texcoord1*bary.z;
//#endif
v.tangent = vi[0].tangent*bary.x + vi[1].tangent*bary.y + vi[2].tangent*bary.z;
#endif
// this works - but the macro below does not?
// #if defined(UNITY_INSTANCING_ENABLED) || defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) || defined(UNITY_STEREO_INSTANCING_ENABLED)
// v.instanceID = vi[0].instanceID;
// #endif
// Now call the regular vertex function
v2f o = vert(v);
UNITY_TRANSFER_INSTANCE_ID(vi[0], o);
return o;
}
#endif