shader_type canvas_item; render_mode unshaded; uniform float age = 0.0; uniform float seed_phase = 0.0; float hash(vec2 p) { p=fract(p*vec2(123.34,456.21)); p+=dot(p,p+45.32); return fract(p.x*p.y); } float noise(vec2 p) { vec2 i=floor(p), f=fract(p); f=f*f*(3.0-2.0*f); return mix(mix(hash(i),hash(i+vec2(1,0)),f.x),mix(hash(i+vec2(0,1)),hash(i+vec2(1)),f.x),f.y); } float fbm(vec2 p) { return noise(p)*0.55+noise(p*2.1+7.3)*0.28+noise(p*4.3+12.1)*0.14; } void fragment() { vec2 p=vec2(UV.x,UV.y-0.5); float n=fbm(p*vec2(8,10)+vec2(-age*6.0,seed_phase)); float x=p.x-0.09; float flare=max(0.0,1.0-age/0.19); float width=0.025+sin(clamp(x/0.8,0.0,1.0)*3.14159)*0.14; float jet=(1.0-smoothstep(width*0.4,width,abs(p.y)+(n-0.5)*0.07)); jet*=smoothstep(-0.02,0.025,x)*(1.0-smoothstep(0.4,0.85,x)); jet*=flare; float smoke_radius=0.11+age*0.24; vec2 center=vec2(0.19+age*0.25,-age*0.025); float smoke_edge=length((p-center)/vec2(smoke_radius*1.7,smoke_radius))+(n-0.5)*0.55; float smoke=(1.0-smoothstep(0.55,1.15,smoke_edge))*smoothstep(0.015,0.12,age)*(1.0-smoothstep(0.45,1.2,age)); smoke*=smoothstep(0.0,0.12,UV.x)*(1.0-smoothstep(0.9,1.0,UV.x)); vec3 smoke_color=mix(vec3(0.055,0.06,0.065),vec3(0.32,0.29,0.25),n); float heat=clamp(jet*0.68+n*0.24,0.0,1.0); vec3 fire=mix(vec3(1.0,0.14,0.005),vec3(1.5,0.85,0.23),heat); fire=mix(fire,vec3(1.8,1.55,0.95),pow(heat,5.0)); COLOR=vec4(mix(smoke_color,fire,smoothstep(0.01,0.3,jet)),max(smoke*0.65,jet)); }