UNPKG

jsx

Version:

a faster, safer, easier JavaScript

235 lines (188 loc) 7.44 kB
import 'js/web.jsx'; import 'mvq.jsx'; import 'webgl-util.jsx'; class Water { static var gl = null:WebGLRenderingContext; static var progDisp = null:WebGLProgram; static var progVelo = null:WebGLProgram; static var vbuf = null:WebGLBuffer; static var drawProg = null:WebGLProgram; static var drawVBuf = null:WebGLBuffer; static var drawTBuf = null:WebGLBuffer; static const tsize = 64; static const time_step = 0.02; static function initWithGL(gl:WebGLRenderingContext) : void { Water.gl = gl; Water.progDisp = Util.getProgram('water.vs', 'waterd.fs'); Water.progVelo = Util.getProgram('water.vs', 'waterv.fs'); Water.vbuf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, Water.vbuf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0, 1,0, 1,1, 0,1]), gl.STATIC_DRAW); Water.drawProg = Util.getProgram('vt.vs', 'refr.fs'); Water.drawVBuf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, Water.drawVBuf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-20,-20, 20,-20, 20,20, -20,20]), gl.STATIC_DRAW); Water.drawTBuf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, Water.drawTBuf); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0, 1,0, 1,1, 0,1]), gl.STATIC_DRAW); } var texture = null:WebGLTexture; var framebuffer = null:WebGLFramebuffer; var texturebuffer = null:WebGLTexture; var depthbuffer = null:WebGLRenderbuffer; var width = 0; var height = 0; var _ix = -1; var _iy = -1; var _ir = 0; var _iz = 0; var _next_step_time = 0; function constructor() { var gl = Water.gl; var w = Water.tsize; var h = Water.tsize; var framebuffer = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); for (var i = 0; i < 2; ++i) { var timg = new Uint8Array(w * h * 4); for (var y = 0; y < h; ++y) for (var x = 0; x < w; ++x) { var b = (y*w+x)*4; timg[b] = 128; timg[b + 1] = 128; timg[b + 2] = 0; timg[b + 3] = 0; } var texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, timg); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 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.bindTexture(gl.TEXTURE_2D, null); if (i == 0) { gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); this.texturebuffer = texture; } else { this.texture = texture; } } var depthbuffer = gl.createRenderbuffer(); //gl.bindRenderbuffer(gl.RENDERBUFFER, depthbuffer); //gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, w, h); //gl.bindRenderbuffer(gl.RENDERBUFFER, null); //gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthbuffer); gl.bindFramebuffer(gl.FRAMEBUFFER, null); this.framebuffer = framebuffer; this.depthbuffer = depthbuffer; this.width = w; this.height = h; } function destroy() : void { var gl = Water.gl; gl.deleteFramebuffer(this.framebuffer); gl.deleteTexture(this.texturebuffer); gl.deleteRenderbuffer(this.depthbuffer); gl.deleteTexture(this.texture); } function step(t:number) : void { if (!this._next_step_time) this._next_step_time = t; if (t < this._next_step_time) return; this._next_step_time += Water.time_step; if (this._next_step_time < t) this._next_step_time = t; var gl = Water.gl; // get viewport //var vp = gl.getParameter(gl.VIEWPORT) as Int32Array; // XXX: workaround fod Firefox var vp = null:Int32Array; var tmp_vp = gl.getParameter(gl.VIEWPORT); if (tmp_vp instanceof Int32Array) { vp = tmp_vp as __noconvert__ Int32Array; } else { vp = new Int32Array(tmp_vp as __noconvert__ Array.<int>); } gl.disable(gl.BLEND); gl.disable(gl.DEPTH_TEST); this._step(Water.progDisp); // displacement step this._step(Water.progVelo); // velocity step // restore viewport gl.viewport(vp[0], vp[1], vp[2], vp[3]); gl.enable(gl.BLEND); gl.enable(gl.DEPTH_TEST); // reset down pos if (this._ir > 0) this._ir = 0; } function _step(prog:WebGLProgram) : void { var gl = Water.gl; var vloc = gl.getAttribLocation(prog, 'vertex'); // draw begin gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); gl.viewport(0, 0, this.width, this.height); gl.useProgram(prog); var impLoc = gl.getUniformLocation(prog, 'impulse'); if (impLoc) { gl.uniform4f(impLoc, this._ix, this._iy, this._iz, this._ir); } gl.uniformMatrix4fv(gl.getUniformLocation(prog, 'projectionMatrix'), false, new M44().setOrtho(0, 1, 0, 1, -1, 1).array()); gl.uniform2f(gl.getUniformLocation(prog, 'sampleStep'), 1/this.width, 1/this.height); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.bindBuffer(gl.ARRAY_BUFFER, Water.vbuf); gl.vertexAttribPointer(vloc, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(vloc); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); gl.disableVertexAttribArray(vloc); gl.bindTexture(gl.TEXTURE_2D, null); // draw end gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texture, 0); gl.bindFramebuffer(gl.FRAMEBUFFER, null); // swap textures var tmpTex = this.texturebuffer; this.texturebuffer = this.texture; this.texture = tmpTex; } function debugDraw() : void { var gl = Water.gl; var prog = Water.progDisp; var vloc = gl.getAttribLocation(prog, 'vertex'); gl.useProgram(prog); gl.uniformMatrix4fv(gl.getUniformLocation(prog, 'projectionMatrix'), false, new M44().setOrtho(0, 1, 0, 1, -1, 1).array()); gl.uniform2f(gl.getUniformLocation(prog, 'sampleStep'), 1/this.width, 1/this.height); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.bindBuffer(gl.ARRAY_BUFFER, Water.vbuf); gl.vertexAttribPointer(vloc, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(vloc); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); gl.disableVertexAttribArray(vloc); } function draw(projMat:M44, viewMat:M44, bgTex:WebGLTexture, w:number, h:number) : void { var gl = Water.gl; var prog = Water.drawProg; var vloc = gl.getAttribLocation(prog, 'vertex'); var tloc = gl.getAttribLocation(prog, 'texcoord'); gl.useProgram(prog); gl.uniformMatrix4fv(gl.getUniformLocation(prog, 'projectionMatrix'), false, projMat.array()); gl.uniformMatrix4fv(gl.getUniformLocation(prog, 'modelviewMatrix'), false, viewMat.array()); gl.uniform2f(gl.getUniformLocation(prog, 'texSize'), w, h); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, this.texture); gl.uniform1i(gl.getUniformLocation(prog, 'waveTexture'), 1); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, bgTex); gl.uniform1i(gl.getUniformLocation(prog, 'bgTexture'), 0); gl.bindBuffer(gl.ARRAY_BUFFER, Water.drawVBuf); gl.vertexAttribPointer(vloc, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(vloc); gl.bindBuffer(gl.ARRAY_BUFFER, Water.drawTBuf); gl.vertexAttribPointer(tloc, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(tloc); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); gl.disableVertexAttribArray(vloc); gl.disableVertexAttribArray(tloc); } function setImpulse(x:number, y:number, r:number, z:number) : void { this._ix = x; this._iy = y; this._ir = r; this._iz = z; } }