From abfba202e54580ee456ad4675cb9be76317f82cf Mon Sep 17 00:00:00 2001 From: amandaghassaei <amandaghassaei@gmail.com> Date: Sun, 2 Apr 2017 16:20:48 -0400 Subject: [PATCH] reworking gpu stuff --- GPUMath.js | 147 +++++++++++++++++++++++++++ GlBoilerplate.js | 258 ++++++++++++++++++++++++++++------------------- index.html | 40 ++++++-- main.js | 152 ++++------------------------ 4 files changed, 349 insertions(+), 248 deletions(-) create mode 100644 GPUMath.js diff --git a/GPUMath.js b/GPUMath.js new file mode 100644 index 0000000..fb9d499 --- /dev/null +++ b/GPUMath.js @@ -0,0 +1,147 @@ +/** + * Created by ghassaei on 2/24/16. + */ + + +function initGPUMath(){ + + var glBoilerplate = initBoilerPlate(); + + var canvas = document.getElementById("glcanvas"); + var gl = canvas.getContext("webgl", {antialias:false}) || canvas.getContext("experimental-webgl", {antialias:false}); + gl.getExtension('OES_texture_float'); + gl.disable(gl.DEPTH_TEST); + + var maxTexturesInFragmentShader = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + console.log(maxTexturesInFragmentShader + " textures max"); + + + function GPUMath(){ + this.reset(); + } + + GPUMath.prototype.createProgram = function(programName, vertexShader, fragmentShader){ + var programs = this.programs; + var program = programs[programName]; + if (program) { + console.warn("already a program with the name " + programName); + return; + } + program = glBoilerplate.createProgramFromScripts(gl, vertexShader, fragmentShader); + gl.useProgram(program); + glBoilerplate.loadVertexData(gl, program); + programs[programName] = { + program: program, + uniforms: {} + }; + }; + + GPUMath.prototype.initTextureFromData = function(name, width, height, typeName, data, shouldReplace){ + var texture = this.textures[name]; + if (!shouldReplace && texture) { + console.warn("already a texture with the name " + name); + return; + } + texture = glBoilerplate.makeTexture(gl, width, height, gl[typeName], data); + this.textures[name] = texture; + }; + + + + GPUMath.prototype.initFrameBufferForTexture = function(textureName){ + var framebuffer = this.frameBuffers[textureName]; + if (framebuffer) { + console.warn("framebuffer already exists for texture " + textureName); + return; + } + var texture = this.textures[textureName]; + if (!texture){ + console.warn("texture " + textureName + " does not exist"); + return; + } + + framebuffer = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); + this.frameBuffers[textureName] = framebuffer; + }; + + + GPUMath.prototype.setUniformForProgram = function(programName, name, val, type){ + if (!this.programs[programName]){ + console.warn("no program with name " + programName); + return; + } + var uniforms = this.programs[programName].uniforms; + var location = uniforms[name]; + if (!location) { + location = gl.getUniformLocation(this.programs[programName].program, name); + uniforms[name] = location; + } + if (type == "1f") gl.uniform1f(location, val); + else if (type == "2f") gl.uniform2f(location, val[0], val[1]); + else if (type == "3f") gl.uniform3f(location, val[0], val[1], val[2]); + else if (type == "1i") gl.uniform1i(location, val); + else { + console.warn("no uniform for type " + type); + } + }; + + GPUMath.prototype.setSize = function(width, height){ + gl.viewport(0, 0, width, height); + canvas.clientWidth = width; + canvas.clientHeight = height; + }; + + GPUMath.prototype.setProgram = function(programName){ + gl.useProgram(this.programs[programName].program); + }; + + GPUMath.prototype.step = function(programName, inputTextures, outputTexture){ + + gl.useProgram(this.programs[programName].program); + gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffers[outputTexture]); + for (var i=0;i<inputTextures.length;i++){ + gl.activeTexture(gl.TEXTURE0 + i); + gl.bindTexture(gl.TEXTURE_2D, this.textures[inputTextures[i]]); + } + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);//draw to framebuffer + }; + + GPUMath.prototype.swapTextures = function(texture1Name, texture2Name){ + var temp = this.textures[texture1Name]; + this.textures[texture1Name] = this.textures[texture2Name]; + this.textures[texture2Name] = temp; + temp = this.frameBuffers[texture1Name]; + this.frameBuffers[texture1Name] = this.frameBuffers[texture2Name]; + this.frameBuffers[texture2Name] = temp; + }; + + GPUMath.prototype.swap3Textures = function(texture1Name, texture2Name, texture3Name){ + var temp = this.textures[texture3Name]; + this.textures[texture3Name] = this.textures[texture2Name]; + this.textures[texture2Name] = this.textures[texture1Name]; + this.textures[texture1Name] = temp; + temp = this.frameBuffers[texture3Name]; + this.frameBuffers[texture3Name] = this.frameBuffers[texture2Name]; + this.frameBuffers[texture2Name] = this.frameBuffers[texture1Name]; + this.frameBuffers[texture1Name] = temp; + }; + + GPUMath.prototype.readyToRead = function(){ + return gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE; + }; + + GPUMath.prototype.readPixels = function(xMin, yMin, width, height, array){ + gl.readPixels(xMin, yMin, width, height, gl.RGBA, gl.UNSIGNED_BYTE, array); + }; + + GPUMath.prototype.reset = function(){ + this.programs = {}; + this.frameBuffers = {}; + this.textures = {}; + this.index = 0; + }; + + return new GPUMath; +} \ No newline at end of file diff --git a/GlBoilerplate.js b/GlBoilerplate.js index 57d717f..a8ec137 100644 --- a/GlBoilerplate.js +++ b/GlBoilerplate.js @@ -1,109 +1,155 @@ //from http://webglfundamentals.org/webgl/lessons/webgl-boilerplate.html -/** - * Creates and compiles a shader. - * - * @param {!WebGLRenderingContext} gl The WebGL Context. - * @param {string} shaderSource The GLSL source code for the shader. - * @param {number} shaderType The type of shader, VERTEX_SHADER or - * FRAGMENT_SHADER. - * @return {!WebGLShader} The shader. - */ -function compileShader(gl, shaderSource, shaderType) { - // Create the shader object - var shader = gl.createShader(shaderType); - - // Set the shader source code. - gl.shaderSource(shader, shaderSource); - - // Compile the shader - gl.compileShader(shader); - - // Check if it compiled - var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); - if (!success) { - // Something went wrong during compilation; get the error - throw "could not compile shader:" + gl.getShaderInfoLog(shader); - } - - return shader; -} - -/** - * Creates a program from 2 shaders. - * - * @param {!WebGLRenderingContext) gl The WebGL context. - * @param {!WebGLShader} vertexShader A vertex shader. - * @param {!WebGLShader} fragmentShader A fragment shader. - * @return {!WebGLProgram} A program. - */ -function createProgram(gl, vertexShader, fragmentShader) { - // create a program. - var program = gl.createProgram(); - - // attach the shaders. - gl.attachShader(program, vertexShader); - gl.attachShader(program, fragmentShader); - - // link the program. - gl.linkProgram(program); - - // Check if it linked. - var success = gl.getProgramParameter(program, gl.LINK_STATUS); - if (!success) { - // something went wrong with the link - throw ("program filed to link:" + gl.getProgramInfoLog (program)); - } - - return program; -} - -/** - * Creates a shader from the content of a script tag. - * - * @param {!WebGLRenderingContext} gl The WebGL Context. - * @param {string} scriptId The id of the script tag. - * @param {string} opt_shaderType. The type of shader to create. - * If not passed in will use the type attribute from the - * script tag. - * @return {!WebGLShader} A shader. - */ -function createShaderFromScript(gl, scriptId, opt_shaderType) { - // look up the script tag by id. - var shaderScript = document.getElementById(scriptId); - if (!shaderScript) { - throw("*** Error: unknown script element" + scriptId); - } - - // extract the contents of the script tag. - var shaderSource = shaderScript.text; - - // If we didn't pass in a type, use the 'type' from - // the script tag. - if (!opt_shaderType) { - if (shaderScript.type == "x-shader/x-vertex") { - opt_shaderType = gl.VERTEX_SHADER; - } else if (shaderScript.type == "x-shader/x-fragment") { - opt_shaderType = gl.FRAGMENT_SHADER; - } else if (!opt_shaderType) { - throw("*** Error: shader type not set"); +function initBoilerPlate(){ + + /** + * Creates and compiles a shader. + * + * @param {!WebGLRenderingContext} gl The WebGL Context. + * @param {string} shaderSource The GLSL source code for the shader. + * @param {number} shaderType The type of shader, VERTEX_SHADER or + * FRAGMENT_SHADER. + * @return {!WebGLShader} The shader. + */ + function compileShader(gl, shaderSource, shaderType) { + // Create the shader object + var shader = gl.createShader(shaderType); + + // Set the shader source code. + gl.shaderSource(shader, shaderSource); + + // Compile the shader + gl.compileShader(shader); + + // Check if it compiled + var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + if (!success) { + // Something went wrong during compilation; get the error + throw "could not compile shader:" + gl.getShaderInfoLog(shader); + } + + return shader; + } + + /** + * Creates a program from 2 shaders. + * + * @param {!WebGLRenderingContext) gl The WebGL context. + * @param {!WebGLShader} vertexShader A vertex shader. + * @param {!WebGLShader} fragmentShader A fragment shader. + * @return {!WebGLProgram} A program. + */ + function createProgram(gl, vertexShader, fragmentShader) { + // create a program. + var program = gl.createProgram(); + + // attach the shaders. + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + + // link the program. + gl.linkProgram(program); + + // Check if it linked. + var success = gl.getProgramParameter(program, gl.LINK_STATUS); + if (!success) { + // something went wrong with the link + throw ("program filed to link:" + gl.getProgramInfoLog (program)); + } + + return program; + } + + /** + * Creates a shader from the content of a script tag. + * + * @param {!WebGLRenderingContext} gl The WebGL Context. + * @param {string} scriptId The id of the script tag. + * @param {string} opt_shaderType. The type of shader to create. + * If not passed in will use the type attribute from the + * script tag. + * @return {!WebGLShader} A shader. + */ + function createShaderFromSource(gl, shaderSource, shaderType) { + return compileShader(gl, shaderSource, shaderType); + } + + /** + * Creates a program from 2 script tags. + * + * @param {!WebGLRenderingContext} gl The WebGL Context. + * @param {string} vertexShaderId The id of the vertex shader script tag. + * @param {string} fragmentShaderId The id of the fragment shader script tag. + * @return {!WebGLProgram} A program + */ + function createProgramFromSource( + gl, vertexShader, fragmentShader) { + var vertexShader = createShaderFromSource(gl, vertexShader, gl.VERTEX_SHADER); + var fragmentShader = createShaderFromSource(gl, fragmentShader, gl.FRAGMENT_SHADER); + return createProgram(gl, vertexShader, fragmentShader); + } + + function createProgramFromScripts(gl, vertexShaderId, fragmentShaderId) { + var vertexShader = createShaderFromScript(gl, vertexShaderId); + var fragmentShader = createShaderFromScript(gl, fragmentShaderId); + return createProgram(gl, vertexShader, fragmentShader); + } + + function createShaderFromScript(gl, scriptId, opt_shaderType) { + // look up the script tag by id. + var shaderScript = document.getElementById(scriptId); + if (!shaderScript) { + throw("*** Error: unknown script element" + scriptId); + } + + // extract the contents of the script tag. + var shaderSource = shaderScript.text; + + // If we didn't pass in a type, use the 'type' from + // the script tag. + if (!opt_shaderType) { + if (shaderScript.type == "x-shader/x-vertex") { + opt_shaderType = gl.VERTEX_SHADER; + } else if (shaderScript.type == "x-shader/x-fragment") { + opt_shaderType = gl.FRAGMENT_SHADER; + } else if (!opt_shaderType) { + throw("*** Error: shader type not set"); + } + } + + return compileShader(gl, shaderSource, opt_shaderType); + } + + 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 makeTexture(gl, width, height, type, 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, type, data); + + return texture; + } + + return { + createProgramFromSource: createProgramFromSource, + createProgramFromScripts: createProgramFromScripts, + loadVertexData: loadVertexData, + makeTexture: makeTexture } - } - - return compileShader(gl, shaderSource, opt_shaderType); -} - -/** - * Creates a program from 2 script tags. - * - * @param {!WebGLRenderingContext} gl The WebGL Context. - * @param {string} vertexShaderId The id of the vertex shader script tag. - * @param {string} fragmentShaderId The id of the fragment shader script tag. - * @return {!WebGLProgram} A program - */ -function createProgramFromScripts( - gl, vertexShaderId, fragmentShaderId) { - var vertexShader = createShaderFromScript(gl, vertexShaderId); - var fragmentShader = createShaderFromScript(gl, fragmentShaderId); - return createProgram(gl, vertexShader, fragmentShader); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/index.html b/index.html index a5e4d79..97fc66f 100644 --- a/index.html +++ b/index.html @@ -20,14 +20,36 @@ <script id="2d-render-shader" type="x-shader/x-fragment"> precision mediump float; - uniform sampler2D u_image; - uniform vec2 u_textureSize; + //uniform sampler2D u_velocities; + //uniform vec2 u_textureSize; + + void main() { + gl_FragColor = vec4(1, 0, 1, 1); + } + </script> + + <script id="advectShader" type="x-shader/x-fragment"> + precision mediump float; - const float COLOR_MIN = 0.2, COLOR_MAX = 0.4; + //uniform sampler2D u_velocities; + //uniform sampler2D u_material; + + //uniform vec2 u_textureSize; + + //uniform float u_dt; void main() { - float v = (COLOR_MAX - texture2D(u_image, gl_FragCoord.xy / u_textureSize)).y / (COLOR_MAX - COLOR_MIN); - gl_FragColor = vec4(v, v, v, 1); + + //vec2 fragCoord = gl_FragCoord.xy; + + //vec2 currentVelocity = texture2D(u_velocities, fragCoord/u_textureSize).xy; + + //implicitly solve advection + //vec2 pos = fragCoord - u_dt * currentVelocity; + + // bilinear interp between nearest cells + //gl_FragColor = texture2D(u_material, pos/u_textureSize); + gl_FragColor = vec4(1,1,1,1); } </script> @@ -74,7 +96,8 @@ <script type="text/javascript" src="dependencies/jquery-3.1.0.min.js"></script> <script type="text/javascript" src="dependencies/flat-ui.min.js"></script> - <script type="text/javascript" src="GlBoilerplate.js"></script> + <script type="text/javascript" src="GLBoilerplate.js"></script> + <script type="text/javascript" src="GPUMath.js"></script> <script type="text/javascript" src="main.js"></script> </head> <body> @@ -89,9 +112,10 @@ <div class="modal-body"> <b>Fluid Simulation Shader</b><br/><br/> I used the following sources to write this simulation:<br/><br/> - <a href="https://pdfs.semanticscholar.org/84b8/c7b7eecf90ebd9d54a51544ca0f8ff93c137.pdf" target="_blank">Real-time ink simulation using a grid-particle method</a><br/> + <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/> <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/> - <a href="http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf" target="_blank">Stable Fluids</a> - a paper about numerical methods for evaluating Navier-Stokes on a discrete grid.<br/> + <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/> <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>. <br/><br/> diff --git a/main.js b/main.js index da23174..dabcad1 100755 --- a/main.js +++ b/main.js @@ -1,21 +1,6 @@ //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 width, height; var mouseCoordLocation; var mouseCoordinates = [null, null]; @@ -24,6 +9,8 @@ var mouseEnable = false; var paused = false;//while window is resizing +var GPU; + window.onload = initGL; function initGL() { @@ -33,10 +20,7 @@ function initGL() { $("#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; @@ -45,125 +29,31 @@ function initGL() { 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'); + GPU = initGPUMath(); - // 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()]; + // setup a GLSL programs + GPU.createProgram("advect", "2d-vertex-shader", "advectShader"); + GPU.createProgram("render", "2d-vertex-shader", "2d-render-shader"); resetWindow(); - gl.bindTexture(gl.TEXTURE_2D, states[0]);//original texture + GPU.initFrameBufferForTexture("velocities"); 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); - } + // if (mouseEnable){ + // gl.uniform1f(mouseEnableLocation, 1); + // gl.uniform2f(mouseCoordLocation, mouseCoordinates[0], mouseCoordinates[1]); + // } else gl.uniform1f(mouseEnableLocation, 0); - - 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); + GPU.step("render", []); } else resetWindow(); @@ -187,20 +77,14 @@ function resetWindow(){ width = canvas.clientWidth; height = canvas.clientHeight; - gl.viewport(0, 0, width, height); + GPU.setSize(width, height); + - // set the size of the texture - gl.useProgram(stepProgram); - gl.uniform2f(textureSizeLocation, width, height); - gl.useProgram(renderProgram); - gl.uniform2f(textureSizeLocationRender, width, height); + GPU.setUniformForProgram("advect" ,"u_textureSize", [width, height], "2f"); - //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)); + var velocities = new Float32Array(width*height*4); + GPU.initTextureFromData("velocities", width, height, "FLOAT", velocities, true); paused = false; } -- GitLab