From 0264f5e767b0b54e82b7c11457b491be555be577 Mon Sep 17 00:00:00 2001 From: yum Date: Wed, 26 Feb 2025 01:18:09 -0800 Subject: Add glitter and more masked stencil channels --- glitter.cginc | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 glitter.cginc (limited to 'glitter.cginc') diff --git a/glitter.cginc b/glitter.cginc new file mode 100644 index 0000000..2f7a796 --- /dev/null +++ b/glitter.cginc @@ -0,0 +1,87 @@ +#ifndef __GLITTER_INC +#define __GLITTER_INC + +#include "math.cginc" +#include "pema99.cginc" +#include "quilez.cginc" + +struct GlitterParams { + float4 color; + float layers; + float cell_size; + float size; + float major_minor_ratio; + float angle_randomization_range; + float center_randomization_range; + float size_randomization_range; + float existence_chance; +#if defined(_GLITTER_ANGLE_LIMIT) + float angle_limit; + float angle_limit_transition_width; +#endif +#if defined(_GLITTER_MASK) + float mask; +#endif +}; + +static const float2 glitter_offset_vectors[6] = { + float2(0.0, 1.0), // 0 degrees + float2(0.866025, 0.5), // 60 degrees + float2(0.866025, -0.5), // 120 degrees + float2(0.0, -1.0), // 180 degrees + float2(-0.866025, -0.5), // 240 degrees + float2(-0.866025, 0.5) // 300 degrees +}; + + +float4 getGlitter(v2f i, GlitterParams params, float3 normal) { + float c_acc = 0; + [loop] + for (uint layer_i = 0; layer_i < params.layers; layer_i++) { + float2 p = i.uv01.xy + glitter_offset_vectors[layer_i] * params.cell_size * 0.5; + + float3 cell_id = float3(floor(p / params.cell_size), layer_i); + float cell_rand = rand3(cell_id*.0001); + float cell_rand2 = rand3((cell_id+1)*.0001); + p = glsl_mod(p, params.cell_size); + p -= params.cell_size * 0.5; + // Apply center randomization + p.x += (cell_rand * 2 - 1) * params.center_randomization_range * (params.cell_size * (1 - params.size)) * 0.5; + // Apply angle randomization + float2x2 p_rot = float2x2( + cos(cell_rand * TAU * params.angle_randomization_range), -sin(cell_rand * TAU * params.angle_randomization_range), + sin(cell_rand * TAU * params.angle_randomization_range), cos(cell_rand * TAU * params.angle_randomization_range) + ); + p = mul(p_rot, p); + + // Draw ellipses + // First arg is position to evaluate distance at. We project onto z=0. + // Second arg is the size of the ellipse. We set z to cell size because I + // think setting it to 0 would probably create fucked up curvature. + float3 size = float3(params.size * float2(params.major_minor_ratio, 1) * params.cell_size * 0.5, params.cell_size); + // Apply size randomization + size *= (1 - cell_rand * params.size_randomization_range); + // TODO find a good 2d ellipse sdf + float d = distance_from_ellipsoid(float3(p, 0), size); + // TODO antialias using fwidth + float c = (d < 0) * params.color.a; + c *= (cell_rand2 < params.existence_chance); + c_acc = c + (1 - c) * c_acc; + } +#if defined(_GLITTER_ANGLE_LIMIT) + float VdotN = dot(-i.eyeVec.xyz, normal); + float angle_mask = smoothstep( + cos(params.angle_limit * PI), + cos(params.angle_limit * (1 - params.angle_limit_transition_width) * PI), + VdotN); + c_acc *= angle_mask; +#endif +#if defined(_GLITTER_MASK) + c_acc *= params.mask; +#endif + return float4(params.color.rgb, c_acc); +} + +#endif // __GLITTER_INC + + -- cgit v1.2.3