Fork me on GitHub

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);