summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-11-03 14:34:46 -0800
committeryum <yum.food.vr@gmail.com>2025-11-03 14:36:47 -0800
commitf606b36aa9e5a562cf46a46124190406d629b6aa (patch)
treee5f756b2983441233d805fb55772c0a393f0cdea
parent4bcd85c9a2a6ede722aea3a403a2a09d9d7cb84d (diff)
begin work on corrected hex domain repetition
-rw-r--r--ray_marching.cginc97
1 files changed, 67 insertions, 30 deletions
diff --git a/ray_marching.cginc b/ray_marching.cginc
index fe48f2c..bf01eb4 100644
--- a/ray_marching.cginc
+++ b/ray_marching.cginc
@@ -45,6 +45,72 @@ float map(float3 p) {
return d;
}
+#if defined(_RAY_MARCHING_HEX_GRID)
+void hex_nearest_neighbors(float3 cubeId, float3 neighborDir,
+ out float3 id0, out float3 id1, out float3 id2) {
+ // Standard cube-coordinate neighbour offsets (sum equals zero).
+ const float3 axis0 = float3( 1.0f, 0.0f, -1.0f);
+ const float3 axis1 = float3( 0.0f, 1.0f, -1.0f);
+ const float3 axis2 = float3( 1.0f, -1.0f, 0.0f);
+
+ const float3 cube0 = cubeId + axis0 * neighborDir.xxx;
+ const float3 cube1 = cubeId + axis1 * neighborDir.yyy;
+ const float3 cube2 = cubeId + axis2 * neighborDir.zzz;
+
+ // Convert back to our "x = y + z" coordinate representation.
+ id0 = float3(cube0.x + cube0.y, cube0.x, cube0.y);
+ id1 = float3(cube1.x + cube1.y, cube1.x, cube1.y);
+ id2 = float3(cube2.x + cube2.y, cube2.x, cube2.y);
+}
+
+float domain_repeat_hex_grid(inout float3 p) {
+ float d;
+
+ const float3 count = _Ray_Marching_Hex_Grid_Count * 0.5f;
+ const float3 period = 1.0f / count;
+ const float3 hex = cart_to_hex(p.xy);
+ // Cell ID.
+ const float3 id = round_hex(hex / period);
+ // Coordinates within the current cell.
+ const float3 local = hex - period * id;
+
+ const float3 cubeId = float3(id.y, id.z, -id.y - id.z);
+ const float3 cubeLocal = float3(local.y, local.z, -local.y - local.z);
+ float3 neighborDir = sign(cubeLocal);
+ neighborDir += (1.0f.xxx - abs(neighborDir));
+
+#if defined(_RAY_MARCHING_CORRECT_REPETITION)
+ float3 ids[4];
+ ids[0] = id;
+ hex_nearest_neighbors(cubeId, neighborDir, ids[1], ids[2], ids[3]);
+ const uint kNumCells = 4u;
+#else
+ float3 ids[1];
+ ids[0] = id;
+ const uint kNumCells = 1u;
+#endif
+
+ d = 1e9;
+ float3 bestPos = p;
+ for (uint ii = 0; ii < kNumCells; ++ii) {
+ const float3 rid = ids[ii];
+ if (any(abs(rid) > count * 0.5f)) continue;
+
+ float3 candidate = p;
+ candidate.xy = hex_to_cart(hex - period * rid);
+
+ const float d_cur = map(candidate);
+ if (d_cur < d) {
+ d = d_cur;
+ bestPos = candidate;
+ }
+ }
+
+ p = bestPos;
+ return d;
+}
+#endif // _RAY_MARCHING_HEX_GRID
+
float domain_repeat(inout float3 p) {
float d;
#if defined(_RAY_MARCHING_CART_GRID)
@@ -62,36 +128,7 @@ float domain_repeat(inout float3 p) {
d = map(p);
}
#elif defined(_RAY_MARCHING_HEX_GRID)
- {
- const float3 count = _Ray_Marching_Hex_Grid_Count * 0.5f;
- const float3 period = 1.0f / count;
- const float3 hex = cart_to_hex(p.xy);
-
- float half_period = period * 0.5;
- float3 which = floor((hex + half_period) / period);
-
- // The original code here was this:
- // p_hex = glsl_mod(p_hex + half_period, period) - half_period;
- //
- // But you can simplify it. Given the definition of glsl_mod:
- // #define glsl_mod(x,y) (((x)-(y)*floor((x)/(y))))
- //
- // You can plug in terms:
- // (p_hex + half_period) - (period) * floor((p_hex + half_period) / period)
- // = p_hex + half_period - period * floor(p_hex/period + 0.5)
- //
- // For all x,
- // round(x) = floor(x + 0.5)
- //
- // Continuing to simplify:
- // (p_hex + half_period - period * round(p_hex/period)) - half_period
- // = p_hex - period * round(p_hex / period)
- const float3 hex_inst = hex - period * round_hex(hex / period);
-
- p.xy = (any(abs(which) > count/2) ? 1e9 : hex_to_cart(hex_inst));
-
- d = map(p);
- }
+ d = domain_repeat_hex_grid(p);
#else
d = map(p);
#endif