diff options
Diffstat (limited to 'math.cginc')
| -rwxr-xr-x | math.cginc | 92 |
1 files changed, 92 insertions, 0 deletions
@@ -109,5 +109,97 @@ float4 alpha_blend(float4 front, float4 back) { return float4(front.rgb * front.a + back.rgb * (1 - front.a), front.a + back.a * (1 - front.a)); } +// Cheap procedural 3D hash -> [0,1]^3. Based on the "hashwithoutsine" family. +float3 hash33_fast(float3 p) { + p = frac(p * float3(0.1031, 0.1030, 0.0973)); + p += dot(p, p.yxz + 33.33); + return frac((p.xxy + p.yxx) * p.zyx); +} + +// Procedural value noise in [0,1]^3 — trilinear interpolation of hashed corners. +float3 value_noise3(float3 p) { + float3 i = floor(p); + float3 f = frac(p); + float3 u = f * f * (3.0 - 2.0 * f); + + return lerp( + lerp(lerp(hash33_fast(i + float3(0, 0, 0)), hash33_fast(i + float3(1, 0, 0)), u.x), + lerp(hash33_fast(i + float3(0, 1, 0)), hash33_fast(i + float3(1, 1, 0)), u.x), u.y), + lerp(lerp(hash33_fast(i + float3(0, 0, 1)), hash33_fast(i + float3(1, 0, 1)), u.x), + lerp(hash33_fast(i + float3(0, 1, 1)), hash33_fast(i + float3(1, 1, 1)), u.x), u.y), + u.z); +} + +// Domain warping using procedural value noise. +float3 domain_warp_procedural(float3 uvw, float strength, + uint octaves, float lacunarity, float gain) { + float3 noise = 0; + float g = 1; + + for (uint ii = 0; ii < octaves; ++ii) { + noise += value_noise3(uvw + noise * strength) * g; + uvw *= lacunarity; + g *= gain; + } + + noise *= (1 - gain) / (1 - pow(gain, octaves)); + + return noise; +} + +// Domain warping using a 3D noise texture. Texture should have an EV of +// 0.5. +float3 domain_warp_3d_tex(texture3D noise_tex, float3 uvw, float strength, + uint octaves, float lacunarity, float gain) { + float3 noise = 0; + float g = 1; + + float3 uvw_dx = ddx(uvw); + float3 uvw_dy = ddy(uvw); + + for (uint ii = 0; ii < octaves; ++ii) { + noise += noise_tex.SampleGrad(aniso4_trilinear_repeat_s, uvw + noise * strength, uvw_dx, uvw_dy).rgb * g; + uvw *= lacunarity; + g *= gain; + uvw_dx *= lacunarity; + uvw_dy *= lacunarity; + } + + // Normalize: geometric series 1 + r + ... + r^{n-1} = (1 - r^n) / (1 - r) + noise *= (1 - gain) / (1 - pow(gain, octaves)); + + return noise; +} + +// Return distance to the nearest cell edge in a Voronoi pattern. +float voronoi_edge_distance(float3 x) { + float3 p = floor(x); + float3 f = frac(x); + float d1 = 1e6; + float d2 = 1e6; + float3 p1 = 0; + float3 p2 = 0; + + for (int k = -1; k <= 1; k++) { + for (int j = -1; j <= 1; j++) { + for (int i = -1; i <= 1; i++) { + float3 b = float3(i, j, k); + float3 r = b + hash33_fast(p + b) - f; + float d = dot(r, r); + if (d < d1) { + d2 = d1; + p2 = p1; + d1 = d; + p1 = r; + } else if (d < d2) { + d2 = d; + p2 = r; + } + } + } + } + return (d2 - d1) / (2.0 * max(1e-4, length(p2 - p1))); +} + #endif // __MATH_INC |
