Randoloot/resources/effects/ship_fireball.gdshader
2026-10-14 22:30:56 +02:00

51 lines
1.9 KiB
Plaintext

shader_type canvas_item;
render_mode unshaded, blend_add;
uniform float phase = 0.0;
uniform float variation = 0.0;
uniform float strength = 1.0;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);
vec2 u = f * f * (3.0 - 2.0 * f);
return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), u.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0)), u.x), u.y);
}
float fbm(vec2 p) {
float value = 0.0;
float weight = 0.5;
for (int i = 0; i < 5; i++) {
value += noise(p) * weight;
p = mat2(vec2(1.6, 1.2), vec2(-1.2, 1.6)) * p + vec2(17.0, 9.0);
weight *= 0.5;
}
return value;
}
void fragment() {
vec2 p = (UV - vec2(0.5)) * 2.0;
float radius = length(p);
float age = max(phase, 0.0);
float expansion = 0.16 + 0.44 * (1.0 - exp(-age * 7.0));
vec2 flow = p * 5.0 / max(expansion, 0.12);
flow += vec2(variation, -age * 3.2);
vec2 warp = vec2(fbm(flow + vec2(age * 1.3, 0.0)), fbm(flow + vec2(8.0, -age)));
float turbulence = fbm(flow + warp * 3.0);
float edge = expansion * (0.65 + turbulence * 0.65);
float body = 1.0 - smoothstep(edge * 0.58, edge, radius);
float fade = 1.0 - smoothstep(0.35, 1.3, age);
float heat = clamp(body * (0.35 + turbulence * 0.9) * exp(-age * 1.0), 0.0, 1.0);
vec3 fire = mix(vec3(0.85, 0.12, 0.015), vec3(1.0, 0.52, 0.035), smoothstep(0.08, 0.35, heat));
fire = mix(fire, vec3(1.0, 0.88, 0.46), smoothstep(0.3, 0.6, heat));
fire = mix(fire, vec3(1.0, 0.98, 0.88), smoothstep(0.6, 0.9, heat));
float glow = exp(-radius * radius / max(0.02, expansion * expansion * 0.85)) * 0.11 * exp(-age * 3.5);
float flash = exp(-radius * radius * 35.0) * exp(-age * 26.0);
vec3 light = fire * body * fade * (0.5 + turbulence) + vec3(1.0, 0.25, 0.035) * glow + vec3(1.0, 0.97, 0.85) * flash;
COLOR = vec4(light * strength, clamp((body * fade + glow + flash) * strength, 0.0, 1.0));
}