
Show HN: WebGL Fire Simulation - jharsman
http://ghostinthecode.net/2016/08/17/fire.html
======
kbirk
Nothing will ever impress me more than this WebGL fire / explosion effect:
[http://glslsandbox.com/e#33550.0](http://glslsandbox.com/e#33550.0)

Warning: may melt your GPU.

~~~
Silhouette
_Warning: may melt your GPU._

You're not wrong. That put a workstation-class GPU in a water-cooled system up
about 20 degrees C within a few seconds. And it was _still_ not fast enough to
animate smoothly during the more demanding parts later in the sequence.

Awesome effect, though. :-)

------
jstsch
Did something similar a few years ago... a port of the classic demo effect to
JS/Canvas :) [https://jstsch.com/post/old-
skool_fire_demo_effect_in_javasc...](https://jstsch.com/post/old-
skool_fire_demo_effect_in_javascriptcanvas)

------
velcro
Takes me back to the time of Netscape 2.0 where webpages were not complete
without a fire.gif background :)

BTW did a pure CSS3 fire a while ago too:
[http://pag.es/fire/test.html](http://pag.es/fire/test.html)

------
s-macke
If you want to see fire based on real fluid dynamics take a look at Ron
Fedkiw's site:
[http://physbam.stanford.edu/~fedkiw/](http://physbam.stanford.edu/~fedkiw/)

For example the following video:
[http://physbam.stanford.edu/~fedkiw/animations/fireball.avi](http://physbam.stanford.edu/~fedkiw/animations/fireball.avi)

------
andypants
Parts of it look way too noisy, like TV static.

~~~
jharsman
Yes, the actual burning fuel part is just random noise, which doesn't look
very very good. I mention it as a possible imrpovement under "Better looking
fuel".

------
heywire
I remember doing something similar in x86 assembly back in the 90's. int 10h
comes to mind.

~~~
acz
Oh me too, was fun and surprisingly not difficult. Still remember learning
cool tricks from the Hugi demoscene diskmag.

------
kruhft
Having fun playing with fire:

[https://twitter.com/kruhft/status/766304583924592640](https://twitter.com/kruhft/status/766304583924592640)

------
CommanderData
Looks like Runescape fire.

------
WhitneyLand
Nice work. Effects like these are a great example of programmers combining
theory, art, and creative optimizations.

------
steaminghacker
do you have a shadertoy version of this for comparison?

i took this one by ozzy
[https://www.shadertoy.com/view/lsSGWw](https://www.shadertoy.com/view/lsSGWw)
and tweaked a few things by hand for optimization. saved a few cycles on the
code and increased the iterations to 13, which gives a better result.

like this:

#define ITERATIONS 13.0 #define SPEED 10.0 #define DISPLACEMENT 0.05 #define
YOFFSET 0.1 #define YSCALE 0.25 #define FLAMETONE vec3(50.0, 5.0, 1.0)

    
    
            uniform lowp sampler2D source; // this item
            uniform lowp sampler2D chan0; // random map
            uniform lowp float qt_Opacity; // inherited opacity of this item
            varying highp vec2 qt_TexCoord0;
            uniform highp float    time;           // shader playback time (in seconds)
    
            float noise( in vec3 x ) // iq noise function
            {
    	        vec3 p = floor(x);
                vec3 f = fract(x);
    	        f = f*f*(3.0-2.0*f);
    	        vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
    	        vec2 rg = texture2D( chan0, (uv + 0.5)/256.0, -100.0 ).yx;
    	        return mix( rg.x, rg.y, f.z ) * 2.0 - 1.0;
            }
    
            void main()
            {
    	        vec2 uv = vec2(qt_TexCoord0.s, (1.0 - qt_TexCoord0.t));
    	        float nx = 0.0;
    	        float ny = 0.0;
                float i;
    
    	        for (i=1.0; i<=ITERATIONS; i = i + 1.0)
    	        {
    		        float ifrac = i/ITERATIONS;
    		        float d = (1.0-ifrac) * DISPLACEMENT;
                    ifrac *= time;
    		        float ii = i*i;
                    float y = uv.y*YSCALE*ii - ifrac * SPEED;
                    float x = uv.x*ii;
    		        nx += noise( vec3(x-ifrac, y, 0.0)) * d * 2.0;
    		        ny += noise( vec3(x+ifrac, y, ifrac/ii)) * d;
    	        }
    
                uv.x += nx;
                uv.y += ny;
    
                // a blob shape to distort
    	        float flame = clamp( sin(uv.x*3.1416) - uv.y+YOFFSET, 0.0, 1.0 );            
                flame *= flame; // f^2
                float ft = flame*flame; // f^4
                flame *= ft*ft; // f^10
                
    	        //lowp vec3 col = pow(flame, TIGHTNESS) * FLAMETONE;
    	        lowp vec3 col = flame * FLAMETONE;
                
                // tonemapping
                col = col / (1.0+col);
                
                // ~sqrt
                //col = pow(col, vec3(1.0/2.2));
                col = sqrt(col);
    
                col = clamp(col, 0.0, 1.0);
                
                lowp vec4 p = texture2D(source, qt_TexCoord0);
                p.xyz = col;
                gl_FragColor = p * qt_Opacity;
            }

~~~
jharsman
I can't get your example code to work, but that is a completely different
technique, ray marching a volume displaced by a noise function. This gives
nice 3D-looking flames, but the movement tends to look like a scrolling noise
function. And it's harder to use arbitrary burning shapes, my simulation
supports drawing anything and it will burn.

~~~
steaminghacker
Sorry, this version wont just paste back as is in shadertoy. Also it needs a
random 256x256 bitmap in channel 0. The effect is the same as ozzy's original,
except change ITERATIONS to 13 in his code to see the change (which is only
slightly better). The other changes were for performance, which i improved
slightly.

------
mirimir
Is there any way to see the result without WebGL?

------
uwu
can i have this for selected text?

