API Documentation
1 /* 2 GLGE WebGL Graphics Engine 3 Copyright (c) 2010, Paul Brunt 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions are met: 8 * Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in the 12 documentation and/or other materials provided with the distribution. 13 * Neither the name of GLGE nor the 14 names of its contributors may be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 DISCLAIMED. IN NO EVENT SHALL PAUL BRUNT BE LIABLE FOR ANY 21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @fileOverview 31 * @name glge_texturecamera.js 32 * @author me@paulbrunt.co.uk 33 */ 34 35 36 (function(GLGE){ 37 38 39 40 41 42 43 /** 44 * @class A reflection texture will reflect in a plane for a specified transform 45 * @param {string} uid the unique id for this texture 46 * @see GLGE.Material 47 * @augments GLGE.QuickNotation 48 * @augments GLGE.JSONLoader 49 */ 50 GLGE.TextureCamera=function(uid){ 51 GLGE.Assets.registerAsset(this,uid); 52 } 53 GLGE.augment(GLGE.QuickNotation,GLGE.TextureCamera); 54 GLGE.augment(GLGE.JSONLoader,GLGE.TextureCamera); 55 GLGE.augment(GLGE.Events,GLGE.TextureCamera); 56 GLGE.TextureCamera.prototype.className="Texture"; 57 GLGE.TextureCamera.prototype.texture=null; 58 GLGE.TextureCamera.prototype.glTexture=null; 59 GLGE.TextureCamera.prototype.object=null; 60 GLGE.TextureCamera.prototype.camera=null; 61 GLGE.TextureCamera.prototype.bufferHeight=0; 62 GLGE.TextureCamera.prototype.bufferWidth=0; 63 GLGE.TextureCamera.prototype.planeOffset=0; 64 GLGE.TextureCamera.prototype.mirrorAxis=GLGE.NONE; 65 GLGE.TextureCamera.prototype.clipAxis=GLGE.NONE; 66 67 68 /** 69 * sets the RTT render clipping plane offset 70 * @param {number} buffer width 71 **/ 72 GLGE.TextureCamera.prototype.setPlaneOffset=function(planeoffset){ 73 this.planeOffset=planeoffset; 74 return this; 75 } 76 /** 77 * gets the RTT render clipping plane offset 78 * @returns the width 79 **/ 80 GLGE.TextureCamera.prototype.getPlaneOffset=function(){ 81 return this.planeOffset; 82 } 83 84 85 /** 86 * sets the RTT render buffer width 87 * @param {number} buffer width 88 **/ 89 GLGE.TextureCamera.prototype.setBufferWidth=function(width){ 90 this.bufferWidth=width; 91 this.update=true; 92 return this; 93 } 94 /** 95 * gets the RTT render buffer width 96 * @returns the width 97 **/ 98 GLGE.TextureCamera.prototype.getBufferWidth=function(){ 99 return this.bufferWidth; 100 } 101 102 /** 103 * sets the RTT render buffer height 104 * @param {number} buffer height 105 **/ 106 GLGE.TextureCamera.prototype.setBufferHeight=function(height){ 107 this.bufferHeight=height; 108 this.update=true; 109 return this; 110 } 111 /** 112 * gets the RTT render buffer height 113 * @returns the height 114 **/ 115 GLGE.TextureCamera.prototype.getBufferHeight=function(){ 116 return this.bufferHeight; 117 } 118 119 /** 120 * sets the RTT clip axis 121 * @param {number} the axis 122 **/ 123 GLGE.TextureCamera.prototype.setClipAxis=function(camera){ 124 this.clipAxis=camera; 125 return this; 126 } 127 /** 128 * gets the RTT clip axis 129 * @returns the axis 130 **/ 131 GLGE.TextureCamera.prototype.getClipAxis=function(){ 132 return this.clipAxis; 133 } 134 135 /** 136 * sets the RTT mirror axis 137 * @param {number} the axis 138 **/ 139 GLGE.TextureCamera.prototype.setMirrorAxis=function(camera){ 140 this.mirrorAxis=camera; 141 return this; 142 } 143 /** 144 * gets the RTT mirror axis 145 * @returns the axis 146 **/ 147 GLGE.TextureCamera.prototype.getMirrorAxis=function(){ 148 return this.mirrorAxis; 149 } 150 151 /** 152 * sets the RTT camera to use 153 * @param {GLGE.Camera} the source camera 154 **/ 155 GLGE.TextureCamera.prototype.setCamera=function(camera){ 156 this.camera=camera; 157 return this; 158 } 159 /** 160 * gets the RTT source camera 161 * @returns {GLGE.Camera} the source camera 162 **/ 163 GLGE.TextureCamera.prototype.getCamera=function(){ 164 return this.camera; 165 } 166 167 /** 168 * does what is needed to get the texture 169 * @private 170 **/ 171 GLGE.TextureCamera.prototype.doTexture=function(gl,object){ 172 if(this.camera){ 173 this.gl=gl; 174 var modelmatrix=object.getModelMatrix(); 175 var pmatrix=gl.scene.camera.getProjectionMatrix(); 176 var cameramatrix=this.camera.getViewMatrix(); 177 var matrix; 178 179 if(this.mirrorAxis){ 180 switch(this.mirrorAxis){ 181 case GLGE.XAXIS: 182 matrix=GLGE.mulMat4(GLGE.mulMat4(GLGE.mulMat4(cameramatrix,modelmatrix),GLGE.scaleMatrix(-1,1,1)),GLGE.inverseMat4(modelmatrix)); 183 break; 184 case GLGE.YAXIS: 185 matrix=GLGE.mulMat4(GLGE.mulMat4(GLGE.mulMat4(cameramatrix,modelmatrix),GLGE.scaleMatrix(1,-1,1)),GLGE.inverseMat4(modelmatrix)); 186 break; 187 case GLGE.ZAXIS: 188 matrix=GLGE.mulMat4(GLGE.mulMat4(GLGE.mulMat4(cameramatrix,modelmatrix),GLGE.scaleMatrix(1,1,-1)),GLGE.inverseMat4(modelmatrix)); 189 break; 190 } 191 }else{ 192 matrix=cameramatrix; 193 } 194 195 if(this.clipAxis){ 196 var clipplane 197 switch(this.clipAxis){ 198 case GLGE.NEG_XAXIS: 199 var dirnorm=GLGE.toUnitVec3([-modelmatrix[0],-modelmatrix[4],-modelmatrix[8]]); 200 clipplane=[dirnorm[0],dirnorm[1],dirnorm[2],-GLGE.dotVec3([modelmatrix[3],modelmatrix[7],modelmatrix[11]],dirnorm)-this.planeOffset]; 201 break; 202 case GLGE.POS_XAXIS: 203 var dirnorm=GLGE.toUnitVec3([modelmatrix[0],modelmatrix[4],modelmatrix[8]]); 204 clipplane=[dirnorm[0],dirnorm[1],dirnorm[2],-GLGE.dotVec3([modelmatrix[3],modelmatrix[7],modelmatrix[11]],dirnorm)-this.planeOffset]; 205 break; 206 case GLGE.NEG_YAXIS: 207 var dirnorm=GLGE.toUnitVec3([-modelmatrix[1],-modelmatrix[5],-modelmatrix[9]]); 208 clipplane=[dirnorm[0],dirnorm[1],dirnorm[2],-GLGE.dotVec3([modelmatrix[3],modelmatrix[7],modelmatrix[11]],dirnorm)-this.planeOffset]; 209 break; 210 case GLGE.POS_YAXIS: 211 var dirnorm=GLGE.toUnitVec3([modelmatrix[1],modelmatrix[5],modelmatrix[9]]); 212 clipplane=[dirnorm[0],dirnorm[1],dirnorm[2],-GLGE.dotVec3([modelmatrix[3],modelmatrix[7],modelmatrix[11]],dirnorm)-this.planeOffset]; 213 break; 214 case GLGE.NEG_ZAXIS: 215 var dirnorm=GLGE.toUnitVec3([-modelmatrix[2],-modelmatrix[6],-modelmatrix[10]]); 216 clipplane=[dirnorm[0],dirnorm[1],dirnorm[2],-GLGE.dotVec3([modelmatrix[3],modelmatrix[7],modelmatrix[11]],dirnorm)-this.planeOffset]; 217 break; 218 case GLGE.POS_ZAXIS: 219 var dirnorm=GLGE.toUnitVec3([modelmatrix[2],modelmatrix[6],modelmatrix[10]]); 220 clipplane=[dirnorm[0],dirnorm[1],dirnorm[2],-GLGE.dotVec3([modelmatrix[3],modelmatrix[7],modelmatrix[11]],dirnorm)-this.planeOffset]; 221 break; 222 } 223 224 225 226 var itmvp=GLGE.transposeMat4(GLGE.inverseMat4(GLGE.mulMat4(pmatrix,matrix))); 227 228 clipplane=GLGE.mulMat4Vec4(itmvp,clipplane); 229 clipplane=GLGE.scaleVec4(clipplane,pmatrix[10]); 230 clipplane[3] -= 1; 231 if(clipplane[2]<0) GLGE.scaleVec4(clipplane,-1); 232 var suffix=[ 1,0,0,0, 233 0,1,0,0, 234 clipplane[0],clipplane[1],clipplane[2],clipplane[3], 235 0,0,0,1]; 236 pmatrix=GLGE.mulMat4(suffix,pmatrix); 237 238 } 239 var height=(!this.bufferHeight ? gl.scene.renderer.canvas.height : this.bufferHeight); 240 var width=(!this.bufferWidth ? gl.scene.renderer.canvas.width : this.bufferWidth); 241 242 //create the texture if it's not already created 243 if(!this.glTexture || this.update){ 244 this.createFrameBuffer(gl); 245 gl.scene.addRenderPass(this.frameBuffer,matrix, gl.scene.camera.getProjectionMatrix(),width,height,object); 246 gl.bindTexture(gl.TEXTURE_2D, this.glTexture); 247 this.update=false; 248 return false; 249 }else{ 250 gl.bindTexture(gl.TEXTURE_2D, this.glTexture); 251 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 252 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 253 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 254 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 255 gl.scene.addRenderPass(this.frameBuffer,matrix, pmatrix,width,height,object); 256 return true; 257 } 258 259 }else{ 260 return false; 261 } 262 } 263 GLGE.TextureCamera.prototype.registerPasses=GLGE.TextureCamera.prototype.doTexture; 264 /** 265 * Creates the frame buffer for our texture 266 * @private 267 */ 268 GLGE.TextureCamera.prototype.createFrameBuffer=function(gl){ 269 var height=(!this.bufferHeight ? gl.scene.renderer.canvas.height : this.bufferHeight); 270 var width=(!this.bufferWidth ? gl.scene.renderer.canvas.width : this.bufferWidth); 271 272 if(!this.frameBuffer) this.frameBuffer = gl.createFramebuffer(); 273 if(!this.renderBuffer) this.renderBuffer = gl.createRenderbuffer(); 274 if(!this.glTexture) this.glTexture=gl.createTexture(); 275 gl.bindTexture(gl.TEXTURE_2D, this.glTexture); 276 277 var tex = new Uint8Array(width*height*4); 278 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width,height, 0, gl.RGBA, gl.UNSIGNED_BYTE, tex); 279 280 gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer); 281 282 gl.bindRenderbuffer(gl.RENDERBUFFER, this.renderBuffer); 283 //dpeth stencil doesn't seem to work in either webkit or mozilla so don't use for now - reflected particles will be messed up! 284 //gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL,width, height); 285 //gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, this.renderBuffer); 286 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16,width, height); 287 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.renderBuffer); 288 289 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.glTexture, 0); 290 291 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 292 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 293 gl.bindTexture(gl.TEXTURE_2D, null); 294 } 295 296 297 298 })(GLGE);