summaryrefslogtreecommitdiffstats
path: root/ray_marching.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-11-03 19:10:42 -0800
committeryum <yum.food.vr@gmail.com>2025-11-03 19:10:42 -0800
commit27c7851bf08aaee87eb348010737c34b5698adaa (patch)
treea4034549c09bb535bb5dbe1494e9ec7ca3a89e82 /ray_marching.cginc
parentf606b36aa9e5a562cf46a46124190406d629b6aa (diff)
fix hexagonal domain repetition; must check 4 neighbors
Diffstat (limited to 'ray_marching.cginc')
-rw-r--r--ray_marching.cginc139
1 files changed, 97 insertions, 42 deletions
diff --git a/ray_marching.cginc b/ray_marching.cginc
index bf01eb4..9cb8dd0 100644
--- a/ray_marching.cginc
+++ b/ray_marching.cginc
@@ -46,65 +46,120 @@ float map(float3 p) {
}
#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 float gridCount = max(_Ray_Marching_Hex_Grid_Count, 1.0f);
+ const float halfCount = gridCount * 0.5f;
+ const float3 count = float3(halfCount, halfCount, halfCount);
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;
+ float3 candidate = p;
+ candidate.xy = hex_to_cart(local);
+ float d = map(candidate);
+ float3 bestPos = candidate;
+#if defined(_RAY_MARCHING_CORRECT_REPETITION)
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));
+ const float limit = max((gridCount - 1.0f) * 0.5f, 0.0f);
+ const float3 cubeLimit = float3(limit, limit, limit);
+ if (any(abs(cubeId) > cubeLimit)) {
+ p = float3(1e9, 1e9, 1e9);
+ return 1e9;
+ }
+ const float3 cubeOffsets[6] = {
+ float3( 1.0f, -1.0f, 0.0f),
+ float3( 1.0f, 0.0f, -1.0f),
+ float3( 0.0f, 1.0f, -1.0f),
+ float3(-1.0f, 1.0f, 0.0f),
+ float3(-1.0f, 0.0f, 1.0f),
+ float3( 0.0f, -1.0f, 1.0f),
+ };
-#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
+ float neighborDistSq[4] = { 1e9, 1e9, 1e9, 1e9 };
+ float3 neighborIds[4] = {
+ float3(0.0f, 0.0f, 0.0f),
+ float3(0.0f, 0.0f, 0.0f),
+ float3(0.0f, 0.0f, 0.0f),
+ float3(0.0f, 0.0f, 0.0f)};
+ float2 neighborLoc[4] = {
+ float2(0.0f, 0.0f),
+ float2(0.0f, 0.0f),
+ float2(0.0f, 0.0f),
+ float2(0.0f, 0.0f)};
- 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;
+ [unroll]
+ for (int idx = 0; idx < 6; ++idx) {
+ const float3 cube = cubeId + cubeOffsets[idx];
+ const float3 rid = float3(cube.x + cube.y, cube.x, cube.y);
+
+ if (any(abs(cube) > cubeLimit)) {
+ continue;
+ }
- float3 candidate = p;
- candidate.xy = hex_to_cart(hex - period * rid);
+ const float2 localXY = hex_to_cart(hex - period * rid);
+ const float distSq = dot(localXY, localXY);
+
+ if (distSq >= neighborDistSq[3]) {
+ continue;
+ }
+
+ neighborDistSq[3] = distSq;
+ neighborIds[3] = rid;
+ neighborLoc[3] = localXY;
+
+ if (neighborDistSq[3] < neighborDistSq[2]) {
+ const float tmpDist = neighborDistSq[2];
+ const float3 tmpId = neighborIds[2];
+ const float2 tmpLoc = neighborLoc[2];
+ neighborDistSq[2] = neighborDistSq[3];
+ neighborIds[2] = neighborIds[3];
+ neighborLoc[2] = neighborLoc[3];
+ neighborDistSq[3] = tmpDist;
+ neighborIds[3] = tmpId;
+ neighborLoc[3] = tmpLoc;
+ }
+ if (neighborDistSq[2] < neighborDistSq[1]) {
+ const float tmpDist = neighborDistSq[1];
+ const float3 tmpId = neighborIds[1];
+ const float2 tmpLoc = neighborLoc[1];
+ neighborDistSq[1] = neighborDistSq[2];
+ neighborIds[1] = neighborIds[2];
+ neighborLoc[1] = neighborLoc[2];
+ neighborDistSq[2] = tmpDist;
+ neighborIds[2] = tmpId;
+ neighborLoc[2] = tmpLoc;
+ }
+ if (neighborDistSq[1] < neighborDistSq[0]) {
+ const float tmpDist = neighborDistSq[0];
+ const float3 tmpId = neighborIds[0];
+ const float2 tmpLoc = neighborLoc[0];
+ neighborDistSq[0] = neighborDistSq[1];
+ neighborIds[0] = neighborIds[1];
+ neighborLoc[0] = neighborLoc[1];
+ neighborDistSq[1] = tmpDist;
+ neighborIds[1] = tmpId;
+ neighborLoc[1] = tmpLoc;
+ }
+ }
+
+ [unroll]
+ for (int idx = 0; idx < 4; ++idx) {
+ if (neighborDistSq[idx] >= 1e9) {
+ continue;
+ }
- const float d_cur = map(candidate);
+ float3 neighbour = p;
+ neighbour.xy = neighborLoc[idx];
+ const float d_cur = map(neighbour);
if (d_cur < d) {
d = d_cur;
- bestPos = candidate;
+ bestPos = neighbour;
}
}
+#endif // _RAY_MARCHING_CORRECT_REPETITION
p = bestPos;
return d;