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)); }