#ifndef __3NER_INC #define __3NER_INC #define INCLUDE_UNITY_STANDARD_BRDF_DEPRECATED #include "UnityStandardBRDF.cginc" #include "UnityDeprecated.cginc" #include "UnityCG.cginc" #include "UnityLightingCommon.cginc" #include "AutoLight.cginc" #include "brdf.cginc" #include "pbr.cginc" #include "lighting.cginc" #include "globals.cginc" #include "interpolators.cginc" v2f vert(appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_INITIALIZE_OUTPUT(v2f, o); UNITY_TRANSFER_INSTANCE_ID(v, o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); #if defined(_TESSELLATION) o.tpos = v.vertex; #endif o.pos = UnityObjectToClipPos(v.vertex); o.uv0 = v.uv0; o.objPos = v.vertex; o.worldPos = mul(unity_ObjectToWorld, v.vertex); o.eyeVec.xyz = o.worldPos.xyz - _WorldSpaceCameraPos; o.normal = UnityObjectToWorldNormal(v.normal); o.tangent.xyz = UnityObjectToWorldNormal(v.tangent.xyz); o.tangent.w = v.tangent.w; UNITY_TRANSFER_LIGHTING(o, v.uv1); UNITY_TRANSFER_FOG_COMBINED_WITH_EYE_VEC(o, o.pos); TRANSFER_SHADOW(o); #if defined(SHADOW_CASTER_PASS) TRANSFER_SHADOW_CASTER_NORMALOFFSET(o); #endif return o; } struct tess_factors { float edge[3] : SV_TessFactor; float inside : SV_InsideTessFactor; }; bool cullPatch(float4 p0, float4 p1, float4 p2, float bias) { return (p0.x < -p0.w - bias && p1.x < -p1.w - bias && p2.x < -p2.w - bias) || (p0.x > p0.w + bias && p1.x > p1.w + bias && p2.x > p2.w + bias) || (p0.y < -p0.w - bias && p1.y < -p1.w - bias && p2.y < -p2.w - bias) || (p0.y > p0.w + bias && p1.y > p1.w + bias && p2.y > p2.w + bias) || (p0.z < -p0.w - bias && p1.z < -p1.w - bias && p2.z < -p2.w - bias) || (p0.z > p0.w + bias && p1.z > p1.w + bias && p2.z > p2.w + bias); } // Replaces the existing patch_constant function tess_factors patch_constant(InputPatch patch) { tess_factors f; #if defined(_TESSELLATION) float edgeLength = _Tessellation_Factor; float3 p0_world = mul(unity_ObjectToWorld, float4(patch[0].objPos, 1)); float3 p1_world = mul(unity_ObjectToWorld, float4(patch[1].objPos, 1)); float3 p2_world = mul(unity_ObjectToWorld, float4(patch[2].objPos, 1)); float3 v0 = p0_world - _WorldSpaceCameraPos; float3 v1 = p1_world - _WorldSpaceCameraPos; float3 v2 = p2_world - _WorldSpaceCameraPos; // Angular size drops with inverse distance float s0 = rsqrt(dot(v0, v0)); float s1 = rsqrt(dot(v1, v1)); float s2 = rsqrt(dot(v2, v2)); float s01 = (s0 + s1) * 0.5f; float s12 = (s1 + s2) * 0.5f; float s20 = (s2 + s0) * 0.5f; float k = _Tessellation_Falloff_Factor; f.edge[2] = min(_Tessellation_Factor, k * _Tessellation_Factor * s01); f.edge[0] = min(_Tessellation_Factor, k * _Tessellation_Factor * s12); f.edge[1] = min(_Tessellation_Factor, k * _Tessellation_Factor * s20); f.inside = (f.edge[0] + f.edge[1] + f.edge[2]) * 0.333333f; // Early exit if tessellation is minimal [branch] if (f.inside <= 1.5) { return f; } #else f.edge[0] = 1; f.edge[1] = 1; f.edge[2] = 1; f.inside = 1; #endif #if defined(_TESSELLATION) && defined(_TESSELLATION_HEIGHTMAPS) { float4 p0 = patch[0].pos; float4 p1 = patch[1].pos; float4 p2 = patch[2].pos; if (cullPatch(p0, p1, p2, _Tessellation_Frustum_Culling_Bias)) { f.edge[0] = 1; f.edge[1] = 1; f.edge[2] = 1; f.inside = 1; } } #endif return f; } [UNITY_domain("tri")] [UNITY_outputcontrolpoints(3)] [UNITY_outputtopology("triangle_cw")] [UNITY_partitioning("fractional_odd")] [UNITY_patchconstantfunc("patch_constant")] v2f hull( InputPatch patch, uint id : SV_OutputControlPointID) { return patch[id]; } [UNITY_domain("tri")] v2f domain( tess_factors factors, OutputPatch patch, float3 baryc : SV_DomainLocation) { v2f o = (v2f) 0; #define DOMAIN_INTERP(fieldName) \ patch[0].fieldName * baryc.x + \ patch[1].fieldName * baryc.y + \ patch[2].fieldName * baryc.z o.uv0 = DOMAIN_INTERP(uv0); #if defined(_TESSELLATION) o.objPos = DOMAIN_INTERP(tpos); #else o.objPos = DOMAIN_INTERP(objPos); #endif o.normal = DOMAIN_INTERP(normal); o.tangent = DOMAIN_INTERP(tangent); o.worldPos = mul(unity_ObjectToWorld, float4(o.objPos, 1)); o.pos = UnityObjectToClipPos(o.objPos); o.eyeVec.xyz = o.worldPos - _WorldSpaceCameraPos; UNITY_TRANSFER_INSTANCE_ID(patch[0], o); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); return o; } float4 frag(v2f i, uint facing : SV_IsFrontFace) : SV_Target { i.normal *= facing ? 1 : -1; i.normal = normalize(i.normal); i.tangent.xyz = normalize(i.tangent.xyz); Pbr pbr = getPbr(i); LightData light_data; GetLighting(i, pbr, light_data); return brdf(pbr, light_data); } #endif // __3NER_INC