summaryrefslogtreecommitdiffstats
path: root/tessellation.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-08-01 13:37:40 -0700
committeryum <yum.food.vr@gmail.com>2025-08-01 13:37:40 -0700
commit512357cd6ffe15c4e4fb40ee09d4f04c51df95a3 (patch)
tree6d77e0bc7be53063fc95a1255d24fc59860afdc8 /tessellation.cginc
parent4186d84cccf1d0db4ba413dba63baf87c87b79bb (diff)
ocean wave work
- add sea foam feature, which takes horizontal displacement derivatives and calculates folding areas (with a bias) using the Tessendorf Jacobian method. - add "isInViewFrustum" method to tessellation
Diffstat (limited to 'tessellation.cginc')
-rw-r--r--tessellation.cginc158
1 files changed, 99 insertions, 59 deletions
diff --git a/tessellation.cginc b/tessellation.cginc
index fce9979..24d53ab 100644
--- a/tessellation.cginc
+++ b/tessellation.cginc
@@ -13,6 +13,79 @@ struct tess_factors {
float inside : SV_InsideTessFactor;
};
+bool isInViewFrustum(float4 clipPos, float radius) {
+ return -clipPos.w - radius < clipPos.x && clipPos.x < clipPos.w + radius &&
+ -clipPos.w - radius < clipPos.y && clipPos.y < clipPos.w + radius &&
+ -clipPos.w - radius < clipPos.z && clipPos.z < clipPos.w + radius;
+}
+
+#if defined(_TESSELLATION_HEIGHTMAP_0) || defined(_TESSELLATION_HEIGHTMAP_1) || defined(_TESSELLATION_HEIGHTMAP_2) || defined(_TESSELLATION_HEIGHTMAP_3) || defined(_TESSELLATION_HEIGHTMAP_4) || defined(_TESSELLATION_HEIGHTMAP_5) || defined(_TESSELLATION_HEIGHTMAP_6) || defined(_TESSELLATION_HEIGHTMAP_7)
+#define _TESSELLATION_HEIGHTMAP
+#endif
+
+float4 applyHeightmap(float4 objPos, float2 uv, float3 normal, float3 tangent, float3 binormal) {
+#if defined(_TESSELLATION) && defined(_TESSELLATION_HEIGHTMAP)
+ float3 height = 0;
+#if defined(_TESSELLATION_HEIGHTMAP_0)
+ float3 heightmap_0_sample = _Tessellation_Heightmap_0.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_0_ST.xy, 0);
+ height += heightmap_0_sample * _Tessellation_Heightmap_0_Scale + _Tessellation_Heightmap_0_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_1)
+ float3 heightmap_1_sample = _Tessellation_Heightmap_1.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_1_ST.xy, 0);
+ height += heightmap_1_sample * _Tessellation_Heightmap_1_Scale + _Tessellation_Heightmap_1_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_2)
+ float3 heightmap_2_sample = _Tessellation_Heightmap_2.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_2_ST.xy, 0);
+ height += heightmap_2_sample * _Tessellation_Heightmap_2_Scale + _Tessellation_Heightmap_2_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_3)
+ float3 heightmap_3_sample = _Tessellation_Heightmap_3.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_3_ST.xy, 0);
+ height += heightmap_3_sample * _Tessellation_Heightmap_3_Scale + _Tessellation_Heightmap_3_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_4)
+ float3 heightmap_4_sample = _Tessellation_Heightmap_4.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_4_ST.xy, 0);
+ height += heightmap_4_sample * _Tessellation_Heightmap_4_Scale + _Tessellation_Heightmap_4_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_5)
+ float3 heightmap_5_sample = _Tessellation_Heightmap_5.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_5_ST.xy, 0);
+ height += heightmap_5_sample * _Tessellation_Heightmap_5_Scale + _Tessellation_Heightmap_5_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_6)
+ float3 heightmap_6_sample = _Tessellation_Heightmap_6.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_6_ST.xy, 0);
+ height += heightmap_6_sample * _Tessellation_Heightmap_6_Scale + _Tessellation_Heightmap_6_Offset;
+#endif
+#if defined(_TESSELLATION_HEIGHTMAP_7)
+ float3 heightmap_7_sample = _Tessellation_Heightmap_7.SampleLevel(bilinear_repeat_s,
+ uv * _Tessellation_Heightmap_7_ST.xy, 0);
+ height += heightmap_7_sample * _Tessellation_Heightmap_7_Scale + _Tessellation_Heightmap_7_Offset;
+#endif
+
+#if defined(_TESSELLATION_HEIGHTMAP_WORLD_SPACE)
+ objPos.xyz += mul(unity_WorldToObject, height).xyz;
+#else
+#if defined(OUTLINE_PASS) && defined(_TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL)
+ float3 heightmap_direction = mul(transpose(-float3x3(normal, tangent, binormal)), _Tessellation_Heightmap_Direction_Control_Vector);
+#elif defined(OUTLINE_PASS) && !defined(_TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL)
+ float3 heightmap_direction = -normal;
+#elif !defined(OUTLINE_PASS) && defined(_TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL)
+ float3 heightmap_direction = mul(transpose(float3x3(normal, tangent, binormal)), _Tessellation_Heightmap_Direction_Control_Vector);
+#else
+ float3 heightmap_direction = normal;
+#endif
+ objPos.xyz += heightmap_direction * height;
+#endif
+
+#endif // _TESSELLATION_HEIGHTMAP
+ return objPos;
+}
+
tess_factors patch_constant(InputPatch<v2f, 3> patch) {
tess_factors f;
#if defined(_TESSELLATION)
@@ -32,6 +105,31 @@ tess_factors patch_constant(InputPatch<v2f, 3> patch) {
#else
float factor = 1;
#endif
+
+#if defined(_TESSELLATION_HEIGHTMAP)
+ [branch]
+ if (factor > 3) {
+ // Scuffed occlusion culling. Need to know what the position will be after displacement
+ // in order to do it right. "Scuffed" because we repeat work :/ this same transform gets
+ // applied in the domain shader. This isn't so bad if we assume that we're tessellating
+ // at a relatively high factor.
+ float3 p0newObjPos = applyHeightmap(patch[0].objPos, patch[0].uv01.xy, patch[0].normal, patch[0].tangent, patch[0].binormal);
+ float3 p1newObjPos = applyHeightmap(patch[1].objPos, patch[1].uv01.xy, patch[1].normal, patch[1].tangent, patch[1].binormal);
+ float3 p2newObjPos = applyHeightmap(patch[2].objPos, patch[2].uv01.xy, patch[2].normal, patch[2].tangent, patch[2].binormal);
+ float4 p0newClipPos = UnityObjectToClipPos(p0newObjPos);
+ float4 p1newClipPos = UnityObjectToClipPos(p1newObjPos);
+ float4 p2newClipPos = UnityObjectToClipPos(p2newObjPos);
+ // Dirty hack to prevent objects that are currently outside the view frustum,
+ // but which are after displacement, from being culled.
+ float radius = 0.3;
+ bool inViewFrustum0 = isInViewFrustum(p0newClipPos, radius);
+ bool inViewFrustum1 = isInViewFrustum(p1newClipPos, radius);
+ bool inViewFrustum2 = isInViewFrustum(p2newClipPos, radius);
+ bool inViewFrustum = inViewFrustum0 || inViewFrustum1 || inViewFrustum2;
+ factor = inViewFrustum ? factor : 1;
+ }
+#endif
+
f.edge[0] = factor;
f.edge[1] = factor;
f.edge[2] = factor;
@@ -82,65 +180,7 @@ v2f domain(
#endif
#endif
-#if defined(_TESSELLATION) && (defined(_TESSELLATION_HEIGHTMAP_0) || defined(_TESSELLATION_HEIGHTMAP_1) || defined(_TESSELLATION_HEIGHTMAP_2) || defined(_TESSELLATION_HEIGHTMAP_3) || defined(_TESSELLATION_HEIGHTMAP_4) || defined(_TESSELLATION_HEIGHTMAP_5) || defined(_TESSELLATION_HEIGHTMAP_6) || defined(_TESSELLATION_HEIGHTMAP_7))
- float3 height = 0;
-#if defined(_TESSELLATION_HEIGHTMAP_0)
- float3 heightmap_0_sample = _Tessellation_Heightmap_0.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_0_ST.xy, 0);
- height += heightmap_0_sample * _Tessellation_Heightmap_0_Scale + _Tessellation_Heightmap_0_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_1)
- float3 heightmap_1_sample = _Tessellation_Heightmap_1.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_1_ST.xy, 0);
- height += heightmap_1_sample * _Tessellation_Heightmap_1_Scale + _Tessellation_Heightmap_1_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_2)
- float3 heightmap_2_sample = _Tessellation_Heightmap_2.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_2_ST.xy, 0);
- height += heightmap_2_sample * _Tessellation_Heightmap_2_Scale + _Tessellation_Heightmap_2_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_3)
- float3 heightmap_3_sample = _Tessellation_Heightmap_3.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_3_ST.xy, 0);
- height += heightmap_3_sample * _Tessellation_Heightmap_3_Scale + _Tessellation_Heightmap_3_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_4)
- float3 heightmap_4_sample = _Tessellation_Heightmap_4.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_4_ST.xy, 0);
- height += heightmap_4_sample * _Tessellation_Heightmap_4_Scale + _Tessellation_Heightmap_4_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_5)
- float3 heightmap_5_sample = _Tessellation_Heightmap_5.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_5_ST.xy, 0);
- height += heightmap_5_sample * _Tessellation_Heightmap_5_Scale + _Tessellation_Heightmap_5_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_6)
- float3 heightmap_6_sample = _Tessellation_Heightmap_6.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_6_ST.xy, 0);
- height += heightmap_6_sample * _Tessellation_Heightmap_6_Scale + _Tessellation_Heightmap_6_Offset;
-#endif
-#if defined(_TESSELLATION_HEIGHTMAP_7)
- float3 heightmap_7_sample = _Tessellation_Heightmap_7.SampleLevel(bilinear_repeat_s,
- o.uv01.xy * _Tessellation_Heightmap_7_ST.xy, 0);
- height += heightmap_7_sample * _Tessellation_Heightmap_7_Scale + _Tessellation_Heightmap_7_Offset;
-#endif
-
-#if defined(_TESSELLATION_HEIGHTMAP_WORLD_SPACE)
- o.objPos.xyz += mul(unity_WorldToObject, height).xyz;
-#else
-#if defined(OUTLINE_PASS) && defined(_TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL)
- float3 heightmap_direction = mul(transpose(-float3x3(o.normal, o.tangent, o.binormal)), _Tessellation_Heightmap_Direction_Control_Vector);
-#elif defined(OUTLINE_PASS) && !defined(_TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL)
- float3 heightmap_direction = -o.normal;
-#elif !defined(OUTLINE_PASS) && defined(_TESSELLATION_HEIGHTMAP_DIRECTION_CONTROL)
- float3 heightmap_direction = mul(transpose(float3x3(o.normal, o.tangent, o.binormal)), _Tessellation_Heightmap_Direction_Control_Vector);
-#else
- float3 heightmap_direction = o.normal;
-#endif
- o.objPos.xyz += heightmap_direction * height;
-#endif
-
-#endif // _TESSELLATION_HEIGHTMAP
+ o.objPos = applyHeightmap(o.objPos, o.uv01.xy, o.normal, o.tangent, o.binormal);
o.pos = UnityObjectToClipPos(o.objPos);
o.worldPos = mul(unity_ObjectToWorld, o.objPos).xyz;