From 5b732ae3d8bf19d4fbade236f318df0f7221cdd2 Mon Sep 17 00:00:00 2001 From: yum Date: Sat, 28 Mar 2026 13:43:27 -0700 Subject: Begin work on Burley's per-pixel histogram preserving blending --- 3ner.shader | 10 ++++++++++ features.cginc | 4 ++++ globals.cginc | 7 +++++++ math.cginc | 20 +++++++++++--------- pbr.cginc | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 9 deletions(-) diff --git a/3ner.shader b/3ner.shader index 0398d27..0eab028 100755 --- a/3ner.shader +++ b/3ner.shader @@ -664,6 +664,16 @@ Shader "yum_food/3ner" [HideInInspector] m_end_Glitter("Glitter", Float) = 0 //endex + //ifex _Burley_Tiling_Enabled==0 + [HideInInspector] m_start_Burley_Tiling("Burley Tiling", Float) = 0 + [ThryToggle(_BURLEY_TILING)] _Burley_Tiling_Enabled("Enable", Float) = 0 + _Burley_Tiling_Input_Scale("Input scale", Range(0, 1)) = 0.5 + _Burley_Tiling_Output_Scale("Output scale", Range(0, 1)) = 0.5 + _Burley_Tiling_Maintex("Base color", 2D) = "white" {} + _Burley_Tiling_Maintex_LUT("Base color LUT", 2D) = "white" {} + [HideInInspector] m_end_Burley_Tiling("Burley Tiling", Float) = 0 + //endex + [HideInInspector] m_end_Main("Main", Float) = 0 [HideInInspector] m_start_Gimmicks("Gimmicks", Float) = 0 diff --git a/features.cginc b/features.cginc index 1ea3858..b30fe8f 100755 --- a/features.cginc +++ b/features.cginc @@ -236,4 +236,8 @@ #pragma shader_feature_local _LETTER_GRID_ANIMATE //endex +//ifex _Burley_Tiling_Enabled==0 +#pragma shader_feature_local _BURLEY_TILING +//endex + #endif // __FEATURES_INC diff --git a/globals.cginc b/globals.cginc index d7ac640..c5c1646 100755 --- a/globals.cginc +++ b/globals.cginc @@ -611,4 +611,11 @@ float _Letter_Grid_Alpha_Threshold; float _Letter_Grid_Animate_Speed; #endif // _LETTER_GRID_ANIMATE +#if defined(_BURLEY_TILING) +float _Burley_Tiling_Input_Scale; +float _Burley_Tiling_Output_Scale; +texture2D _Burley_Tiling_Maintex; +texture2D _Burley_Tiling_Maintex_LUT; +#endif // _BURLEY_TILING + #endif // __GLOBALS_INC diff --git a/math.cginc b/math.cginc index c2ae26e..0f5f8f5 100755 --- a/math.cginc +++ b/math.cginc @@ -13,6 +13,7 @@ #define RCP_SQRT_2 0.707106781f #define RCP_SQRT_3 0.577350269f #define TWO_OVER_THREE 0.6666666666666666f +#define TWO_OVER_SQRT_3 1.15470054f #define SQRT_3 1.73205081f #define SQRT_3_OVER_2 0.8660254037844386f #define EULERS_CONSTANT 2.718281828f @@ -64,20 +65,20 @@ float3 rotate_vector(float3 v, float4 q) return v + q.w * t + cross(q.xyz, t); } -// Cartesian to cube hexagonal coordinates. +// Cartesian to packed cube hexagonal coordinates. +// Stores (q + r, q, r), where the article's cube coordinates satisfy +// q + r + s = 0 and s = -(q + r). // Based on this: https://backdrifting.net/post/064_hex_grids float3 cart_to_hex(float2 cart) { - float p = cart.x; - float q = dot(cart, float2(0.5f, SQRT_3_OVER_2)); - float r = dot(cart, float2(0.5f, -SQRT_3_OVER_2)); - - return float3(p, q, r) * 0.5f; + float q = cart.x - cart.y * RCP_SQRT_3; + float r = cart.y * (2.0f * RCP_SQRT_3); + return float3(q + r, q, r); } -float2 hex_to_cart(float3 cart) { +float2 hex_to_cart(float3 hex_coord) { return float2( - cart[0] + (cart[1] + cart[2]) * 0.5f, - (cart[1] - cart[2]) * SQRT_3_OVER_2); + hex_coord[1] + hex_coord[2] * 0.5f, + hex_coord[2] * SQRT_3_OVER_2); } @@ -166,6 +167,7 @@ float3 domain_warp_procedural(float3 uvw, float strength, float g = 1; for (uint ii = 0; ii < octaves; ++ii) { + // Need to remap noise onto [-1, 1] when domain warping. float3 vnoise = value_noise3(uvw + (noise * 2.0 - 1.0) * strength); noise += vnoise * g; uvw *= lacunarity; diff --git a/pbr.cginc b/pbr.cginc index 2ddcdbf..d59001f 100755 --- a/pbr.cginc +++ b/pbr.cginc @@ -181,6 +181,37 @@ void apply_letter_grid(v2f i, inout Pbr pbr) { #endif } +void apply_burley_tiling(v2f i, inout Pbr pbr) { +#if defined(_BURLEY_TILING) + float2 uv = i.uv01.xy - 0.5; + uv *= TWO_OVER_SQRT_3; + uv /= _Burley_Tiling_Output_Scale; + float3 hex_coord = cart_to_hex(uv); + float3 cell = round_hex(hex_coord); + float3 cube_id = float3(cell.y, cell.z, -cell.y - cell.z); + float3 local_hex = hex_coord - cell; + // Get UVs on [-1/2,1/2] for the current cell. + // This is the tightest square fit that preserves the hex aspect ratio. + float2 local_uv = hex_to_cart(local_hex) * SQRT_3_OVER_2; + float3 tile_rand3 = hash33_fast(cube_id); + // Apply input scaling. + float input_scale = saturate(_Burley_Tiling_Input_Scale); + local_uv *= input_scale; + // Rotate. + float theta = hash31_ff(tile_rand3) * TAU; + float2x2 rot = float2x2(cos(theta), -sin(theta), sin(theta), cos(theta)); + local_uv = mul(rot, local_uv); + // Apply randomized offset, staying within bounds. + // The scaled-and-rotated footprint is bounded by [-Input_Scale / 2, Input_Scale / 2], + // so we can offset by [(1 - Input_Scale) / 2]. + float2 random_offset = (tile_rand3.yz * 2.0 - 1.0) * (0.5 * (1.0 - input_scale)); + local_uv += random_offset; + // Finally, remap onto [0, 1]. + local_uv += 0.5; + pbr.albedo.xy = local_uv.xy; +#endif // _BURLEY_TILING +} + Pbr getPbr(v2f i) { Pbr pbr = (Pbr) 0; @@ -227,6 +258,7 @@ Pbr getPbr(v2f i) { apply_marble(i.worldPos, pbr.albedo.xyz); apply_kintsugi(i.worldPos, pbr.albedo.xyz, pbr.smoothness, pbr.metallic); apply_letter_grid(i, pbr); + apply_burley_tiling(i, pbr); applyDecals(i, pbr, normal_tangent); -- cgit v1.2.3