From 0d7e2444c55eb2067792c6da57dad370e997fa4d Mon Sep 17 00:00:00 2001 From: yum Date: Sun, 2 Nov 2025 18:10:55 -0800 Subject: add hex grid tiling --- 3ner.shader | 29 ++++++++++++++------ features.cginc | 12 +++++++-- globals.cginc | 16 +++++++++++ math.cginc | 15 +++++++++++ ray_marching.cginc | 70 ++++++++++++++++++++++++++++++++++++++++++------- ray_marching_maps.slang | 19 +++----------- 6 files changed, 127 insertions(+), 34 deletions(-) diff --git a/3ner.shader b/3ner.shader index d755f64..8d3a577 100644 --- a/3ner.shader +++ b/3ner.shader @@ -75,14 +75,27 @@ Shader "yum_food/3ner" [HideInInspector] m_end_Ray_Marching_Baked_Origins("Baked Origins", Float) = 0 //endex - //ifex _Ray_Marching_Ball_Grid_Enabled==0 - [HideInInspector] m_start_Ray_Marching_Ball_Grid("Ball Grid", Float) = 0 - [ThryToggle(_RAY_MARCHING_BALL_GRID)] _Ray_Marching_Ball_Grid_Enabled("Enable", Float) = 0 - _Ray_Marching_Ball_Grid_Radius("Radius", Float) = 1 - _Ray_Marching_Ball_Grid_Count_X("Count X", Range(0,40)) = 5 - _Ray_Marching_Ball_Grid_Count_Y("Count Y", Range(0,40)) = 5 - _Ray_Marching_Ball_Grid_Count_Z("Count Z", Range(0,40)) = 5 - [HideInInspector] m_end_Ray_Marching_Ball_Grid("Ball Grid", Float) = 0 + //ifex _Ray_Marching_Cart_Grid_Enabled==0 + [HideInInspector] m_start_Ray_Marching_Cart_Grid("Cart Grid", Float) = 0 + [ThryToggle(_RAY_MARCHING_CART_GRID)] _Ray_Marching_Cart_Grid_Enabled("Enable", Float) = 0 + _Ray_Marching_Cart_Grid_Count_X("Count X", Range(0,40)) = 5 + _Ray_Marching_Cart_Grid_Count_Y("Count Y", Range(0,40)) = 5 + _Ray_Marching_Cart_Grid_Count_Z("Count Z", Range(0,40)) = 5 + [HideInInspector] m_end_Ray_Marching_Cart_Grid("Cart Grid", Float) = 0 + //endex + + //ifex _Ray_Marching_Hex_Grid_Enabled==0 + [HideInInspector] m_start_Ray_Marching_Hex_Grid("Hex Grid", Float) = 0 + [ThryToggle(_RAY_MARCHING_HEX_GRID)] _Ray_Marching_Hex_Grid_Enabled("Enable", Float) = 0 + _Ray_Marching_Hex_Grid_Count("CountX", Range(0,40)) = 5 + [HideInInspector] m_end_Ray_Marching_Hex_Grid("Hex Grid", Float) = 0 + //endex + + //ifex _Ray_Marching_Ball_Enabled==0 + [HideInInspector] m_start_Ray_Marching_Ball("Ball", Float) = 0 + [ThryToggle(_RAY_MARCHING_BALL)] _Ray_Marching_Ball_Enabled("Enable", Float) = 0 + _Ray_Marching_Ball_Radius("Radius", Range(0,1)) = 1 + [HideInInspector] m_end_Ray_Marching_Ball("Ball", Float) = 0 //endex [HideInInspector] m_end_Ray_Marching("Ray Marching", Float) = 0 diff --git a/features.cginc b/features.cginc index 49aa3e7..9b76cd4 100644 --- a/features.cginc +++ b/features.cginc @@ -84,8 +84,16 @@ #pragma shader_feature_local _RAY_MARCHING_BAKED_ORIGINS //endex -//ifex _Ray_Marching_Ball_Grid_Enabled==0 -#pragma shader_feature_local _RAY_MARCHING_BALL_GRID +//ifex _Ray_Marching_Cart_Grid_Enabled==0 +#pragma shader_feature_local _RAY_MARCHING_CART_GRID +//endex + +//ifex _Ray_Marching_Hex_Grid_Enabled==0 +#pragma shader_feature_local _RAY_MARCHING_HEX_GRID +//endex + +//ifex _Ray_Marching_Ball_Enabled==0 +#pragma shader_feature_local _RAY_MARCHING_BALL //endex #endif // __FEATURES_INC diff --git a/globals.cginc b/globals.cginc index 533e102..181e71f 100644 --- a/globals.cginc +++ b/globals.cginc @@ -134,6 +134,18 @@ float _Ray_Marching_Overstepping_Factor; int _Baked_Origins_UV_Channel_Index; #endif // _RAY_MARCHING_BAKED_ORIGINS +#if defined(_RAY_MARCHING_CART_GRID) +float _Ray_Marching_Cart_Grid_Radius; +float _Ray_Marching_Cart_Grid_Count_X; +float _Ray_Marching_Cart_Grid_Count_Y; +float _Ray_Marching_Cart_Grid_Count_Z; +#endif // _RAY_MARCHING_CART_GRID + +#if defined(_RAY_MARCHING_HEX_GRID) +float _Ray_Marching_Hex_Grid_Radius; +float _Ray_Marching_Hex_Grid_Count; +#endif // _RAY_MARCHING_HEX_GRID + #if defined(_RAY_MARCHING_BALL_GRID) float _Ray_Marching_Ball_Grid_Radius; float _Ray_Marching_Ball_Grid_Count_X; @@ -141,4 +153,8 @@ float _Ray_Marching_Ball_Grid_Count_Y; float _Ray_Marching_Ball_Grid_Count_Z; #endif // _RAY_MARCHING_BALL_GRID +#if defined(_RAY_MARCHING_BALL) +float _Ray_Marching_Ball_Radius; +#endif // _RAY_MARCHING_BALL + #endif // __GLOBALS_INC diff --git a/math.cginc b/math.cginc index 58a9c08..f188a91 100644 --- a/math.cginc +++ b/math.cginc @@ -74,5 +74,20 @@ float2 hex_to_cart(float3 cart) { (cart[1] - cart[2]) * SQRT_3_OVER_2); } + +float3 round_hex(float3 hex_coord) { + float3 rounded = round(hex_coord); + float3 diff = abs(rounded - hex_coord); + float error = rounded.x - rounded.y - rounded.z; + + float3 max_mask = float3( + diff.x > diff.y && diff.x > diff.z, + diff.y > diff.x && diff.y > diff.z, + diff.z > diff.x && diff.z > diff.y); + + rounded += error * float3(-1, 1, 1) * max_mask; + return rounded; +} + #endif // __MATH_INC diff --git a/ray_marching.cginc b/ray_marching.cginc index b13bee0..57a3dff 100644 --- a/ray_marching.cginc +++ b/ray_marching.cginc @@ -42,12 +42,63 @@ void ray_march(inout v2f i) { const uint kMaxIter = _Ray_Marching_Max_Iter; float d_cur; float d_acc = 0; + float3 hit_pos; for (uint ii = 0; ii < kMaxIter; ++ii) { float3 p = ro + rd * d_acc; d_cur = 1e9; -#if defined(_RAY_MARCHING_BALL_GRID) - float3 count = float3(_Ray_Marching_Ball_Grid_Count_X, _Ray_Marching_Ball_Grid_Count_Y, _Ray_Marching_Ball_Grid_Count_Z); - d_cur = min(d_cur, map_ball_grid(p, count)); + + // Coordinate system transformations. +#if defined(_RAY_MARCHING_CART_GRID) + { + float3 count = float3(_Ray_Marching_Cart_Grid_Count_X, _Ray_Marching_Cart_Grid_Count_Y, _Ray_Marching_Cart_Grid_Count_Z); + float3 period = 1.0f / count; + period *= 2; + float3 half_period = period*0.5f; + float3 which = floor((p + half_period) / period); + if (any(abs(which) > count/2)) { + p = 1e6; + } else { + p = glsl_mod(p + half_period, period) - half_period; + } + } +#endif +#if 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)); + } +#endif + + // Sdfs. +#if defined(_RAY_MARCHING_BALL) + { + float r = _Ray_Marching_Ball_Radius; + d_cur = min(d_cur, map_ball(p, _Ray_Marching_Ball_Radius)); + } #endif #if defined(_RAY_MARCHING_OVERSTEP) @@ -56,6 +107,7 @@ void ray_march(inout v2f i) { d_acc += d_cur; if (abs(d_cur) < kMinDist) { + hit_pos = p; break; } if (d_acc > kMaxDist) { @@ -67,13 +119,14 @@ void ray_march(inout v2f i) { discard; } - // TODO clip / hit detection - float3 lclPos = ro + rd * d_acc; + float3 lclPos = hit_pos; float3 lclNorm; float3 lclTan; -#if defined(_RAY_MARCHING_BALL_GRID) - float3 count = float3(_Ray_Marching_Ball_Grid_Count_X, _Ray_Marching_Ball_Grid_Count_Y, _Ray_Marching_Ball_Grid_Count_Z); - map_ball_grid_normal(count, lclPos, lclNorm, lclTan); +#if defined(_RAY_MARCHING_BALL) + { + float r = _Ray_Marching_Ball_Radius; + map_ball_normal(r, lclPos, lclNorm, lclTan); + } #endif i.objPos = lclPos; @@ -83,4 +136,3 @@ void ray_march(inout v2f i) { } #endif // __RAY_MARCHING_INC - diff --git a/ray_marching_maps.slang b/ray_marching_maps.slang index 3c83a19..002ef90 100644 --- a/ray_marching_maps.slang +++ b/ray_marching_maps.slang @@ -32,25 +32,14 @@ R3R1_AUTODIFF_BASIS_VECTORS(fun, __VA_ARGS__); \ R3R1_DEFORM_NORMAL_AND_TANGENT(normal, tangent) -// Just trace a sphere of radius 0.1 for now. [Differentiable] -public float map_ball_grid(float3 p, no_diff float3 count) { - float3 period = 1.0f / count; - period *= 2; - float3 half_period = period*0.5f; - float3 which = floor((p + half_period) / period); - if (any(abs(which) > count/2)) { - p = 1e6; - } else { - p = glsl_mod(p + half_period, period) - half_period; - } - - return length(p) - half_period.x; +public float map_ball(float3 p, no_diff float r) { + return length(p) - r; } -public void map_ball_grid_normal(float3 count, inout float3 xyz, inout float3 normal, +public void map_ball_normal(float r, inout float3 xyz, inout float3 normal, inout float3 tangent) { - R3R1_RAY_MARCH_NORMALS(xyz, normal, tangent, map_ball_grid, count); + R3R1_RAY_MARCH_NORMALS(xyz, normal, tangent, map_ball, r); } #endif // __RAY_MARCHING_MAPS_INC -- cgit v1.2.3