UNPKG

webgl-3d-animation

Version:

Interactive 3D animation using WebGL showing a 2D predator prey ecology on a grid which is real-time mapped onto the surface of a 3D torus. node.js server side gives access to WAV format files which are rendered using Web Audio API

887 lines 338 kB
(function ($hx_exports) { "use strict"; $hx_exports.lime = $hx_exports.lime || {}; var console = (1,eval)('this').console || {log:function(){}}; var $hxClasses = {},$estr = function() { return js.Boot.__string_rec(this,''); }; function $extend(from, fields) { function Inherit() {} Inherit.prototype = from; var proto = new Inherit(); for (var name in fields) proto[name] = fields[name]; if( fields.toString !== Object.prototype.toString ) proto.toString = fields.toString; return proto; } var ApplicationMain = function() { }; $hxClasses["ApplicationMain"] = ApplicationMain; ApplicationMain.__name__ = true; ApplicationMain.create = function() { ApplicationMain.preloader = new lime.app.Preloader(); ApplicationMain.preloader.onComplete = ApplicationMain.start; ApplicationMain.preloader.create(ApplicationMain.config); var urls = []; var types = []; ApplicationMain.preloader.load(urls,types); }; ApplicationMain.main = function() { ApplicationMain.config = { antialiasing : 0, background : 16777215, borderless : false, depthBuffer : false, fps : 0, fullscreen : false, height : 0, orientation : "", resizable : true, stencilBuffer : false, title : "WebGL Fluid Experiment", vsync : true, width : 0}; }; ApplicationMain.start = function() { ApplicationMain.app = new Main(); ApplicationMain.app.create(ApplicationMain.config); var result = ApplicationMain.app.exec(); }; var lime = {}; lime.AssetLibrary = function() { }; $hxClasses["lime.AssetLibrary"] = lime.AssetLibrary; lime.AssetLibrary.__name__ = true; lime.AssetLibrary.prototype = { exists: function(id,type) { return false; } ,getAudioBuffer: function(id) { return null; } ,getBytes: function(id) { return null; } ,getFont: function(id) { return null; } ,getImage: function(id) { return null; } ,getPath: function(id) { return null; } ,getText: function(id) { var bytes = this.getBytes(id); if(bytes == null) return null; else return bytes.readUTFBytes(bytes.length); } ,isLocal: function(id,type) { return true; } ,list: function(type) { return null; } ,load: function(handler) { handler(this); } ,loadAudioBuffer: function(id,handler) { handler(this.getAudioBuffer(id)); } ,loadBytes: function(id,handler) { handler(this.getBytes(id)); } ,loadFont: function(id,handler) { handler(this.getFont(id)); } ,loadImage: function(id,handler) { handler(this.getImage(id)); } ,loadText: function(id,handler) { var callback = function(bytes) { if(bytes == null) handler(null); else handler(bytes.readUTFBytes(bytes.length)); }; this.loadBytes(id,callback); } ,__class__: lime.AssetLibrary }; var DefaultAssetLibrary = function() { this.type = new haxe.ds.StringMap(); this.path = new haxe.ds.StringMap(); this.className = new haxe.ds.StringMap(); lime.AssetLibrary.call(this); var id; }; $hxClasses["DefaultAssetLibrary"] = DefaultAssetLibrary; DefaultAssetLibrary.__name__ = true; DefaultAssetLibrary.__super__ = lime.AssetLibrary; DefaultAssetLibrary.prototype = $extend(lime.AssetLibrary.prototype,{ exists: function(id,type) { var requestedType; if(type != null) requestedType = js.Boot.__cast(type , String); else requestedType = null; var assetType = this.type.get(id); if(assetType != null) { if(assetType == requestedType || (requestedType == "SOUND" || requestedType == "MUSIC") && (assetType == "MUSIC" || assetType == "SOUND")) return true; if(requestedType == "BINARY" || requestedType == null || assetType == "BINARY" && requestedType == "TEXT") return true; } return false; } ,getAudioBuffer: function(id) { return null; } ,getBytes: function(id) { var bytes = null; var data; data = ((function($this) { var $r; var key = $this.path.get(id); $r = lime.app.Preloader.loaders.get(key); return $r; }(this))).data; if(typeof(data) == "string") { bytes = new lime.utils.ByteArray(); bytes.writeUTFBytes(data); } else if(js.Boot.__instanceof(data,lime.utils.ByteArray)) bytes = data; else bytes = null; if(bytes != null) { bytes.position = 0; return bytes; } else return null; } ,getFont: function(id) { return null; } ,getImage: function(id) { return lime.graphics.Image.fromImageElement((function($this) { var $r; var key = $this.path.get(id); $r = lime.app.Preloader.images.get(key); return $r; }(this))); } ,getPath: function(id) { return this.path.get(id); } ,getText: function(id) { var bytes = null; var data; data = ((function($this) { var $r; var key = $this.path.get(id); $r = lime.app.Preloader.loaders.get(key); return $r; }(this))).data; if(typeof(data) == "string") return data; else if(js.Boot.__instanceof(data,lime.utils.ByteArray)) bytes = data; else bytes = null; if(bytes != null) { bytes.position = 0; return bytes.readUTFBytes(bytes.length); } else return null; } ,isLocal: function(id,type) { var requestedType; if(type != null) requestedType = js.Boot.__cast(type , String); else requestedType = null; return true; } ,list: function(type) { var requestedType; if(type != null) requestedType = js.Boot.__cast(type , String); else requestedType = null; var items = []; var $it0 = this.type.keys(); while( $it0.hasNext() ) { var id = $it0.next(); if(requestedType == null || this.exists(id,type)) items.push(id); } return items; } ,loadAudioBuffer: function(id,handler) { handler(this.getAudioBuffer(id)); } ,loadBytes: function(id,handler) { handler(this.getBytes(id)); } ,loadImage: function(id,handler) { handler(this.getImage(id)); } ,loadText: function(id,handler) { var callback = function(bytes) { if(bytes == null) handler(null); else handler(bytes.readUTFBytes(bytes.length)); }; this.loadBytes(id,callback); } ,__class__: DefaultAssetLibrary }); var EReg = function(r,opt) { opt = opt.split("u").join(""); this.r = new RegExp(r,opt); }; $hxClasses["EReg"] = EReg; EReg.__name__ = true; EReg.prototype = { match: function(s) { if(this.r.global) this.r.lastIndex = 0; this.r.m = this.r.exec(s); this.r.s = s; return this.r.m != null; } ,__class__: EReg }; var GPUFluid = function(gl,width,height,cellSize,solverIterations) { if(solverIterations == null) solverIterations = 18; if(cellSize == null) cellSize = 8; this.pressureGradientSubstractShader = new PressureGradientSubstract(); this.pressureSolveShader = new PressureSolve(); this.divergenceShader = new Divergence(); this.advectShader = new Advect(); this.gl = gl; this.width = width; this.height = height; this.solverIterations = solverIterations; this.aspectRatio = this.width / this.height; this.cellSize = cellSize; this.advectShader.rdx.set(1 / this.cellSize); this.divergenceShader.halfrdx.set(0.5 * (1 / this.cellSize)); this.pressureGradientSubstractShader.halfrdx.set(0.5 * (1 / this.cellSize)); this.pressureSolveShader.alpha.set(-this.cellSize * this.cellSize); this.cellSize; var texture_float_linear_supported = true; if(gl.getExtension("OES_texture_float_linear") == null) texture_float_linear_supported = false; if(gl.getExtension("OES_texture_float") == null) null; this.textureQuad = gltoolbox.GeometryTools.getCachedTextureQuad(); var nearestFactory = gltoolbox.TextureTools.createTextureFactory(gl.RGBA,gl.FLOAT,gl.NEAREST,null); this.velocityRenderTarget = new gltoolbox.render.RenderTarget2Phase(width,height,nearestFactory); this.pressureRenderTarget = new gltoolbox.render.RenderTarget2Phase(width,height,nearestFactory); this.divergenceRenderTarget = new gltoolbox.render.RenderTarget(width,height,nearestFactory); this.dyeRenderTarget = new gltoolbox.render.RenderTarget2Phase(width,height,gltoolbox.TextureTools.createTextureFactory(gl.RGB,gl.FLOAT,texture_float_linear_supported?gl.LINEAR:gl.NEAREST,null)); this.updateCoreShaderUniforms(this.advectShader); this.updateCoreShaderUniforms(this.divergenceShader); this.updateCoreShaderUniforms(this.pressureSolveShader); this.updateCoreShaderUniforms(this.pressureGradientSubstractShader); }; $hxClasses["GPUFluid"] = GPUFluid; GPUFluid.__name__ = true; GPUFluid.prototype = { step: function(dt) { this.gl.viewport(0,0,this.width,this.height); this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.textureQuad); this.advect(this.velocityRenderTarget,dt); if(this.applyForcesShader == null) null; else { this.applyForcesShader.dt.set(dt); this.applyForcesShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.applyForcesShader,this.velocityRenderTarget); this.velocityRenderTarget.swap(); } this.divergenceShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.divergenceShader,this.divergenceRenderTarget); this.solvePressure(); this.pressureGradientSubstractShader.pressure.set(this.pressureRenderTarget.readFromTexture); this.pressureGradientSubstractShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.pressureGradientSubstractShader,this.velocityRenderTarget); this.velocityRenderTarget.swap(); if(this.updateDyeShader == null) null; else { this.updateDyeShader.dt.set(dt); this.updateDyeShader.dye.set(this.dyeRenderTarget.readFromTexture); this.renderShaderTo(this.updateDyeShader,this.dyeRenderTarget); this.dyeRenderTarget.swap(); } this.advect(this.dyeRenderTarget,dt); } ,resize: function(width,height) { this.velocityRenderTarget.resize(width,height); this.pressureRenderTarget.resize(width,height); this.divergenceRenderTarget.resize(width,height); this.dyeRenderTarget.resize(width,height); this.width = width; this.height = height; } ,clear: function() { this.velocityRenderTarget.clear(this.gl.COLOR_BUFFER_BIT); this.pressureRenderTarget.clear(this.gl.COLOR_BUFFER_BIT); this.dyeRenderTarget.clear(this.gl.COLOR_BUFFER_BIT); } ,simToClipSpaceX: function(simX) { return simX / (this.cellSize * this.aspectRatio); } ,simToClipSpaceY: function(simY) { return simY / this.cellSize; } ,advect: function(target,dt) { this.advectShader.dt.set(dt); this.advectShader.target.set(target.readFromTexture); this.advectShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.advectShader,target); target.tmpFBO = target.writeFrameBufferObject; target.writeFrameBufferObject = target.readFrameBufferObject; target.readFrameBufferObject = target.tmpFBO; target.tmpTex = target.writeToTexture; target.writeToTexture = target.readFromTexture; target.readFromTexture = target.tmpTex; } ,applyForces: function(dt) { if(this.applyForcesShader == null) return; this.applyForcesShader.dt.set(dt); this.applyForcesShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.applyForcesShader,this.velocityRenderTarget); this.velocityRenderTarget.swap(); } ,computeDivergence: function() { this.divergenceShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.divergenceShader,this.divergenceRenderTarget); } ,solvePressure: function() { this.pressureSolveShader.divergence.set(this.divergenceRenderTarget.texture); this.pressureSolveShader.activate(true,true); var _g1 = 0; var _g = this.solverIterations; while(_g1 < _g) { var i = _g1++; this.pressureSolveShader.pressure.set(this.pressureRenderTarget.readFromTexture); this.pressureSolveShader.setUniforms(); lime.graphics.opengl.GL.context.bindFramebuffer(36160,this.pressureRenderTarget.writeFrameBufferObject); this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4); this.pressureRenderTarget.swap(); } this.pressureSolveShader.deactivate(); } ,subtractPressureGradient: function() { this.pressureGradientSubstractShader.pressure.set(this.pressureRenderTarget.readFromTexture); this.pressureGradientSubstractShader.velocity.set(this.velocityRenderTarget.readFromTexture); this.renderShaderTo(this.pressureGradientSubstractShader,this.velocityRenderTarget); this.velocityRenderTarget.swap(); } ,updateDye: function(dt) { if(this.updateDyeShader == null) return; this.updateDyeShader.dt.set(dt); this.updateDyeShader.dye.set(this.dyeRenderTarget.readFromTexture); this.renderShaderTo(this.updateDyeShader,this.dyeRenderTarget); this.dyeRenderTarget.swap(); } ,renderShaderTo: function(shader,target) { if(shader.active) { shader.setUniforms(); shader.setAttributes(); null; } else { if(!shader.ready) shader.create(); lime.graphics.opengl.GL.context.useProgram(shader.prog); shader.setUniforms(); shader.setAttributes(); shader.active = true; } target.activate(); this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4); shader.deactivate(); } ,updateCoreShaderUniforms: function(shader) { if(shader == null) return; shader.aspectRatio.set(this.aspectRatio); shader.invresolution.data.x = 1 / this.width; shader.invresolution.data.y = 1 / this.height; } ,set_applyForcesShader: function(v) { this.applyForcesShader = v; this.applyForcesShader.dx.set_data(this.cellSize); this.updateCoreShaderUniforms(this.applyForcesShader); return this.applyForcesShader; } ,set_updateDyeShader: function(v) { this.updateDyeShader = v; this.updateDyeShader.dx.set_data(this.cellSize); this.updateCoreShaderUniforms(this.updateDyeShader); return this.updateDyeShader; } ,set_cellSize: function(v) { this.cellSize = v; this.advectShader.rdx.set(1 / this.cellSize); this.divergenceShader.halfrdx.set(0.5 * (1 / this.cellSize)); this.pressureGradientSubstractShader.halfrdx.set(0.5 * (1 / this.cellSize)); this.pressureSolveShader.alpha.set(-this.cellSize * this.cellSize); return this.cellSize; } ,__class__: GPUFluid }; var shaderblox = {}; shaderblox.ShaderBase = function() { this.textures = []; this.uniforms = []; this.attributes = []; this.name = ("" + Std.string(Type.getClass(this))).split(".").pop(); this.createProperties(); }; $hxClasses["shaderblox.ShaderBase"] = shaderblox.ShaderBase; shaderblox.ShaderBase.__name__ = true; shaderblox.ShaderBase.prototype = { createProperties: function() { } ,create: function() { } ,destroy: function() { haxe.Log.trace("Destroying " + Std.string(this),{ fileName : "ShaderBase.hx", lineNumber : 51, className : "shaderblox.ShaderBase", methodName : "destroy"}); lime.graphics.opengl.GL.context.deleteShader(this.vert); lime.graphics.opengl.GL.context.deleteShader(this.frag); lime.graphics.opengl.GL.context.deleteProgram(this.prog); this.prog = null; this.vert = null; this.frag = null; this.ready = false; } ,initFromSource: function(vertSource,fragSource) { var vertexShader = lime.graphics.opengl.GL.context.createShader(35633); lime.graphics.opengl.GL.context.shaderSource(vertexShader,vertSource); lime.graphics.opengl.GL.context.compileShader(vertexShader); if(lime.graphics.opengl.GL.context.getShaderParameter(vertexShader,35713) == 0) { haxe.Log.trace("Error compiling vertex shader: " + lime.graphics.opengl.GL.context.getShaderInfoLog(vertexShader),{ fileName : "ShaderBase.hx", lineNumber : 67, className : "shaderblox.ShaderBase", methodName : "initFromSource"}); haxe.Log.trace("\n" + vertSource,{ fileName : "ShaderBase.hx", lineNumber : 68, className : "shaderblox.ShaderBase", methodName : "initFromSource"}); throw "Error compiling vertex shader"; } var fragmentShader = lime.graphics.opengl.GL.context.createShader(35632); lime.graphics.opengl.GL.context.shaderSource(fragmentShader,fragSource); lime.graphics.opengl.GL.context.compileShader(fragmentShader); if(lime.graphics.opengl.GL.context.getShaderParameter(fragmentShader,35713) == 0) { haxe.Log.trace("Error compiling fragment shader: " + lime.graphics.opengl.GL.context.getShaderInfoLog(fragmentShader) + "\n",{ fileName : "ShaderBase.hx", lineNumber : 77, className : "shaderblox.ShaderBase", methodName : "initFromSource"}); var lines = fragSource.split("\n"); var i = 0; var _g = 0; while(_g < lines.length) { var l = lines[_g]; ++_g; haxe.Log.trace(i++ + " - " + l,{ fileName : "ShaderBase.hx", lineNumber : 81, className : "shaderblox.ShaderBase", methodName : "initFromSource"}); } throw "Error compiling fragment shader"; } var shaderProgram = lime.graphics.opengl.GL.context.createProgram(); lime.graphics.opengl.GL.context.attachShader(shaderProgram,vertexShader); lime.graphics.opengl.GL.context.attachShader(shaderProgram,fragmentShader); lime.graphics.opengl.GL.context.linkProgram(shaderProgram); if(lime.graphics.opengl.GL.context.getProgramParameter(shaderProgram,35714) == 0) throw "Unable to initialize the shader program.\n" + lime.graphics.opengl.GL.context.getProgramInfoLog(shaderProgram); var numUniforms = lime.graphics.opengl.GL.context.getProgramParameter(shaderProgram,35718); var uniformLocations = new haxe.ds.StringMap(); while(numUniforms-- > 0) { var uInfo = lime.graphics.opengl.GL.context.getActiveUniform(shaderProgram,numUniforms); var loc = lime.graphics.opengl.GL.context.getUniformLocation(shaderProgram,uInfo.name); uniformLocations.set(uInfo.name,loc); loc; } var numAttributes = lime.graphics.opengl.GL.context.getProgramParameter(shaderProgram,35721); var attributeLocations = new haxe.ds.StringMap(); while(numAttributes-- > 0) { var aInfo = lime.graphics.opengl.GL.context.getActiveAttrib(shaderProgram,numAttributes); var loc1 = lime.graphics.opengl.GL.context.getAttribLocation(shaderProgram,aInfo.name); attributeLocations.set(aInfo.name,loc1); loc1; } this.vert = vertexShader; this.frag = fragmentShader; this.prog = shaderProgram; var count = this.uniforms.length; var removeList = []; this.numTextures = 0; this.textures = []; var _g1 = 0; var _g11 = this.uniforms; while(_g1 < _g11.length) { var u = _g11[_g1]; ++_g1; var loc2 = uniformLocations.get(u.name); if(js.Boot.__instanceof(u,shaderblox.uniforms.UTexture)) { var t = u; t.samplerIndex = this.numTextures++; this.textures[t.samplerIndex] = t; } if(loc2 != null) u.location = loc2; else removeList.push(u); } while(removeList.length > 0) { var x = removeList.pop(); HxOverrides.remove(this.uniforms,x); } var _g2 = 0; var _g12 = this.attributes; while(_g2 < _g12.length) { var a = _g12[_g2]; ++_g2; var loc3 = attributeLocations.get(a.name); if(loc3 == null) a.location = -1; else a.location = loc3; } } ,activate: function(initUniforms,initAttribs) { if(initAttribs == null) initAttribs = false; if(initUniforms == null) initUniforms = true; if(this.active) { if(initUniforms) this.setUniforms(); if(initAttribs) this.setAttributes(); return; } if(!this.ready) this.create(); lime.graphics.opengl.GL.context.useProgram(this.prog); if(initUniforms) this.setUniforms(); if(initAttribs) this.setAttributes(); this.active = true; } ,deactivate: function() { if(!this.active) return; this.active = false; this.disableAttributes(); } ,setUniforms: function() { var _g = 0; var _g1 = this.uniforms; while(_g < _g1.length) { var u = _g1[_g]; ++_g; u.apply(); } } ,setAttributes: function() { var offset = 0; var _g1 = 0; var _g = this.attributes.length; while(_g1 < _g) { var i = _g1++; var att = this.attributes[i]; var location = att.location; if(location != -1) { lime.graphics.opengl.GL.context.enableVertexAttribArray(location); lime.graphics.opengl.GL.context.vertexAttribPointer(location,att.itemCount,att.type,false,this.aStride,offset); } offset += att.byteSize; } } ,disableAttributes: function() { var _g1 = 0; var _g = this.attributes.length; while(_g1 < _g) { var i = _g1++; var idx = this.attributes[i].location; if(idx == -1) continue; lime.graphics.opengl.GL.context.disableVertexAttribArray(idx); } } ,toString: function() { return "[Shader(" + this.name + ", attributes:" + this.attributes.length + ", uniforms:" + this.uniforms.length + ")]"; } ,__class__: shaderblox.ShaderBase }; var FluidBase = function() { shaderblox.ShaderBase.call(this); }; $hxClasses["FluidBase"] = FluidBase; FluidBase.__name__ = true; FluidBase.__super__ = shaderblox.ShaderBase; FluidBase.prototype = $extend(shaderblox.ShaderBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n"); this.ready = true; } ,createProperties: function() { shaderblox.ShaderBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["aspectRatio",-1]); this.aspectRatio = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UVec2"),["invresolution",-1]); this.invresolution = instance1; this.uniforms.push(instance1); var instance2 = Type.createInstance(Type.resolveClass("shaderblox.attributes.FloatAttribute"),["vertexPosition",0,2]); this.vertexPosition = instance2; this.attributes.push(instance2); this.aStride += 8; } ,__class__: FluidBase }); var Advect = function() { FluidBase.call(this); }; $hxClasses["Advect"] = Advect; Advect.__name__ = true; Advect.__super__ = FluidBase; Advect.prototype = $extend(FluidBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n\nuniform sampler2D velocity;\nuniform sampler2D target;\nuniform float dt;\nuniform float rdx; \n\nvarying vec2 texelCoord;\nvarying vec2 p;\n\nvoid main(void){\n \n \n vec2 tracedPos = p - dt * rdx * texture2D(velocity, texelCoord ).xy;\n\n \n tracedPos = simToTexelSpace(tracedPos)/invresolution; \n \n vec4 st;\n st.xy = floor(tracedPos-.5)+.5; \n st.zw = st.xy+1.; \n\n vec2 t = tracedPos - st.xy;\n\n st*=invresolution.xyxy; \n \n vec4 tex11 = texture2D(target, st.xy );\n vec4 tex21 = texture2D(target, st.zy );\n vec4 tex12 = texture2D(target, st.xw );\n vec4 tex22 = texture2D(target, st.zw );\n\n \n gl_FragColor = mix(mix(tex11, tex21, t.x), mix(tex12, tex22, t.x), t.y);\n}\n"); this.ready = true; } ,createProperties: function() { FluidBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["velocity",-1,false]); this.velocity = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["target",-1,false]); this.target = instance1; this.uniforms.push(instance1); var instance2 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["dt",-1]); this.dt = instance2; this.uniforms.push(instance2); var instance3 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["rdx",-1]); this.rdx = instance3; this.uniforms.push(instance3); this.aStride += 0; } ,__class__: Advect }); var Divergence = function() { FluidBase.call(this); }; $hxClasses["Divergence"] = Divergence; Divergence.__name__ = true; Divergence.__super__ = FluidBase; Divergence.prototype = $extend(FluidBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n\nuniform sampler2D velocity;\t\nuniform float halfrdx;\t\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvoid main(void){\r\n\t\n \t\n\tvec2 L = sampleVelocity(velocity, texelCoord - vec2(invresolution.x, 0));\r\n\tvec2 R = sampleVelocity(velocity, texelCoord + vec2(invresolution.x, 0));\r\n\tvec2 B = sampleVelocity(velocity, texelCoord - vec2(0, invresolution.y));\r\n\tvec2 T = sampleVelocity(velocity, texelCoord + vec2(0, invresolution.y));\r\n\r\n\tgl_FragColor = vec4( halfrdx * ((R.x - L.x) + (T.y - B.y)), 0, 0, 1);\r\n}\r\n\n"); this.ready = true; } ,createProperties: function() { FluidBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["velocity",-1,false]); this.velocity = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["halfrdx",-1]); this.halfrdx = instance1; this.uniforms.push(instance1); this.aStride += 0; } ,__class__: Divergence }); var PressureSolve = function() { FluidBase.call(this); }; $hxClasses["PressureSolve"] = PressureSolve; PressureSolve.__name__ = true; PressureSolve.__super__ = FluidBase; PressureSolve.prototype = $extend(FluidBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n\nuniform sampler2D pressure;\nuniform sampler2D divergence;\nuniform float alpha;\n\nvarying vec2 texelCoord;\n\nvoid main(void){\n \n \n float L = samplePressue(pressure, texelCoord - vec2(invresolution.x, 0));\n float R = samplePressue(pressure, texelCoord + vec2(invresolution.x, 0));\n float B = samplePressue(pressure, texelCoord - vec2(0, invresolution.y));\n float T = samplePressue(pressure, texelCoord + vec2(0, invresolution.y));\n\n float bC = texture2D(divergence, texelCoord).x;\n\n gl_FragColor = vec4( (L + R + B + T + alpha * bC) * .25, 0, 0, 1 );\n}\n"); this.ready = true; } ,createProperties: function() { FluidBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["pressure",-1,false]); this.pressure = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["divergence",-1,false]); this.divergence = instance1; this.uniforms.push(instance1); var instance2 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["alpha",-1]); this.alpha = instance2; this.uniforms.push(instance2); this.aStride += 0; } ,__class__: PressureSolve }); var PressureGradientSubstract = function() { FluidBase.call(this); }; $hxClasses["PressureGradientSubstract"] = PressureGradientSubstract; PressureGradientSubstract.__name__ = true; PressureGradientSubstract.__super__ = FluidBase; PressureGradientSubstract.prototype = $extend(FluidBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n\nuniform sampler2D pressure;\r\nuniform sampler2D velocity;\r\nuniform float halfrdx;\r\n\r\nvarying vec2 texelCoord;\r\n\r\nvoid main(void){\r\n float L = samplePressue(pressure, texelCoord - vec2(invresolution.x, 0));\r\n float R = samplePressue(pressure, texelCoord + vec2(invresolution.x, 0));\r\n float B = samplePressue(pressure, texelCoord - vec2(0, invresolution.y));\r\n float T = samplePressue(pressure, texelCoord + vec2(0, invresolution.y));\r\n\r\n vec2 v = texture2D(velocity, texelCoord).xy;\r\n\r\n gl_FragColor = vec4(v - halfrdx*vec2(R-L, T-B), 0, 1);\r\n}\r\n\r\n\n"); this.ready = true; } ,createProperties: function() { FluidBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["pressure",-1,false]); this.pressure = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["velocity",-1,false]); this.velocity = instance1; this.uniforms.push(instance1); var instance2 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["halfrdx",-1]); this.halfrdx = instance2; this.uniforms.push(instance2); this.aStride += 0; } ,__class__: PressureGradientSubstract }); var ApplyForces = function() { FluidBase.call(this); }; $hxClasses["ApplyForces"] = ApplyForces; ApplyForces.__name__ = true; ApplyForces.__super__ = FluidBase; ApplyForces.prototype = $extend(FluidBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n\nuniform sampler2D velocity;\n\tuniform float dt;\n\tuniform float dx;\n\tvarying vec2 texelCoord;\n\tvarying vec2 p;\n"); this.ready = true; } ,createProperties: function() { FluidBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["velocity",-1,false]); this.velocity = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["dt",-1]); this.dt = instance1; this.uniforms.push(instance1); var instance2 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["dx",-1]); this.dx = instance2; this.uniforms.push(instance2); this.aStride += 0; } ,__class__: ApplyForces }); var UpdateDye = function() { FluidBase.call(this); }; $hxClasses["UpdateDye"] = UpdateDye; UpdateDye.__name__ = true; UpdateDye.__super__ = FluidBase; UpdateDye.prototype = $extend(FluidBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n \r\nattribute vec2 vertexPosition;\r\n\r\nuniform float aspectRatio;\r\n\r\nvarying vec2 texelCoord;\r\n\r\n\r\nvarying vec2 p;\r\n\r\nvoid main() {\r\n\ttexelCoord = vertexPosition;\r\n\t\r\n\tvec2 clipSpace = 2.0*texelCoord - 1.0;\t\n\t\r\n\tp = vec2(clipSpace.x * aspectRatio, clipSpace.y);\r\n\r\n\tgl_Position = vec4(clipSpace, 0.0, 1.0 );\t\r\n}\r\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\n#define PRESSURE_BOUNDARY\n#define VELOCITY_BOUNDARY\n\nuniform vec2 invresolution;\nuniform float aspectRatio;\n\nvec2 clipToSimSpace(vec2 clipSpace){\n return vec2(clipSpace.x * aspectRatio, clipSpace.y);\n}\n\nvec2 simToTexelSpace(vec2 simSpace){\n return vec2(simSpace.x / aspectRatio + 1.0 , simSpace.y + 1.0)*.5;\n}\n\n\nfloat samplePressue(sampler2D pressure, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n\n \n \n \n #ifdef PRESSURE_BOUNDARY\n if(coord.x < 0.0) cellOffset.x = 1.0;\n else if(coord.x > 1.0) cellOffset.x = -1.0;\n if(coord.y < 0.0) cellOffset.y = 1.0;\n else if(coord.y > 1.0) cellOffset.y = -1.0;\n #endif\n\n return texture2D(pressure, coord + cellOffset * invresolution).x;\n}\n\n\nvec2 sampleVelocity(sampler2D velocity, vec2 coord){\n vec2 cellOffset = vec2(0.0, 0.0);\n vec2 multiplier = vec2(1.0, 1.0);\n\n \n \n \n #ifdef VELOCITY_BOUNDARY\n if(coord.x<0.0){\n cellOffset.x = 1.0;\n multiplier.x = -1.0;\n }else if(coord.x>1.0){\n cellOffset.x = -1.0;\n multiplier.x = -1.0;\n }\n if(coord.y<0.0){\n cellOffset.y = 1.0;\n multiplier.y = -1.0;\n }else if(coord.y>1.0){\n cellOffset.y = -1.0;\n multiplier.y = -1.0;\n }\n #endif\n\n return multiplier * texture2D(velocity, coord + cellOffset * invresolution).xy;\n}\n\nuniform sampler2D dye;\n\tuniform float dt;\n\tuniform float dx;\n\tvarying vec2 texelCoord;\n\tvarying vec2 p;\n"); this.ready = true; } ,createProperties: function() { FluidBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["dye",-1,false]); this.dye = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["dt",-1]); this.dt = instance1; this.uniforms.push(instance1); var instance2 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["dx",-1]); this.dx = instance2; this.uniforms.push(instance2); this.aStride += 0; } ,__class__: UpdateDye }); var GPUParticles = function(gl,count) { if(count == null) count = 524288; this.gl = gl; gl.getExtension("OES_texture_float"); this.textureQuad = gltoolbox.GeometryTools.getCachedTextureQuad(); this.inititalConditionsShader = new InitialConditions(); this.stepParticlesShader = new StepParticles(); this.stepParticlesShader.dragCoefficient.set_data(1); this.stepParticlesShader.flowScale.data.x = 1; this.stepParticlesShader.flowScale.data.y = 1; this.setCount(count); this.renderShaderTo(this.inititalConditionsShader,this.particleData); }; $hxClasses["GPUParticles"] = GPUParticles; GPUParticles.__name__ = true; GPUParticles.prototype = { step: function(dt) { this.stepParticlesShader.dt.set_data(dt); this.stepParticlesShader.particleData.set_data(this.particleData.readFromTexture); this.renderShaderTo(this.stepParticlesShader,this.particleData); } ,reset: function() { this.renderShaderTo(this.inititalConditionsShader,this.particleData); } ,setCount: function(newCount) { var dataWidth = Math.ceil(Math.sqrt(newCount)); var dataHeight = dataWidth; if(this.particleData != null) this.particleData.resize(dataWidth,dataHeight); else this.particleData = new gltoolbox.render.RenderTarget2Phase(dataWidth,dataHeight,gltoolbox.TextureTools.floatTextureFactoryRGBA); if(this.particleUVs != null) this.gl.deleteBuffer(this.particleUVs); this.particleUVs = this.gl.createBuffer(); var arrayUVs = new Array(); var _g = 0; while(_g < dataWidth) { var i = _g++; var _g1 = 0; while(_g1 < dataHeight) { var j = _g1++; arrayUVs.push(i / dataWidth); arrayUVs.push(j / dataHeight); } } this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.particleUVs); this.gl.bufferData(this.gl.ARRAY_BUFFER,new Float32Array(arrayUVs),this.gl.STATIC_DRAW); this.gl.bindBuffer(this.gl.ARRAY_BUFFER,null); return this.count = newCount; } ,renderShaderTo: function(shader,target) { this.gl.viewport(0,0,target.width,target.height); this.gl.bindFramebuffer(this.gl.FRAMEBUFFER,target.writeFrameBufferObject); this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.textureQuad); if(shader.active) { shader.setUniforms(); shader.setAttributes(); null; } else { if(!shader.ready) shader.create(); lime.graphics.opengl.GL.context.useProgram(shader.prog); shader.setUniforms(); shader.setAttributes(); shader.active = true; } this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4); shader.deactivate(); target.tmpFBO = target.writeFrameBufferObject; target.writeFrameBufferObject = target.readFrameBufferObject; target.readFrameBufferObject = target.tmpFBO; target.tmpTex = target.writeToTexture; target.writeToTexture = target.readFromTexture; target.readFromTexture = target.tmpTex; } ,get_dragCoefficient: function() { return this.stepParticlesShader.dragCoefficient.data; } ,get_flowScaleX: function() { return this.stepParticlesShader.flowScale.data.x; } ,get_flowScaleY: function() { return this.stepParticlesShader.flowScale.data.y; } ,get_flowVelocityField: function() { return this.stepParticlesShader.flowVelocityField.data; } ,set_dragCoefficient: function(v) { return this.stepParticlesShader.dragCoefficient.set_data(v); } ,set_flowScaleX: function(v) { return this.stepParticlesShader.flowScale.data.x = v; } ,set_flowScaleY: function(v) { return this.stepParticlesShader.flowScale.data.y = v; } ,set_flowVelocityField: function(v) { return this.stepParticlesShader.flowVelocityField.set_data(v); } ,__class__: GPUParticles }; var PlaneTexture = function() { shaderblox.ShaderBase.call(this); }; $hxClasses["PlaneTexture"] = PlaneTexture; PlaneTexture.__name__ = true; PlaneTexture.__super__ = shaderblox.ShaderBase; PlaneTexture.prototype = $extend(shaderblox.ShaderBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nattribute vec2 vertexPosition;\n\tvarying vec2 texelCoord;\n\tvoid main(){\n\t\ttexelCoord = vertexPosition;\n\t\tgl_Position = vec4(vertexPosition*2.0 - vec2(1.0, 1.0), 0.0, 1.0 );\n\t}\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvarying vec2 texelCoord;\n"); this.ready = true; } ,createProperties: function() { shaderblox.ShaderBase.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.attributes.FloatAttribute"),["vertexPosition",0,2]); this.vertexPosition = instance; this.attributes.push(instance); this.aStride += 8; } ,__class__: PlaneTexture }); var InitialConditions = function() { PlaneTexture.call(this); }; $hxClasses["InitialConditions"] = InitialConditions; InitialConditions.__name__ = true; InitialConditions.__super__ = PlaneTexture; InitialConditions.prototype = $extend(PlaneTexture.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nattribute vec2 vertexPosition;\n\tvarying vec2 texelCoord;\n\tvoid main(){\n\t\ttexelCoord = vertexPosition;\n\t\tgl_Position = vec4(vertexPosition*2.0 - vec2(1.0, 1.0), 0.0, 1.0 );\n\t}\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvarying vec2 texelCoord;\n\nvoid main(){\n\t\tvec2 ip = vec2((texelCoord.x), (texelCoord.y)) * 2.0 - 1.0;\n\t\tvec2 iv = vec2(0,0);\n\t\tgl_FragColor = vec4(ip, iv);\n\t}\n"); this.ready = true; } ,createProperties: function() { PlaneTexture.prototype.createProperties.call(this); this.aStride += 0; } ,__class__: InitialConditions }); var ParticleBase = function() { PlaneTexture.call(this); }; $hxClasses["ParticleBase"] = ParticleBase; ParticleBase.__name__ = true; ParticleBase.__super__ = PlaneTexture; ParticleBase.prototype = $extend(PlaneTexture.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nattribute vec2 vertexPosition;\n\tvarying vec2 texelCoord;\n\tvoid main(){\n\t\ttexelCoord = vertexPosition;\n\t\tgl_Position = vec4(vertexPosition*2.0 - vec2(1.0, 1.0), 0.0, 1.0 );\n\t}\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvarying vec2 texelCoord;\n\nuniform float dt;\n\tuniform sampler2D particleData;\n"); this.ready = true; } ,createProperties: function() { PlaneTexture.prototype.createProperties.call(this); var instance = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UFloat"),["dt",-1]); this.dt = instance; this.uniforms.push(instance); var instance1 = Type.createInstance(Type.resolveClass("shaderblox.uniforms.UTexture"),["particleData",-1,false]); this.particleData = instance1; this.uniforms.push(instance1); this.aStride += 0; } ,__class__: ParticleBase }); var StepParticles = function() { ParticleBase.call(this); }; $hxClasses["StepParticles"] = StepParticles; StepParticles.__name__ = true; StepParticles.__super__ = ParticleBase; StepParticles.prototype = $extend(ParticleBase.prototype,{ create: function() { this.initFromSource("\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nattribute vec2 vertexPosition;\n\tvarying vec2 texelCoord;\n\tvoid main(){\n\t\ttexelCoord = vertexPosition;\n\t\tgl_Position = vec4(vertexPosition*2.0 - vec2(1.0, 1.0), 0.0, 1.0 );\n\t}\n\n\n\n\n","\n#ifdef GL_ES\nprecision mediump float;\n#endif\n\nvarying vec2 texelCoord;\n\nuniform float dt;\n\tuniform sampler2D particleData;\n\nuniform float dragCoefficient;\n\tuniform vec2 flowScale;\n\tuniform sampler2D flowVelocityField;\n\tvoid main(){\n\t\tvec2 p = texture2D(particleData, texelCoord).xy;\n\t\tvec2 v = texture2D(particleData, texelCoord).zw;\n\t\tvec2 vf = texture2D(flowVelocityField, (p+1.)*.5).xy * flowScale;\n\t\tv += (vf - v) * dragCoeffi