65 lines
2.6 KiB
GLSL
65 lines
2.6 KiB
GLSL
#version 450 core
|
|
#include "common.glsl"
|
|
// Premultiplied output: glows and fire write alpha 0 (pure additive), sparks
|
|
// and smoke write coverage (alpha-blended). Blend func is ONE, ONE_MINUS_SRC_ALPHA.
|
|
|
|
in vec2 vUV;
|
|
in vec4 vColor;
|
|
flat in int vKind;
|
|
in vec2 vLifeSeed;
|
|
|
|
layout(location = 0) out vec4 fragColor;
|
|
|
|
void main() {
|
|
vec2 p = vUV * 2.0 - 1.0;
|
|
float r = length(p);
|
|
float life = vLifeSeed.x, seed = vLifeSeed.y;
|
|
|
|
if (vKind == 2) { // spark / droplet
|
|
float a = (1.0 - smoothstep(0.6, 1.0, r)) * vColor.a;
|
|
fragColor = vec4(vColor.rgb * a, a);
|
|
return;
|
|
}
|
|
if (vKind == 3) {
|
|
// Flame lick: a soft-topped blob with a crisp, noise-eroded silhouette,
|
|
// shaded from a hot yellow center to orange and a red rim; it reddens
|
|
// and erodes as it rises. Nearly opaque (HD-2D fires read as solid,
|
|
// painterly shapes), emissive HDR so the core blooms.
|
|
float taper = 1.0 + 0.45 * (p.y * 0.5 + 0.5);
|
|
float d = length(vec2(p.x * taper, p.y * 0.8 + 0.1));
|
|
vec2 q = vec2(p.x * 1.8, p.y * 1.5 - uTime * 2.6) + seed * 37.0;
|
|
float n = vnoise(q) * 0.7 + vnoise(q * 2.4 + 11.0) * 0.3;
|
|
float e = d + (n - 0.5) * (0.35 + 0.7 * life);
|
|
float body = 1.0 - smoothstep(0.62, 0.76, e);
|
|
if (body <= 0.0) discard;
|
|
// Young licks stay hot right to their rim so the mass merges into one
|
|
// bright body; only older, higher licks get the red edge.
|
|
float heat = clamp((1.0 - e / 0.72) * 1.35 + 0.25 * (1.0 - life), 0.0, 1.0) * (1.0 - 0.65 * life);
|
|
vec3 red = vec3(0.8, 0.1, 0.02), orange = vec3(1.8, 0.5, 0.06), yellow = vec3(2.3, 1.4, 0.32);
|
|
vec3 c = heat < 0.5 ? mix(red, orange, heat * 2.0) : mix(orange, yellow, heat * 2.0 - 1.0);
|
|
float a = body * vColor.a;
|
|
fragColor = vec4(c * vColor.rgb * a, a * 0.92);
|
|
return;
|
|
}
|
|
if (vKind == 4) { // ember
|
|
float core = exp(-r * r * 10.0);
|
|
fragColor = vec4(vColor.rgb * vColor.a * core, 0.0);
|
|
return;
|
|
}
|
|
if (vKind == 5) { // smoke puff
|
|
vec2 q = p * 1.6 + seed * 23.0 + vec2(0.0, -uTime * 0.3);
|
|
float n = vnoise(q) * 0.6 + vnoise(q * 2.1 + 5.0) * 0.4;
|
|
float a = (1.0 - smoothstep(0.2, 1.0, r + (n - 0.5) * 0.7)) * vColor.a;
|
|
fragColor = vec4(vColor.rgb * a, a);
|
|
return;
|
|
}
|
|
if (vKind == 6) { // fire glow halo
|
|
float g = exp(-r * r * 3.5) - 0.03;
|
|
fragColor = vec4(vColor.rgb * max(g, 0.0), 0.0);
|
|
return;
|
|
}
|
|
float core = 1.0 - smoothstep(0.0, 0.2, r);
|
|
float halo = exp(-r * r * 9.0) * 0.45;
|
|
fragColor = vec4(vColor.rgb * vColor.a * (core * 1.5 + halo), 0.0);
|
|
}
|