API Documentation
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_text.js.html, line: 375 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_text.js.html, line: 376 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
Warning: DOMDocument::loadHTMLFile() [domdocument.loadhtmlfile]: htmlParseEntityRef: no name in jsdoc/symbols/src/src_renderable_glge_text.js.html, line: 377 in /homepages/22/d163487924/htdocs/glge/wp-content/themes/glge/manual.php on line 29
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_text.js 32 * @author me@paulbrunt.co.uk 33 */ 34 35 36 (function(GLGE){ 37 38 39 40 41 42 /** 43 * @class Text that can be rendered in a scene 44 * @augments GLGE.Animatable 45 * @augments GLGE.Placeable 46 * @augments GLGE.QuickNotation 47 * @augments GLGE.JSONLoader 48 */ 49 GLGE.Text=function(uid){ 50 this.canvas=document.createElement("canvas"); 51 this.scaleCanvas=document.createElement("canvas"); 52 this.color={r:1.0,g:1.0,b:1.0}; 53 GLGE.Assets.registerAsset(this,uid); 54 } 55 GLGE.augment(GLGE.Placeable,GLGE.Text); 56 GLGE.augment(GLGE.Animatable,GLGE.Text); 57 GLGE.augment(GLGE.QuickNotation,GLGE.Text); 58 GLGE.augment(GLGE.JSONLoader,GLGE.Text); 59 GLGE.Text.prototype.className="Text"; 60 GLGE.Text.prototype.zTrans=true; 61 GLGE.Text.prototype.canvas=null; 62 GLGE.Text.prototype.aspect=1.0; 63 GLGE.Text.prototype.color=null; 64 GLGE.Text.prototype.text=""; 65 GLGE.Text.prototype.font="Times"; 66 GLGE.Text.prototype.size=100; 67 GLGE.Text.prototype.pickType=GLGE.TEXT_TEXTPICK; 68 GLGE.Text.prototype.pickable=true; 69 GLGE.Text.prototype.alpha=1; 70 71 /** 72 * Gets the pick type for this text 73 * @returns {string} the pick type 74 */ 75 GLGE.Text.prototype.getPickType=function(){ 76 return this.pickType; 77 }; 78 /** 79 * Sets the pick type GLGE.TEXT_BOXPICK for picking based on bound box or GLGE.TEXT_TEXTPICK for pixel perfect text picking 80 * @param {Number} value the picking type 81 */ 82 GLGE.Text.prototype.setPickType=function(value){ 83 this.pickType=value; 84 return this; 85 }; 86 /** 87 * Gets the font of the text 88 * @returns {string} the font of the text 89 */ 90 GLGE.Text.prototype.getFont=function(){ 91 return this.size; 92 }; 93 /** 94 * Sets the font of the text 95 * @param {Number} value the font of the text 96 */ 97 GLGE.Text.prototype.setFont=function(value){ 98 this.font=value; 99 if(this.gl) this.updateCanvas(this.gl); 100 return this; 101 }; 102 /** 103 * Gets the size of the text 104 * @returns {string} the size of the text 105 */ 106 GLGE.Text.prototype.getSize=function(){ 107 return this.size; 108 }; 109 /** 110 * Sets the size of the text 111 * @param {Number} value the size of the text 112 */ 113 GLGE.Text.prototype.setSize=function(value){ 114 this.size=value; 115 if(this.gl) this.updateCanvas(this.gl); 116 return this; 117 }; 118 /** 119 * Gets the rendered text 120 * @returns {string} the text rendered 121 */ 122 GLGE.Text.prototype.getText=function(){ 123 return this.text; 124 }; 125 /** 126 * Sets the text to be rendered 127 * @param {Number} value the text to render 128 */ 129 GLGE.Text.prototype.setText=function(value){ 130 this.text=value; 131 if(this.gl) this.updateCanvas(this.gl); 132 return this; 133 }; 134 /** 135 * Sets the base colour of the text 136 * @param {string} color The colour of the material 137 */ 138 GLGE.Text.prototype.setColor=function(color){ 139 color=GLGE.colorParse(color); 140 this.color={r:color.r,g:color.g,b:color.b}; 141 return this; 142 }; 143 /** 144 * Sets the red base colour of the text 145 * @param {Number} r The new red level 0-1 146 */ 147 GLGE.Text.prototype.setColorR=function(value){ 148 this.color.r=value; 149 return this; 150 }; 151 /** 152 * Sets the green base colour of the text 153 * @param {Number} g The new green level 0-1 154 */ 155 GLGE.Text.prototype.setColorG=function(value){ 156 this.color.g=value; 157 return this; 158 }; 159 /** 160 * Sets the blue base colour of the text 161 * @param {Number} b The new blue level 0-1 162 */ 163 GLGE.Text.prototype.setColorB=function(value){ 164 this.color.b=value; 165 return this; 166 }; 167 /** 168 * Gets the current base color of the text 169 * @return {[r,g,b]} The current base color 170 */ 171 GLGE.Text.prototype.getColor=function(){ 172 return this.color; 173 return this; 174 }; 175 176 /** 177 * Sets the alpha 178 * @param {Number} b The new alpha level 0-1 179 */ 180 GLGE.Text.prototype.setAlpha=function(value){ 181 this.alpha=value; 182 return this; 183 }; 184 185 /** 186 * Gets the alpha 187 * @returns The alpha level 188 */ 189 GLGE.Text.prototype.getAlpha=function(){ 190 return this.alpha; 191 }; 192 193 /** 194 * Sets the Z Transparency of this text 195 * @param {boolean} value Does this object need blending? 196 */ 197 GLGE.Text.prototype.setZtransparent=function(value){ 198 this.zTrans=value; 199 return this; 200 } 201 /** 202 * Gets the z transparency 203 * @returns boolean 204 */ 205 GLGE.Text.prototype.isZtransparent=function(){ 206 return this.zTrans; 207 } 208 /** 209 * Creates the shader program for the object 210 * @private 211 */ 212 GLGE.Text.prototype.GLGenerateShader=function(gl){ 213 if(this.GLShaderProgram) gl.deleteProgram(this.GLShaderProgram); 214 215 //Vertex Shader 216 var vertexStr=""; 217 vertexStr+="attribute vec3 position;\n"; 218 vertexStr+="attribute vec2 uvcoord;\n"; 219 vertexStr+="varying vec2 texcoord;\n"; 220 vertexStr+="uniform mat4 Matrix;\n"; 221 vertexStr+="uniform mat4 PMatrix;\n"; 222 vertexStr+="varying vec4 pos;\n"; 223 224 vertexStr+="void main(void){\n"; 225 vertexStr+="texcoord=uvcoord;\n"; 226 vertexStr+="pos = Matrix * vec4(position,1.0);\n"; 227 vertexStr+="gl_Position = PMatrix * pos;\n"; 228 vertexStr+="}\n"; 229 230 //Fragment Shader 231 var fragStr="#ifdef GL_ES\nprecision highp float;\n#endif\n"; 232 fragStr=fragStr+"uniform sampler2D TEXTURE;\n"; 233 fragStr=fragStr+"varying vec2 texcoord;\n"; 234 fragStr=fragStr+"uniform mat4 Matrix;\n"; 235 fragStr=fragStr+"varying vec4 pos;\n"; 236 fragStr=fragStr+"uniform float far;\n"; 237 fragStr=fragStr+"uniform bool depthrender;\n"; 238 fragStr=fragStr+"uniform float distance;\n"; 239 fragStr=fragStr+"uniform int picktype;\n"; 240 fragStr=fragStr+"uniform vec3 pickcolor;\n"; 241 fragStr=fragStr+"uniform vec3 color;\n"; 242 fragStr=fragStr+"uniform float alpha;\n"; 243 fragStr=fragStr+"void main(void){\n"; 244 fragStr=fragStr+"float ob=pow(min(1.0,abs(dot(normalize(Matrix[2].rgb),vec3(0.0,0.0,1.0)))*2.0),1.5);\n"; 245 fragStr=fragStr+"float a=texture2D(TEXTURE,texcoord).a*alpha*ob;\n"; 246 fragStr=fragStr+"if(picktype=="+GLGE.TEXT_BOXPICK+"){gl_FragColor = vec4(pickcolor,1.0);}" 247 fragStr=fragStr+"else if(picktype=="+GLGE.TEXT_TEXTPICK+"){if(alpha<1.0) discard; gl_FragColor = vec4(pickcolor,alpha);}" 248 fragStr=fragStr+"else{gl_FragColor = vec4(color.rgb,a);};\n"; 249 fragStr=fragStr+"if (depthrender) { if(a<0.5) discard; float depth = gl_FragCoord.z / gl_FragCoord.w;\n"; 250 fragStr=fragStr+"vec4 rgba=fract(depth/distance * vec4(16777216.0, 65536.0, 256.0, 1.0));\n"; 251 fragStr=fragStr+"gl_FragColor=rgba-rgba.rrgb*vec4(0.0,0.00390625,0.00390625,0.00390625);}\n"; 252 fragStr=fragStr+"}\n"; 253 254 this.GLFragmentShader=gl.createShader(gl.FRAGMENT_SHADER); 255 this.GLVertexShader=gl.createShader(gl.VERTEX_SHADER); 256 257 258 gl.shaderSource(this.GLFragmentShader, fragStr); 259 gl.compileShader(this.GLFragmentShader); 260 if (!gl.getShaderParameter(this.GLFragmentShader, gl.COMPILE_STATUS)) { 261 GLGE.error(gl.getShaderInfoLog(this.GLFragmentShader)); 262 return; 263 } 264 265 //set and compile the vertex shader 266 //need to set str 267 gl.shaderSource(this.GLVertexShader, vertexStr); 268 gl.compileShader(this.GLVertexShader); 269 if (!gl.getShaderParameter(this.GLVertexShader, gl.COMPILE_STATUS)) { 270 GLGE.error(gl.getShaderInfoLog(this.GLVertexShader)); 271 return; 272 } 273 274 this.GLShaderProgram = gl.createProgram(); 275 gl.attachShader(this.GLShaderProgram, this.GLVertexShader); 276 gl.attachShader(this.GLShaderProgram, this.GLFragmentShader); 277 gl.linkProgram(this.GLShaderProgram); 278 } 279 /** 280 * Initiallize all the GL stuff needed to render to screen 281 * @private 282 */ 283 GLGE.Text.prototype.GLInit=function(gl){ 284 this.gl=gl; 285 this.createPlane(gl); 286 this.GLGenerateShader(gl); 287 288 this.glTexture=gl.createTexture(); 289 this.updateCanvas(gl); 290 } 291 /** 292 * Updates the canvas texture 293 * @private 294 */ 295 GLGE.Text.prototype.updateCanvas=function(gl){ 296 var canvas = this.canvas; 297 canvas.width=1; 298 canvas.height=this.size*1.2; 299 var ctx = canvas.getContext("2d"); 300 ctx.font = this.size+"px "+this.font; 301 canvas.width=ctx.measureText(this.text).width; 302 canvas.height=this.size*1.2; 303 ctx = canvas.getContext("2d"); 304 ctx.textBaseline="top"; 305 ctx.font = (this.extra||"") + " " + this.size+"px "+this.font; 306 this.aspect=canvas.width/canvas.height; 307 ctx.fillText(this.text, 0, 0); 308 309 var height=Math.pow(2,Math.ceil(Math.log(canvas.height))/(Math.log(2))); 310 var width=Math.pow(2,Math.ceil(Math.log(canvas.width))/(Math.log(2))); 311 312 this.scaleCanvas.height=height; 313 this.scaleCanvas.width=width; 314 315 this.scaleContext=this.scaleCanvas.getContext("2d"); 316 this.scaleContext.clearRect(0,0,width,height); 317 this.scaleContext.drawImage(canvas, 0, 0, width, height); 318 319 gl.bindTexture(gl.TEXTURE_2D, this.glTexture); 320 //TODO: fix this when minefield is upto spec 321 try{gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.scaleCanvas);} 322 catch(e){gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.scaleCanvas,null);} 323 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 324 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 325 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR_MIPMAP_LINEAR); 326 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 327 gl.generateMipmap(gl.TEXTURE_2D); 328 329 gl.bindTexture(gl.TEXTURE_2D, null); 330 } 331 332 /** 333 * Renders the text to the render buffer 334 * @private 335 */ 336 GLGE.Text.prototype.GLRender=function(gl,renderType,pickindex){ 337 if(!this.gl){ 338 this.GLInit(gl); 339 } 340 if(renderType==GLGE.RENDER_DEFAULT || renderType==GLGE.RENDER_PICK || renderType==GLGE.RENDER_SHADOW){ 341 //if look at is set then look 342 if(this.lookAt) this.Lookat(this.lookAt); 343 344 if(gl.program!=this.GLShaderProgram){ 345 gl.useProgram(this.GLShaderProgram); 346 gl.program=this.GLShaderProgram; 347 } 348 349 var attribslot; 350 //disable all the attribute initially arrays - do I really need this? 351 for(var i=0; i<8; i++) gl.disableVertexAttribArray(i); 352 attribslot=GLGE.getAttribLocation(gl,this.GLShaderProgram, "position"); 353 354 gl.bindBuffer(gl.ARRAY_BUFFER, this.posBuffer); 355 gl.enableVertexAttribArray(attribslot); 356 gl.vertexAttribPointer(attribslot, this.posBuffer.itemSize, gl.FLOAT, false, 0, 0); 357 358 attribslot=GLGE.getAttribLocation(gl,this.GLShaderProgram, "uvcoord"); 359 gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); 360 gl.enableVertexAttribArray(attribslot); 361 gl.vertexAttribPointer(attribslot, this.uvBuffer.itemSize, gl.FLOAT, false, 0, 0); 362 363 gl.activeTexture(gl["TEXTURE0"]); 364 gl.bindTexture(gl.TEXTURE_2D, this.glTexture); 365 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "TEXTURE"),0); 366 367 if(!pickindex) pickindex=0; 368 var b = pickindex >> 16 & 0xFF; 369 var g = pickindex >> 8 & 0xFF; 370 var r = pickindex & 0xFF; 371 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,this.GLShaderProgram, "pickcolor"),r/255,g/255,b/255); 372 373 if(renderType==GLGE.RENDER_PICK){ 374 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "picktype"), this.pickType); 375 }else{ 376 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "picktype"), 0); 377 } 378 var distance=gl.scene.camera.getFar(); 379 GLGE.setUniform(gl,"1f",GLGE.getUniformLocation(gl,this.GLShaderProgram, "distance"), distance); 380 if(renderType==GLGE.RENDER_SHADOW){ 381 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "depthrender"), 1); 382 }else{ 383 GLGE.setUniform(gl,"1i",GLGE.getUniformLocation(gl,this.GLShaderProgram, "depthrender"), 0); 384 } 385 386 387 if(!this.GLShaderProgram.glarrays) this.GLShaderProgram.glarrays={}; 388 389 390 //generate and set the modelView matrix 391 var scalefactor=this.size/100; 392 var mMatrix=GLGE.mulMat4(gl.scene.camera.getViewMatrix(),GLGE.mulMat4(this.getModelMatrix(),GLGE.scaleMatrix(this.aspect*scalefactor,scalefactor,scalefactor))); 393 var mUniform = GLGE.getUniformLocation(gl,this.GLShaderProgram, "Matrix"); 394 if(!this.GLShaderProgram.glarrays.mMatrix) this.GLShaderProgram.glarrays.mMatrix=new Float32Array(mMatrix); 395 else GLGE.mat4gl(mMatrix,this.GLShaderProgram.glarrays.mMatrix); 396 GLGE.setUniformMatrix(gl,"Matrix4fv",mUniform, true, this.GLShaderProgram.glarrays.mMatrix); 397 398 var mUniform = GLGE.getUniformLocation(gl,this.GLShaderProgram, "PMatrix"); 399 400 if(!this.GLShaderProgram.glarrays.pMatrix) this.GLShaderProgram.glarrays.pMatrix=new Float32Array(gl.scene.camera.getProjectionMatrix()); 401 else GLGE.mat4gl(gl.scene.camera.getProjectionMatrix(),this.GLShaderProgram.glarrays.pMatrix); 402 GLGE.setUniformMatrix(gl,"Matrix4fv",mUniform, true, this.GLShaderProgram.glarrays.pMatrix); 403 404 var farUniform = GLGE.getUniformLocation(gl,this.GLShaderProgram, "far"); 405 GLGE.setUniform(gl,"1f",farUniform, gl.scene.camera.getFar()); 406 407 var alphaUniform = GLGE.getUniformLocation(gl,this.GLShaderProgram, "alpha"); 408 GLGE.setUniform(gl,"1f",alphaUniform, this.alpha); 409 410 //set the color 411 GLGE.setUniform3(gl,"3f",GLGE.getUniformLocation(gl,this.GLShaderProgram, "color"), this.color.r,this.color.g,this.color.b); 412 413 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.GLfaces); 414 gl.drawElements(gl.TRIANGLES, this.GLfaces.numItems, gl.UNSIGNED_SHORT, 0); 415 gl.scene.lastMaterial=null; 416 } 417 } 418 /** 419 * creates the plane mesh to draw 420 * @private 421 */ 422 GLGE.Text.prototype.createPlane=function(gl){ 423 //create the vertex positions 424 if(!this.posBuffer) this.posBuffer = gl.createBuffer(); 425 gl.bindBuffer(gl.ARRAY_BUFFER, this.posBuffer); 426 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1,1,0,-1,1,0,-1,-1,0,1,-1,0]), gl.STATIC_DRAW); 427 this.posBuffer.itemSize = 3; 428 this.posBuffer.numItems = 4; 429 //create the vertex uv coords 430 if(!this.uvBuffer) this.uvBuffer = gl.createBuffer(); 431 gl.bindBuffer(gl.ARRAY_BUFFER, this.uvBuffer); 432 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0,0,1,0,1,1,0,1]), gl.STATIC_DRAW); 433 this.uvBuffer.itemSize = 2; 434 this.uvBuffer.numItems = 4; 435 //create the faces 436 if(!this.GLfaces) this.GLfaces = gl.createBuffer(); 437 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.GLfaces); 438 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([2,1,0,0,3,2]), gl.STATIC_DRAW); 439 this.GLfaces.itemSize = 1; 440 this.GLfaces.numItems = 6; 441 } 442 443 444 })(GLGE);