diff options
| author | yum <yum.food.vr@gmail.com> | 2025-11-03 14:34:46 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2025-11-03 14:36:47 -0800 |
| commit | f606b36aa9e5a562cf46a46124190406d629b6aa (patch) | |
| tree | e5f756b2983441233d805fb55772c0a393f0cdea | |
| parent | 4bcd85c9a2a6ede722aea3a403a2a09d9d7cb84d (diff) | |
begin work on corrected hex domain repetition
| -rw-r--r-- | ray_marching.cginc | 97 |
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 |
