#version 300 es // procedural rime — no texture asset. ridged value noise gives the cracked-crystal look, a radial // falloff carves the square quad into a disc, and the whole thing rides the ADDITIVE path (a custom // material is ignored on the ALPHA path, which is why this glows rather than tints) precision highp float; in highp vec3 vWorldPos; in highp vec3 vCenter; in vec4 vColor; in float vEmissive; in float vRadius; #include "_graphics_uniforms.glsl" out vec4 fragColor; float hash21(vec2 p) { p = fract(p * vec2(123.34, 456.21)); p += dot(p, p + 45.32); return fract(p.x * p.y); } float vnoise(vec2 p) { vec2 i = floor(p); vec2 f = fract(p); f = f * f * (3.0 - 2.0 * f); float a = hash21(i); float b = hash21(i + vec2(1.0, 0.0)); float c = hash21(i + vec2(0.0, 1.0)); float d = hash21(i + vec2(1.0, 1.0)); return mix(mix(a, b, f.x), mix(c, d, f.x), f.y); } // ridged: the creases between noise cells read as frost fractures float ridged(vec2 p) { return 1.0 - abs((vnoise(p) * 2.0) - 1.0); } void main() { vec2 d = vWorldPos.xy - vCenter.xy; float dist = length(d) / max(vRadius, 0.0001); if (dist > 1.0) discard; // two octaves, second one rotated so the cells do not line up into a grid vec2 p = vWorldPos.xy; float n = ridged(p * 1.7) * 0.65 + ridged(p * 4.3 + vec2(31.7, 11.3)) * 0.35; n = pow(n, 3.0); // squeeze it to thin bright veins instead of an even wash // fade at the rim, and thin the crust toward it so the patch has no hard edge float edge = 1.0 - smoothstep(0.55, 1.0, dist); float a = n * edge; fragColor = vec4(vColor.rgb * (a * vEmissive), 1.0); }