Skip to content
Snippets Groups Projects
index.html 8.25 KiB
Newer Older
  • Learn to ignore specific revisions
  • amandaghassaei's avatar
    amandaghassaei committed
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Fluid Simulation</title>
    
        <link rel="stylesheet" type="text/css" href="dependencies/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="dependencies/flat-ui.min.css">
        <link rel="stylesheet" type="text/css" href="main.css">
    
        <script id="2d-vertex-shader" type="x-shader/x-vertex">
    
            attribute vec2 a_position;
    
            void main() {
               gl_Position = vec4(a_position, 0, 1);
            }
        </script>
    
        <script id="2d-render-shader" type="x-shader/x-fragment">
            precision mediump float;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform sampler2D u_material;
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform vec2 u_textureSize;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
            void main() {
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 fragCoord = gl_FragCoord.xy;
    
    amandaghassaei's avatar
    amandaghassaei committed
                gl_FragColor = vec4(texture2D(u_material, fragCoord/u_textureSize).x, 0, 1, 1);
    
    amandaghassaei's avatar
    amandaghassaei committed
            }
        </script>
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        <script id="gradientSubtractionShader" type="x-shader/x-fragment">
            precision mediump float;
    
            uniform sampler2D u_velocity;
            uniform sampler2D u_pressure;
    
            uniform vec2 u_textureSize;
    
            uniform float u_const;
    
            void main() {
    
                vec2 fragCoord = gl_FragCoord.xy;
    
                vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;
    
                float n = texture2D(u_pressure, (fragCoord+vec2(0.0, 1.0))/u_textureSize).x;
                float s = texture2D(u_pressure, (fragCoord+vec2(0.0, -1.0))/u_textureSize).x;
                float e = texture2D(u_pressure, (fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
                float w = texture2D(u_pressure, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;
    
                gl_FragColor = vec4(currentVelocity-u_const*vec2(e-w, n-s), 0, 0);
            }
        </script>
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        <script id="divergenceShader" type="x-shader/x-fragment">
            precision mediump float;
    
            uniform sampler2D u_velocity;
    
            uniform vec2 u_textureSize;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform float u_const;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
            void main() {
    
                vec2 fragCoord = gl_FragCoord.xy;
    
                //finite difference formulation of divergence
    
                float n = texture2D(u_velocity, (fragCoord+vec2(0.0, 1.0))/u_textureSize).y;
                float s = texture2D(u_velocity, (fragCoord+vec2(0.0, -1.0))/u_textureSize).y;
                float e = texture2D(u_velocity, (fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
                float w = texture2D(u_velocity, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
                float div = u_const*(e-w + n-s);
                gl_FragColor = vec4(div, div, 0, 0);
    
    amandaghassaei's avatar
    amandaghassaei committed
            }
        </script>
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        <script id="forceShader" type="x-shader/x-fragment">
            precision mediump float;
    
            uniform sampler2D u_velocity;
    
            uniform vec2 u_textureSize;
    
            uniform vec2 u_mouseCoord;
            uniform vec2 u_mouseDir;
            uniform float u_mouseEnable;
    
            uniform float u_dt;
    
            const float reciprocalRadius = 0.01;
    
            void main() {
    
                vec2 fragCoord = gl_FragCoord.xy;
    
                vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;
    
                if (u_mouseEnable == 1.0){
                    vec2 pxDist = fragCoord - u_mouseCoord;
                    currentVelocity += u_mouseDir*u_dt*exp(-(pxDist.x*pxDist.x+pxDist.y*pxDist.y)*reciprocalRadius);
                }
    
                gl_FragColor = vec4(currentVelocity, 0, 0);
            }
        </script>
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        <script id="jacobiShader" type="x-shader/x-fragment">
    
    amandaghassaei's avatar
    amandaghassaei committed
            precision mediump float;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform sampler2D u_b;
            uniform sampler2D u_x;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
            uniform vec2 u_textureSize;
    
            uniform float u_alpha;
            uniform float u_reciprocalBeta;
    
            void main() {
    
                vec2 fragCoord = gl_FragCoord.xy;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 currentState = texture2D(u_b, fragCoord/u_textureSize).xy;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
                //implicitly solve diffusion via jacobi iteration
    
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 n = texture2D(u_x, (fragCoord+vec2(0.0, 1.0))/u_textureSize).xy;
                vec2 s = texture2D(u_x, (fragCoord+vec2(0.0, -1.0))/u_textureSize).xy;
                vec2 e = texture2D(u_x, (fragCoord+vec2(1.0, 0.0))/u_textureSize).xy;
                vec2 w = texture2D(u_x, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).xy;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
                vec2 nextState = (n + s + e + w + u_alpha * currentState) * u_reciprocalBeta;
    
                gl_FragColor = vec4(nextState, 0, 0);
            }
    
    amandaghassaei's avatar
    amandaghassaei committed
       </script>
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        <script id="advectShader" type="x-shader/x-fragment">
    
    amandaghassaei's avatar
    amandaghassaei committed
            precision mediump float;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform sampler2D u_velocity;
            uniform sampler2D u_material;
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform vec2 u_textureSize;
    
    amandaghassaei's avatar
    amandaghassaei committed
            uniform float u_dt;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
            void main() {
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 fragCoord = gl_FragCoord.xy;
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
                //implicitly solve advection
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
                if (length(currentVelocity) == 0.0) {//no velocity
    
    amandaghassaei's avatar
    amandaghassaei committed
                    gl_FragColor = vec4(texture2D(u_material, fragCoord/u_textureSize).xy, 0, 0);
    
    amandaghassaei's avatar
    amandaghassaei committed
                    return;
                }
    
                vec2 pxCenter = vec2(0.5, 0.5);
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 pos = fragCoord - pxCenter - u_dt*currentVelocity;
    
    amandaghassaei's avatar
    amandaghassaei committed
                //if (pos.x < 0.0 || pos.x >= u_textureSize.x-1.0 || pos.y < 0.0 || pos.y >= u_textureSize.y-1.0){
                //    //boundary
                //    gl_FragColor = vec4(0);
                //    return;
                //}
                //periodic boundary
                if (pos.x < 0.0) pos.x += u_textureSize.x-1.0;
                if (pos.x >= u_textureSize.x-1.0) pos.x -= u_textureSize.x-1.0;
                if (pos.y < 0.0) pos.y += u_textureSize.y-1.0;
                if (pos.y >= u_textureSize.y-1.0) pos.y -= u_textureSize.y-1.0;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
                //bilinear interp between nearest cells
                vec2 ceiled = ceil(pos);
                vec2 floored = floor(pos);
    
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 n = texture2D(u_material, (ceiled+pxCenter)/u_textureSize).xy;//actually ne
                vec2 s = texture2D(u_material, (floored+pxCenter)/u_textureSize).xy;//actually sw
    
    amandaghassaei's avatar
    amandaghassaei committed
                if (ceiled.x != floored.x){
    
    amandaghassaei's avatar
    amandaghassaei committed
                    vec2 se = texture2D(u_material, (vec2(ceiled.x, floored.y)+pxCenter)/u_textureSize).xy;
                    vec2 nw = texture2D(u_material, (vec2(floored.x, ceiled.y)+pxCenter)/u_textureSize).xy;
    
    amandaghassaei's avatar
    amandaghassaei committed
                    n = n*(pos.x-floored.x) + nw*(ceiled.x-pos.x);
                    s = se*(pos.x-floored.x) + s*(ceiled.x-pos.x);
                }
    
    amandaghassaei's avatar
    amandaghassaei committed
                vec2 materialVal = n;
    
    amandaghassaei's avatar
    amandaghassaei committed
                if (ceiled.y != floored.y){
                    materialVal = n*(pos.y-floored.y) + s*(ceiled.y-pos.y);
                }
    
    
    amandaghassaei's avatar
    amandaghassaei committed
                gl_FragColor = vec4(materialVal, 0, 0);
    
    amandaghassaei's avatar
    amandaghassaei committed
            }
        </script>
    
        <script type="text/javascript" src="dependencies/jquery-3.1.0.min.js"></script>
        <script type="text/javascript" src="dependencies/flat-ui.min.js"></script>
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        <script type="text/javascript" src="GLBoilerplate.js"></script>
        <script type="text/javascript" src="GPUMath.js"></script>
    
    amandaghassaei's avatar
    amandaghassaei committed
        <script type="text/javascript" src="main.js"></script>
    </head>
    <body>
    
    <canvas id="glcanvas"></canvas>
    
    <a href="#" id="about">?</a>
    
    <div class="modal fade" id="aboutModal" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-body">
                    <b>Fluid Simulation Shader</b><br/><br/>
    
    amandaghassaei's avatar
    amandaghassaei committed
                    I used the following sources to write this simulation:<br/><br/>
    
    amandaghassaei's avatar
    amandaghassaei committed
                    <a href="https://pdfs.semanticscholar.org/84b8/c7b7eecf90ebd9d54a51544ca0f8ff93c137.pdf" target="_blank">Real-time ink simulation using a grid-particle method</a> - a method for real-time simulation of ink
                    in water using a coarse-grained fluid simulation with a particle simulation on top.<br/>
    
    amandaghassaei's avatar
    amandaghassaei committed
                    <a href="http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html" target="_blank">Fast Fluid Dynamics Simulation on the GPU</a> - a very well written tutorial about programming the Navier-Stokes equations on a GPU.<br/>
    
    amandaghassaei's avatar
    amandaghassaei committed
                    <a href="http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf" target="_blank">Stable Fluids</a> - a paper about stable numerical methods for evaluating Navier-Stokes on a discrete grid.<br/>
    
    amandaghassaei's avatar
    amandaghassaei committed
                    <br/>
                    By <a href="http://www.amandaghassaei.com/" target="_blank">Amanda Ghassaei</a>, code on <a href="https://github.com/amandaghassaei/FluidSimulation" target="_blank">Github</a>.
    
    amandaghassaei's avatar
    amandaghassaei committed
                    <br/><br/>
                </div>
            </div>
        </div>
    </div>
    
    </body>
    </html>