summaryrefslogtreecommitdiffstats
path: root/glitter.cginc
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-02-26 01:18:09 -0800
committeryum <yum.food.vr@gmail.com>2025-02-26 01:18:19 -0800
commit0264f5e767b0b54e82b7c11457b491be555be577 (patch)
tree4a31a90956b167c959eb8f45328719384a19ac89 /glitter.cginc
parent6017d2d8bad7dde020121259cba5cb614c11f761 (diff)
Add glitter and more masked stencil channels
Diffstat (limited to 'glitter.cginc')
-rw-r--r--glitter.cginc87
1 files changed, 87 insertions, 0 deletions
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
+
+