Skip to content
Snippets Groups Projects
main.js 6.12 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
    
    var gl;
    var canvas;
    var frameBuffers;
    var states = [null, null];
    
    var resizedLastState;
    var resizedCurrentState;
    
    var width;
    var height;
    
    var stepProgram;
    var renderProgram;
    
    var textureSizeLocation;
    var textureSizeLocationRender;
    
    var mouseCoordLocation;
    var mouseCoordinates =  [null, null];
    var mouseEnableLocation;
    var mouseEnable = true;
    
    var paused = false;//while window is resizing
    
    window.onload = initGL;
    
    function initGL() {
    
        $("#about").click(function(e){
            e.preventDefault();
            $("#aboutModal").modal('show');
        });
    
        // Get A WebGL context
        canvas = document.getElementById("glcanvas");
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;
    
        canvas.onmousemove = onMouseMove;
        canvas.onmousedown = onMouseDown;
        // canvas.onmouseup = onMouseUp;
        canvas.onmouseout = onMouseUp;
        canvas.onmouseenter = function(){
            mouseEnable = 1;
        };
    
        window.onresize = onResize;
    
        gl = canvas.getContext("webgl", {antialias:false}) || canvas.getContext("experimental-webgl", {antialias:false});
        if (!gl) {
            alert('Could not initialize WebGL, try another browser');
            return;
        }
    
        gl.disable(gl.DEPTH_TEST);
        gl.getExtension('OES_texture_float');
    
        // setup a GLSL program
        stepProgram = createProgramFromScripts(gl, "2d-vertex-shader", "2d-fragment-shader");
        renderProgram = createProgramFromScripts(gl, "2d-vertex-shader", "2d-render-shader");
        gl.useProgram(renderProgram);
        loadVertexData(gl, renderProgram);
        textureSizeLocationRender = gl.getUniformLocation(renderProgram, "u_textureSize");
        gl.useProgram(stepProgram);
        loadVertexData(gl, stepProgram);
    
    
        textureSizeLocation = gl.getUniformLocation(stepProgram, "u_textureSize");
        mouseCoordLocation = gl.getUniformLocation(stepProgram, "u_mouseCoord");
        mouseEnableLocation = gl.getUniformLocation(stepProgram, "u_mouseEnable");
    
        frameBuffers = [makeFrameBuffer(), makeFrameBuffer()];
    
        resetWindow();
    
        gl.bindTexture(gl.TEXTURE_2D, states[0]);//original texture
    
        render();
    }
    
    function loadVertexData(gl, program) {
    	gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
    	gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1,-1, 1,-1, -1, 1, 1, 1]), gl.STATIC_DRAW);
    
        // look up where the vertex data needs to go.
    	var positionLocation = gl.getAttribLocation(program, "a_position");
    	gl.enableVertexAttribArray(positionLocation);
    	gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
    }
    
    function makeFrameBuffer(){
        return gl.createFramebuffer();
    }
    
    function makeRandomArray(rgba){
        for (var x=0;x<width;x++) {
            for (var y=0;y<height;y++) {
                var ii = (y*width + x) * 4;
    			var central_square = (x > width/2-10 && x < width/2+10 && y > height/2-10 && y < height/2+10);
    			if (central_square) {
    				rgba[ii] = 0.5 + Math.random() * 0.02 - 0.01;
    				rgba[ii + 1] = 0.25 + Math.random() * 0.02 - 0.01;
    			} else {
    				rgba[ii] = 1.0;
    				rgba[ii + 1] = 0;
    			}
            }
        }
        return rgba;
    }
    
    function makeTexture(gl, data){
    
        var texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
    
        // Set the parameters so we can render any size image.
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, data);
    
        return texture;
    }
    
    function render(){
    
        if (!paused) {
    
            gl.useProgram(stepProgram);
    
            if (mouseEnable){
                gl.uniform1f(mouseEnableLocation, 1);
                gl.uniform2f(mouseCoordLocation, mouseCoordinates[0], mouseCoordinates[1]);
            } else gl.uniform1f(mouseEnableLocation, 0);
    
            if (resizedLastState) {
                states[0] = resizedLastState;
                gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffers[0]);
                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, states[0], 0);
                resizedLastState = null;
            }
            if (resizedCurrentState) {
                states[1] = resizedCurrentState;
                gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffers[1]);
                gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, states[1], 0);
                resizedCurrentState = null;
            }
    
            for (var i=0;i<2;i++) {
                if (paused) {
                    window.requestAnimationFrame(render);
                    return;
                }
    
                step(i);
            }
    
    
            gl.useProgram(renderProgram);
    
            //draw to canvas
            gl.bindFramebuffer(gl.FRAMEBUFFER, null);
            gl.bindTexture(gl.TEXTURE_2D, states[0]);
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    
        } else resetWindow();
    
        window.requestAnimationFrame(render);
    }
    
    function step(i){
        gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffers[(i+1)%2]);
        gl.bindTexture(gl.TEXTURE_2D, states[i%2]);
    
        gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);//draw to framebuffer
    }
    
    function onResize(){
        paused = true;
    }
    
    function resetWindow(){
        canvas.width = canvas.clientWidth;
        canvas.height = canvas.clientHeight;
        width = canvas.clientWidth;
        height = canvas.clientHeight;
    
        gl.viewport(0, 0, width, height);
    
        // set the size of the texture
        gl.useProgram(stepProgram);
        gl.uniform2f(textureSizeLocation, width, height);
        gl.useProgram(renderProgram);
        gl.uniform2f(textureSizeLocationRender, width, height);
    
        //texture for saving output from frag shader
        resizedCurrentState = makeTexture(gl, null);
    
        //fill with random pixels
        var rgba = new Float32Array(width*height*4);
        resizedLastState = makeTexture(gl, makeRandomArray(rgba));
    
        paused = false;
    }
    
    function onMouseMove(e){
        mouseCoordinates = [e.clientX, height-e.clientY];
    }
    
    function onMouseDown(e){
        // gl.useProgram(stepProgram);
        mouseCoordinates = [e.clientX, height-e.clientY];
    }
    
    function onMouseUp(){
        mouseEnable = 0;
    }