Skip to content
Snippets Groups Projects
main.js 7.48 KiB
Newer Older
  • Learn to ignore specific revisions
  • amandaghassaei's avatar
    amandaghassaei committed
    //used a lot of ideas from https://bl.ocks.org/robinhouston/ed597847175cf692ecce to clean this code up
    
    
    amandaghassaei's avatar
    amandaghassaei committed
    var width, height;
    
    amandaghassaei's avatar
    amandaghassaei committed
    var body;
    var scale = 4;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
    var lastMouseCoordinates =  [0,0];
    var mouseCoordinates =  [0,0];
    
    amandaghassaei's avatar
    amandaghassaei committed
    var mouseEnable = false;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    var paused = false;//while window is resizing
    
    
    amandaghassaei's avatar
    amandaghassaei committed
    var dt = 1;
    var dx = 1;
    var nu = 1;//viscosity
    
    amandaghassaei's avatar
    amandaghassaei committed
    var rho = 1;//density
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
    var GPU;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
    window.onload = initGL;
    
    function initGL() {
    
        $("#about").click(function(e){
            e.preventDefault();
            $("#aboutModal").modal('show');
        });
    
        canvas = document.getElementById("glcanvas");
    
    amandaghassaei's avatar
    amandaghassaei committed
        body = document.getElementsByTagName("body")[0];
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        canvas.onmousemove = onMouseMove;
        canvas.onmousedown = onMouseDown;
    
    amandaghassaei's avatar
    amandaghassaei committed
        canvas.onmouseup = onMouseUp;
    
    amandaghassaei's avatar
    amandaghassaei committed
        canvas.onmouseout = onMouseUp;
    
        window.onresize = onResize;
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU = initGPUMath();
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        // setup a GLSL programs
        GPU.createProgram("advect", "2d-vertex-shader", "advectShader");
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("advect", "u_dt", dt, "1f");
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("advect", "u_velocity", 0, "1i");
        GPU.setUniformForProgram("advect", "u_material", 1, "1i");
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.createProgram("gradientSubtraction", "2d-vertex-shader", "gradientSubtractionShader");
        GPU.setUniformForProgram("gradientSubtraction", "u_const", 0.5/dx, "1f");//dt/(2*rho*dx)
        GPU.setUniformForProgram("gradientSubtraction", "u_velocity", 0, "1i");
        GPU.setUniformForProgram("gradientSubtraction", "u_pressure", 1, "1i");
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.createProgram("diverge", "2d-vertex-shader", "divergenceShader");
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("diverge", "u_const", 0.5/dx, "1f");//-2*dx*rho/dt
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("diverge", "u_velocity", 0, "1i");
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.createProgram("force", "2d-vertex-shader", "forceShader");
        GPU.setUniformForProgram("force", "u_dt", dt, "1f");
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("force", "u_reciprocalRadius", 0.1*scale, "1f");
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("force", "u_velocity", 0, "1i");
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.createProgram("jacobi", "2d-vertex-shader", "jacobiShader");
        GPU.setUniformForProgram("jacobi", "u_b", 0, "1i");
        GPU.setUniformForProgram("jacobi", "u_x", 1, "1i");
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.createProgram("render", "2d-vertex-shader", "2d-render-shader");
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setUniformForProgram("render", "u_material", 0, "1i");
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        resetWindow();
    
        render();
    }
    
    function render(){
    
        if (!paused) {
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            //advect velocity
            GPU.step("advect", ["velocity", "velocity"], "nextVelocity");
    
    amandaghassaei's avatar
    amandaghassaei committed
            GPU.swapTextures("velocity", "nextVelocity");
    
    amandaghassaei's avatar
    amandaghassaei committed
    
            //diffuse velocity
    
    amandaghassaei's avatar
    amandaghassaei committed
            GPU.setProgram("jacobi");
            var alpha = dx*dx/(nu*dt);
            GPU.setUniformForProgram("jacobi", "u_alpha", alpha, "1f");
            GPU.setUniformForProgram("jacobi", "u_reciprocalBeta", 1/(4+alpha), "1f");
    
    amandaghassaei's avatar
    amandaghassaei committed
            for (var i=0;i<2;i++){
    
    amandaghassaei's avatar
    amandaghassaei committed
                GPU.step("jacobi", ["velocity", "velocity"], "nextVelocity");
                GPU.step("jacobi", ["nextVelocity", "nextVelocity"], "velocity");
    
    amandaghassaei's avatar
    amandaghassaei committed
            }
    
    amandaghassaei's avatar
    amandaghassaei committed
    
            //apply force
    
    amandaghassaei's avatar
    amandaghassaei committed
            GPU.setProgram("force");
            if (mouseEnable){
                GPU.setUniformForProgram("force", "u_mouseEnable", 1.0, "1f");
                GPU.setUniformForProgram("force", "u_mouseCoord", [mouseCoordinates[0], mouseCoordinates[1]], "2f");
                GPU.setUniformForProgram("force", "u_mouseDir", [mouseCoordinates[0]-lastMouseCoordinates[0],
                    mouseCoordinates[1]-lastMouseCoordinates[1]], "2f");
            } else {
                GPU.setUniformForProgram("force", "u_mouseEnable", 0.0, "1f");
            }
            GPU.step("force", ["velocity"], "nextVelocity");
            GPU.swapTextures("velocity", "nextVelocity");
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            // compute pressure
    
    amandaghassaei's avatar
    amandaghassaei committed
            GPU.step("diverge", ["velocity"], "velocityDivergence");//calc velocity divergence
    
    amandaghassaei's avatar
    amandaghassaei committed
            GPU.setProgram("jacobi");
            GPU.setUniformForProgram("jacobi", "u_alpha", -dx*dx, "1f");
            GPU.setUniformForProgram("jacobi", "u_reciprocalBeta", 1/4, "1f");
            for (var i=0;i<20;i++){
    
    amandaghassaei's avatar
    amandaghassaei committed
                GPU.step("jacobi", ["velocityDivergence", "pressure"], "nextPressure");//diffuse velocity
                GPU.step("jacobi", ["velocityDivergence", "nextPressure"], "pressure");//diffuse velocity
            }
    
    
    amandaghassaei's avatar
    amandaghassaei committed
            // subtract pressure gradient
            GPU.step("gradientSubtraction", ["velocity", "pressure"], "nextVelocity");
            GPU.swapTextures("velocity", "nextVelocity");
    
    amandaghassaei's avatar
    amandaghassaei committed
            // GPU.step("diffuse", ["material"], "nextMaterial");
            GPU.step("advect", ["velocity", "material"], "nextMaterial");
            GPU.step("render", ["nextMaterial"]);
            GPU.swapTextures("nextMaterial", "material");
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        } else resetWindow();
    
        window.requestAnimationFrame(render);
    }
    
    function onResize(){
        paused = true;
    }
    
    function resetWindow(){
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        width = Math.floor(body.clientWidth/scale);
        height = Math.floor(body.clientHeight/scale);
    
        canvas.width = width;
        canvas.height = height;
        canvas.clientWidth = body.clientWidth;
        canvas.clientHeight = body.clientHeight;
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setSize(width, height);
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.setProgram("advect");
        GPU.setUniformForProgram("advect" ,"u_textureSize", [width, height], "2f");
        GPU.setProgram("gradientSubtraction");
        GPU.setUniformForProgram("gradientSubtraction" ,"u_textureSize", [width, height], "2f");
        GPU.setProgram("diverge");
        GPU.setUniformForProgram("diverge" ,"u_textureSize", [width, height], "2f");
        GPU.setProgram("force");
        GPU.setUniformForProgram("force" ,"u_textureSize", [width, height], "2f");
        GPU.setProgram("jacobi");
        GPU.setUniformForProgram("jacobi" ,"u_textureSize", [width, height], "2f");
        GPU.setProgram("render");
        GPU.setUniformForProgram("render" ,"u_textureSize", [width, height], "2f");
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        var velocity = new Float32Array(width*height*4);
    
    amandaghassaei's avatar
    amandaghassaei committed
        // for (var i=0;i<height;i++){
        //     for (var j=0;j<width;j++){
        //         var index = 4*(i*width+j);
        //         velocity[index] = Math.sin(2*Math.PI*i/200)/10;
        //         velocity[index+1] = Math.sin(2*Math.PI*j/200)/10;
        //     }
        // }
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initTextureFromData("velocity", width, height, "FLOAT", velocity, true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initFrameBufferForTexture("velocity", true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initTextureFromData("nextVelocity", width, height, "FLOAT", new Float32Array(width*height*4), true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initFrameBufferForTexture("nextVelocity", true);
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        GPU.initTextureFromData("velocityDivergence", width, height, "FLOAT", new Float32Array(width*height*4), true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initFrameBufferForTexture("velocityDivergence", true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initTextureFromData("pressure", width, height, "FLOAT", new Float32Array(width*height*4), true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initFrameBufferForTexture("pressure", true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initTextureFromData("nextPressure", width, height, "FLOAT", new Float32Array(width*height*4), true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initFrameBufferForTexture("nextPressure", true);
    
    amandaghassaei's avatar
    amandaghassaei committed
    
    
    amandaghassaei's avatar
    amandaghassaei committed
        var material = new Float32Array(width*height*4);
    
    amandaghassaei's avatar
    amandaghassaei committed
        for (var i=0;i<height;i++){
            for (var j=0;j<width;j++){
                var index = 4*(i*width+j);
    
    amandaghassaei's avatar
    amandaghassaei committed
                if (((Math.floor(i/10))%2 && (Math.floor(j/10))%2)
                    || ((Math.floor(i/10))%2 == 0 && (Math.floor(j/10))%2 == 0)) material[index] = 1.0;
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initTextureFromData("material", width, height, "FLOAT", material, true);
    
    amandaghassaei's avatar
    amandaghassaei committed
        GPU.initFrameBufferForTexture("material", true);
        GPU.initTextureFromData("nextMaterial", width, height, "FLOAT", material, true);
        GPU.initFrameBufferForTexture("nextMaterial", true);
    
    amandaghassaei's avatar
    amandaghassaei committed
    
        paused = false;
    }
    
    function onMouseMove(e){
    
    amandaghassaei's avatar
    amandaghassaei committed
        lastMouseCoordinates = mouseCoordinates;
    
    amandaghassaei's avatar
    amandaghassaei committed
        mouseCoordinates = [e.clientX/scale, (body.clientHeight-e.clientY)/scale];
    
    amandaghassaei's avatar
    amandaghassaei committed
    }
    
    
    amandaghassaei's avatar
    amandaghassaei committed
    function onMouseDown(){
    
    amandaghassaei's avatar
    amandaghassaei committed
        mouseEnable = true;
    
    amandaghassaei's avatar
    amandaghassaei committed
    }
    
    function onMouseUp(){
    
    amandaghassaei's avatar
    amandaghassaei committed
        mouseEnable = false;
    
    amandaghassaei's avatar
    amandaghassaei committed
    }