1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright 2011 Jeff Lamarche 5 Copyright 2012 Goffredo Marocchi 6 Copyright (c) 2011 Zynga Inc. 7 8 http://www.cocos2d-x.org 9 10 Permission is hereby granted, free of charge, to any person obtaining a copy 11 of this software and associated documentation files (the "Software"), to deal 12 in the Software without restriction, including without limitation the rights 13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 copies of the Software, and to permit persons to whom the Software is 15 furnished to do so, subject to the following conditions: 16 17 The above copyright notice and this permission notice shall be included in 18 all copies or substantial portions of the Software. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 THE SOFTWARE. 27 ****************************************************************************/ 28 29 //-------------Vertex Attributes----------- 30 /** 31 * @constant 32 * @type {Number} 33 */ 34 cc.VERTEX_ATTRIB_POSITION = 0; 35 /** 36 * @constant 37 * @type {Number} 38 */ 39 cc.VERTEX_ATTRIB_COLOR = 1; 40 /** 41 * @constant 42 * @type {Number} 43 */ 44 cc.VERTEX_ATTRIB_TEX_COORDS = 2; 45 /** 46 * @constant 47 * @type {Number} 48 */ 49 cc.VERTEX_ATTRIB_MAX = 3; 50 51 //------------Uniforms------------------ 52 /** 53 * @constant 54 * @type {Number} 55 */ 56 cc.UNIFORM_PMATRIX = 0; 57 /** 58 * @constant 59 * @type {Number} 60 */ 61 cc.UNIFORM_MVMATRIX = 1; 62 /** 63 * @constant 64 * @type {Number} 65 */ 66 cc.UNIFORM_MVPMATRIX = 2; 67 /** 68 * @constant 69 * @type {Number} 70 */ 71 cc.UNIFORM_TIME = 3; 72 /** 73 * @constant 74 * @type {Number} 75 */ 76 cc.UNIFORM_SINTIME = 4; 77 /** 78 * @constant 79 * @type {Number} 80 */ 81 cc.UNIFORM_COSTIME = 5; 82 /** 83 * @constant 84 * @type {Number} 85 */ 86 cc.UNIFORM_RANDOM01 = 6; 87 /** 88 * @constant 89 * @type {Number} 90 */ 91 cc.UNIFORM_SAMPLER = 7; 92 /** 93 * @constant 94 * @type {Number} 95 */ 96 cc.UNIFORM_MAX = 8; 97 98 //------------Shader Name--------------- 99 /** 100 * @constant 101 * @type {String} 102 */ 103 cc.SHADER_POSITION_TEXTURECOLOR = "ShaderPositionTextureColor"; 104 /** 105 * @constant 106 * @type {String} 107 */ 108 cc.SHADER_POSITION_TEXTURECOLORALPHATEST = "ShaderPositionTextureColorAlphaTest"; 109 /** 110 * @constant 111 * @type {String} 112 */ 113 cc.SHADER_POSITION_COLOR = "ShaderPositionColor"; 114 /** 115 * @constant 116 * @type {String} 117 */ 118 cc.SHADER_POSITION_TEXTURE = "ShaderPositionTexture"; 119 /** 120 * @constant 121 * @type {String} 122 */ 123 cc.SHADER_POSITION_TEXTURE_UCOLOR = "ShaderPositionTexture_uColor"; 124 /** 125 * @constant 126 * @type {String} 127 */ 128 cc.SHADER_POSITION_TEXTUREA8COLOR = "ShaderPositionTextureA8Color"; 129 /** 130 * @constant 131 * @type {String} 132 */ 133 cc.SHADER_POSITION_UCOLOR = "ShaderPosition_uColor"; 134 /** 135 * @constant 136 * @type {String} 137 */ 138 cc.SHADER_POSITION_LENGTHTEXTURECOLOR = "ShaderPositionLengthTextureColor"; 139 140 //------------uniform names---------------- 141 /** 142 * @constant 143 * @type {String} 144 */ 145 cc.UNIFORM_PMATRIX_S = "CC_PMatrix"; 146 /** 147 * @constant 148 * @type {String} 149 */ 150 cc.UNIFORM_MVMATRIX_S = "CC_MVMatrix"; 151 /** 152 * @constant 153 * @type {String} 154 */ 155 cc.UNIFORM_MVPMATRIX_S = "CC_MVPMatrix"; 156 /** 157 * @constant 158 * @type {String} 159 */ 160 cc.UNIFORM_TIME_S = "CC_Time"; 161 /** 162 * @constant 163 * @type {String} 164 */ 165 cc.UNIFORM_SINTIME_S = "CC_SinTime"; 166 /** 167 * @constant 168 * @type {String} 169 */ 170 cc.UNIFORM_COSTIME_S = "CC_CosTime"; 171 /** 172 * @constant 173 * @type {String} 174 */ 175 cc.UNIFORM_RANDOM01_S = "CC_Random01"; 176 /** 177 * @constant 178 * @type {String} 179 */ 180 cc.UNIFORM_SAMPLER_S = "CC_Texture0"; 181 /** 182 * @constant 183 * @type {String} 184 */ 185 cc.UNIFORM_ALPHA_TEST_VALUE_S = "CC_alpha_value"; 186 187 //------------Attribute names-------------- 188 /** 189 * @constant 190 * @type {String} 191 */ 192 cc.ATTRIBUTE_NAME_COLOR = "a_color"; 193 /** 194 * @constant 195 * @type {String} 196 */ 197 cc.ATTRIBUTE_NAME_POSITION = "a_position"; 198 /** 199 * @constant 200 * @type {String} 201 */ 202 cc.ATTRIBUTE_NAME_TEX_COORD = "a_texCoord"; 203 204 cc.HashUniformEntry = function (value, location, hh) { 205 this.value = value; 206 this.location = location; 207 this.hh = hh || {}; 208 }; 209 210 /** 211 * Class that implements a glProgram 212 * @class 213 * @extends cc.Class 214 */ 215 cc.GLProgram = cc.Class.extend({ 216 _glContext: null, 217 _programObj: null, 218 _vertShader: null, 219 _fragShader: null, 220 _uniforms: null, 221 _hashForUniforms: null, 222 _usesTime: false, 223 224 // Uniform cache 225 _updateUniformLocation: function (location, data, bytes) { 226 if (location == null) 227 return false; 228 229 var updated = true; 230 var element = null; 231 for (var i = 0; i < this._hashForUniforms.length; i++) 232 if (this._hashForUniforms[i].location == location) 233 element = this._hashForUniforms[i]; 234 235 if (!element) { 236 element = new cc.HashUniformEntry(); 237 // key 238 element.location = location; 239 // value 240 element.value = data; 241 this._hashForUniforms.push(element); 242 } else { 243 if (element.value == data) 244 updated = false; 245 else 246 element.value = data; 247 } 248 249 return updated; 250 }, 251 252 _description: function () { 253 return "<CCGLProgram = " + this.toString() + " | Program = " + this._programObj.toString() + ", VertexShader = " + 254 this._vertShader.toString() + ", FragmentShader = " + this._fragShader.toString() + ">"; 255 }, 256 257 _compileShader: function (shader, type, source) { 258 if (!source || !shader) 259 return false; 260 261 var preStr = (type == this._glContext.VERTEX_SHADER) ? "precision highp float;\n" : "precision mediump float;\n"; 262 263 source = preStr 264 + "uniform mat4 CC_PMatrix; \n" 265 + "uniform mat4 CC_MVMatrix; \n" 266 + "uniform mat4 CC_MVPMatrix; \n" 267 + "uniform vec4 CC_Time; \n" 268 + "uniform vec4 CC_SinTime; \n" 269 + "uniform vec4 CC_CosTime; \n" 270 + "uniform vec4 CC_Random01; \n" 271 + "//CC INCLUDES END \n \n" + source; 272 273 this._glContext.shaderSource(shader, source); 274 this._glContext.compileShader(shader); 275 var status = this._glContext.getShaderParameter(shader, this._glContext.COMPILE_STATUS); 276 277 if (!status) { 278 cc.log("cocos2d: ERROR: Failed to compile shader:\n" + this._glContext.getShaderSource(shader)); 279 if (type == this._glContext.VERTEX_SHADER) 280 cc.log("cocos2d: \n" + this.vertexShaderLog()); 281 else 282 cc.log("cocos2d: \n" + this.fragmentShaderLog()); 283 } 284 return ( status == 1 ); 285 }, 286 287 ctor: function (glContext) { 288 this._programObj = null; 289 this._vertShader = null; 290 this._fragShader = null; 291 this._uniforms = []; 292 this._hashForUniforms = []; 293 this._glContext = glContext || cc.renderContext; 294 }, 295 296 destroyProgram: function () { 297 this._vertShader = null; 298 this._fragShader = null; 299 this._uniforms = null; 300 this._hashForUniforms = null; 301 302 this._glContext.deleteProgram(this._programObj); 303 }, 304 305 /** 306 * Initializes the cc.GLProgram with a vertex and fragment with string 307 * @param {String} vertShaderStr 308 * @param {String} fragShaderStr 309 * @return {Boolean} 310 */ 311 initWithVertexShaderByteArray: function (vertShaderStr, fragShaderStr) { 312 this._programObj = cc.renderContext.createProgram(); 313 //cc.CHECK_GL_ERROR_DEBUG(); 314 315 this._vertShader = null; 316 this._fragShader = null; 317 318 if (vertShaderStr) { 319 this._vertShader = this._glContext.createShader(this._glContext.VERTEX_SHADER); 320 if (!this._compileShader(this._vertShader, this._glContext.VERTEX_SHADER, vertShaderStr)) { 321 cc.log("cocos2d: ERROR: Failed to compile vertex shader"); 322 } 323 } 324 325 // Create and compile fragment shader 326 if (fragShaderStr) { 327 this._fragShader = this._glContext.createShader(this._glContext.FRAGMENT_SHADER); 328 if (!this._compileShader(this._fragShader, this._glContext.FRAGMENT_SHADER, fragShaderStr)) { 329 cc.log("cocos2d: ERROR: Failed to compile fragment shader"); 330 } 331 } 332 333 if (this._vertShader) 334 this._glContext.attachShader(this._programObj, this._vertShader); 335 cc.CHECK_GL_ERROR_DEBUG(); 336 337 if (this._fragShader) 338 this._glContext.attachShader(this._programObj, this._fragShader); 339 this._hashForUniforms = []; 340 341 cc.CHECK_GL_ERROR_DEBUG(); 342 return true; 343 }, 344 345 /** 346 * Initializes the cc.GLProgram with a vertex and fragment with string 347 * @param {String} vertShaderStr 348 * @param {String} fragShaderStr 349 * @return {Boolean} 350 */ 351 initWithString: function (vertShaderStr, fragShaderStr) { 352 return this.initWithVertexShaderByteArray(vertShaderStr, fragShaderStr); 353 }, 354 355 /** 356 * Initializes the CCGLProgram with a vertex and fragment with contents of filenames 357 * @param {String} vShaderFilename 358 * @param {String} fShaderFileName 359 * @return {Boolean} 360 */ 361 initWithVertexShaderFilename: function (vShaderFilename, fShaderFileName) { 362 var fileUtils = cc.FileUtils.getInstance(); 363 var vertexSource = fileUtils.getTextFileData(fileUtils.fullPathForFilename(vShaderFilename)); 364 var fragmentSource = fileUtils.getTextFileData(fileUtils.fullPathForFilename(fShaderFileName)); 365 return this.initWithVertexShaderByteArray(vertexSource, fragmentSource); 366 }, 367 368 /** 369 * Initializes the CCGLProgram with a vertex and fragment with contents of filenames 370 * @param {String} vShaderFilename 371 * @param {String} fShaderFileName 372 * @return {Boolean} 373 */ 374 init: function (vShaderFilename, fShaderFileName) { 375 return this.initWithVertexShaderFilename(vShaderFilename, fShaderFileName); 376 }, 377 378 /** 379 * It will add a new attribute to the shader 380 * @param {String} attributeName 381 * @param {Number} index 382 */ 383 addAttribute: function (attributeName, index) { 384 this._glContext.bindAttribLocation(this._programObj, index, attributeName); 385 }, 386 387 /** 388 * links the glProgram 389 * @return {Boolean} 390 */ 391 link: function () { 392 cc.Assert(this._programObj != null, "Cannot link invalid program"); 393 394 this._glContext.linkProgram(this._programObj); 395 396 if (this._vertShader) 397 this._glContext.deleteShader(this._vertShader); 398 if (this._fragShader) 399 this._glContext.deleteShader(this._fragShader); 400 401 this._vertShader = null; 402 this._fragShader = null; 403 404 if (cc.COCOS2D_DEBUG) { 405 var status = this._glContext.getProgramParameter(this._programObj, this._glContext.LINK_STATUS); 406 if (!status) { 407 cc.log("cocos2d: ERROR: Failed to link program: " + this._programObj); 408 cc.glDeleteProgram(this._programObj); 409 this._programObj = null; 410 return false; 411 } 412 } 413 414 return true; 415 }, 416 417 /** 418 * it will call glUseProgram() 419 */ 420 use: function () { 421 cc.glUseProgram(this._programObj); 422 }, 423 424 /** 425 * It will create 4 uniforms: 426 * cc.UNIFORM_PMATRIX 427 * cc.UNIFORM_MVMATRIX 428 * cc.UNIFORM_MVPMATRIX 429 * cc.UNIFORM_SAMPLER 430 */ 431 updateUniforms: function () { 432 this._uniforms[cc.UNIFORM_PMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_PMATRIX_S); 433 this._uniforms[cc.UNIFORM_MVMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVMATRIX_S); 434 this._uniforms[cc.UNIFORM_MVPMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVPMATRIX_S); 435 this._uniforms[cc.UNIFORM_TIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_TIME_S); 436 this._uniforms[cc.UNIFORM_SINTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SINTIME_S); 437 this._uniforms[cc.UNIFORM_COSTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_COSTIME_S); 438 439 this._usesTime = (this._uniforms[cc.UNIFORM_TIME] != null || this._uniforms[cc.UNIFORM_SINTIME] != null || this._uniforms[cc.UNIFORM_COSTIME] != null); 440 441 this._uniforms[cc.UNIFORM_RANDOM01] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_RANDOM01_S); 442 this._uniforms[cc.UNIFORM_SAMPLER] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SAMPLER_S); 443 444 this.use(); 445 // Since sample most probably won't change, set it to 0 now. 446 this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER], 0); 447 }, 448 449 /** 450 * calls retrieves the named uniform location for this shader program. 451 * @param {String} name 452 * @returns {Number} 453 */ 454 getUniformLocationForName:function(name){ 455 cc.Assert(name != null, "Invalid uniform name" ); 456 cc.Assert(this._programObj != 0, "Invalid operation. Cannot get uniform location when program is not initialized"); 457 458 return this._glContext.getUniformLocation(this._programObj, name); 459 }, 460 461 getUniformMVPMatrix: function () { 462 return this._uniforms[cc.UNIFORM_MVPMATRIX]; 463 }, 464 465 getUniformSampler: function () { 466 return this._uniforms[cc.UNIFORM_SAMPLER]; 467 }, 468 469 /** 470 * calls glUniform1i only if the values are different than the previous call for this same shader program. 471 * @param {WebGLUniformLocation} location 472 * @param {Number} i1 473 */ 474 setUniformLocationWith1i: function (location, i1) { 475 var updated = this._updateUniformLocation(location, i1); 476 if (updated) 477 this._glContext.uniform1i(location, i1); 478 }, 479 480 /** 481 * calls glUniform2i only if the values are different than the previous call for this same shader program. 482 * @param {WebGLUniformLocation} location 483 * @param {Number} i1 484 * @param {Number} i2 485 */ 486 setUniformLocationWith2i:function(location, i1,i2){ 487 var intArray= [i1,i2]; 488 var updated = this._updateUniformLocation(location, intArray); 489 490 if( updated ) 491 this._glContext.uniform2i(location, i1, i2); 492 }, 493 494 /** 495 * calls glUniform3i only if the values are different than the previous call for this same shader program. 496 * @param {WebGLUniformLocation} location 497 * @param {Number} i1 498 * @param {Number} i2 499 * @param {Number} i3 500 */ 501 setUniformLocationWith3i:function(location, i1, i2, i3){ 502 var intArray = [i1,i2,i3]; 503 var updated = this._updateUniformLocation(location, intArray); 504 505 if( updated ) 506 this._glContext.uniform3i(location, i1, i2, i3); 507 }, 508 509 /** 510 * calls glUniform4i only if the values are different than the previous call for this same shader program. 511 * @param {WebGLUniformLocation} location 512 * @param {Number} i1 513 * @param {Number} i2 514 * @param {Number} i3 515 * @param {Number} i4 516 */ 517 setUniformLocationWith4i:function(location, i1, i2, i3, i4){ 518 var intArray = [i1,i2,i3,i4]; 519 var updated = this._updateUniformLocation(location, intArray); 520 521 if( updated ) 522 this._glContext.uniform4i(location, i1, i2, i3, i4); 523 }, 524 525 /** 526 * calls glUniform2iv only if the values are different than the previous call for this same shader program. 527 * @param {WebGLUniformLocation} location 528 * @param {Int32Array} intArray 529 * @param {Number} numberOfArrays 530 */ 531 setUniformLocationWith2iv:function(location, intArray, numberOfArrays){ 532 var updated = this._updateUniformLocation(location, intArray); 533 534 if( updated ) 535 this._glContext.uniform2iv(location, intArray); 536 }, 537 538 /** 539 * calls glUniform3iv only if the values are different than the previous call for this same shader program. 540 * @param {WebGLUniformLocation} location 541 * @param {Int32Array} intArray 542 * @param {Number} numberOfArrays 543 */ 544 setUniformLocationWith3iv:function(location, intArray, numberOfArrays){ 545 var updated = this._updateUniformLocation(location, intArray); 546 547 if( updated ) 548 this._glContext.uniform3iv(location, intArray); 549 }, 550 551 /** 552 * calls glUniform4iv only if the values are different than the previous call for this same shader program. 553 * @param {WebGLUniformLocation} location 554 * @param {Int32Array} intArray 555 * @param {Number} numberOfArrays 556 */ 557 setUniformLocationWith4iv:function(location, intArray, numberOfArrays){ 558 var updated = this._updateUniformLocation(location, intArray); 559 560 if( updated ) 561 this._glContext.uniform4iv(location, intArray); 562 }, 563 564 /** 565 * calls glUniform1i only if the values are different than the previous call for this same shader program. 566 * @param {WebGLUniformLocation} location 567 * @param {Number} i1 568 */ 569 setUniformLocationI32: function (location, i1) { 570 this.setUniformLocationWith1i(arguments[0], arguments[1]); 571 }, 572 573 /** 574 * calls glUniform1f only if the values are different than the previous call for this same shader program. 575 * @param {WebGLUniformLocation} location 576 * @param {Number} f1 577 */ 578 setUniformLocationWith1f: function (location, f1) { 579 var updated = this._updateUniformLocation(location, f1); 580 if (updated) 581 this._glContext.uniform1f(location, f1); 582 }, 583 584 /** 585 * calls glUniform2f only if the values are different than the previous call for this same shader program. 586 * @param {WebGLUniformLocation} location 587 * @param {Number} f1 588 * @param {Number} f2 589 */ 590 setUniformLocationWith2f: function (location, f1, f2) { 591 var floats = [f1, f2]; 592 var updated = this._updateUniformLocation(location, floats); 593 if (updated) 594 this._glContext.uniform2f(location, f1, f2); 595 }, 596 597 /** 598 * calls glUniform3f only if the values are different than the previous call for this same shader program. 599 * @param {WebGLUniformLocation} location 600 * @param {Number} f1 601 * @param {Number} f2 602 * @param {Number} f3 603 */ 604 setUniformLocationWith3f: function (location, f1, f2, f3) { 605 var floats = [f1, f2, f3]; 606 var updated = this._updateUniformLocation(location, floats); 607 if (updated) 608 this._glContext.uniform3f(location, f1, f2, f3); 609 }, 610 611 /** 612 * calls glUniform4f only if the values are different than the previous call for this same shader program. 613 * @param {WebGLUniformLocation} location 614 * @param {Number} f1 615 * @param {Number} f2 616 * @param {Number} f3 617 * @param {Number} f4 618 */ 619 setUniformLocationWith4f: function (location, f1, f2, f3, f4) { 620 var floats = [f1, f2, f3, f4]; 621 var updated = this._updateUniformLocation(location, floats); 622 if (updated) 623 this._glContext.uniform4f(location, f1, f2, f3, f4); 624 }, 625 626 /** 627 * calls glUniform2fv only if the values are different than the previous call for this same shader program. 628 * @param {WebGLUniformLocation} location 629 * @param {Float32Array} floatArray 630 * @param {Number} numberOfArrays 631 */ 632 setUniformLocationWith2fv: function (location, floatArray, numberOfArrays) { 633 var updated = this._updateUniformLocation(location, floatArray); 634 if (updated) 635 this._glContext.uniform2fv(location, floatArray); 636 }, 637 638 /** 639 * calls glUniform3fv only if the values are different than the previous call for this same shader program. 640 * @param {WebGLUniformLocation} location 641 * @param {Float32Array} floatArray 642 * @param {Number} numberOfArrays 643 */ 644 setUniformLocationWith3fv: function (location, floatArray, numberOfArrays) { 645 var updated = this._updateUniformLocation(location, floatArray); 646 if (updated) 647 this._glContext.uniform3fv(location, floatArray); 648 }, 649 650 /** 651 * calls glUniform4fv only if the values are different than the previous call for this same shader program. 652 * @param {WebGLUniformLocation} location 653 * @param {Float32Array} floatArray 654 * @param {Number} numberOfArrays 655 */ 656 setUniformLocationWith4fv: function (location, floatArray, numberOfArrays) { 657 var updated = this._updateUniformLocation(location, floatArray); 658 if (updated) 659 this._glContext.uniform4fv(location, floatArray); 660 }, 661 662 /** 663 * calls glUniformMatrix4fv only if the values are different than the previous call for this same shader program. 664 * @param {WebGLUniformLocation} location 665 * @param {Float32Array} matrixArray 666 * @param {Number} numberOfMatrices 667 */ 668 setUniformLocationWithMatrix4fv: function (location, matrixArray, numberOfMatrices) { 669 var updated = this._updateUniformLocation(location, matrixArray); 670 if (updated) 671 this._glContext.uniformMatrix4fv(location, false, matrixArray); 672 }, 673 674 setUniformLocationF32: function () { 675 if (arguments.length < 2) 676 return; 677 678 switch (arguments.length) { 679 case 2: 680 this.setUniformLocationWith1f(arguments[0], arguments[1]); 681 break; 682 case 3: 683 this.setUniformLocationWith2f(arguments[0], arguments[1], arguments[2]); 684 break; 685 case 4: 686 this.setUniformLocationWith3f(arguments[0], arguments[1], arguments[2], arguments[3]); 687 break; 688 case 5: 689 this.setUniformLocationWith4f(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); 690 break; 691 } 692 }, 693 694 /** 695 * will update the builtin uniforms if they are different than the previous call for this same shader program. 696 */ 697 setUniformsForBuiltins: function () { 698 var matrixP = new cc.kmMat4(); 699 var matrixMV = new cc.kmMat4(); 700 var matrixMVP = new cc.kmMat4(); 701 702 cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP); 703 cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, matrixMV); 704 705 cc.kmMat4Multiply(matrixMVP, matrixP, matrixMV); 706 707 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], matrixP.mat, 1); 708 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], matrixMV.mat, 1); 709 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], matrixMVP.mat, 1); 710 711 if (this._usesTime) { 712 var director = cc.Director.getInstance(); 713 // This doesn't give the most accurate global time value. 714 // Cocos2D doesn't store a high precision time value, so this will have to do. 715 // Getting Mach time per frame per shader using time could be extremely expensive. 716 var time = director.getTotalFrames() * director.getAnimationInterval(); 717 718 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME], time / 10.0, time, time * 2, time * 4); 719 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME], time / 8.0, time / 4.0, time / 2.0, Math.sin(time)); 720 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME], time / 8.0, time / 4.0, time / 2.0, Math.cos(time)); 721 } 722 723 if (this._uniforms[cc.UNIFORM_RANDOM01] != -1) 724 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01], Math.random(), Math.random(), Math.random(), Math.random()); 725 }, 726 727 /** 728 * will update the MVP matrix on the MVP uniform if it is different than the previous call for this same shader program. 729 */ 730 setUniformForModelViewProjectionMatrix: function () { 731 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, 732 cc.getMat4MultiplyValue(cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top)); 733 }, 734 735 setUniformForModelViewProjectionMatrixWithMat4: function (swapMat4) { 736 cc.kmMat4Multiply(swapMat4, cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top); 737 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, swapMat4.mat); 738 }, 739 740 setUniformForModelViewAndProjectionMatrixWithMat4: function () { 741 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], false, cc.modelview_matrix_stack.top.mat); 742 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], false, cc.projection_matrix_stack.top.mat); 743 }, 744 745 746 /** 747 * returns the vertexShader error log 748 * @return {String} 749 */ 750 vertexShaderLog: function () { 751 return this._glContext.getShaderInfoLog(this._vertShader); 752 }, 753 754 /** 755 * returns the vertexShader error log 756 * @return {String} 757 */ 758 getVertexShaderLog: function () { 759 return this._glContext.getShaderInfoLog(this._vertShader); 760 }, 761 762 /** 763 * returns the fragmentShader error log 764 * @returns {String} 765 */ 766 getFragmentShaderLog: function () { 767 return this._glContext.getShaderInfoLog(this._vertShader); 768 }, 769 770 /** 771 * returns the fragmentShader error log 772 * @return {String} 773 */ 774 fragmentShaderLog: function () { 775 return this._glContext.getShaderInfoLog(this._fragShader); 776 }, 777 778 /** 779 * returns the program error log 780 * @return {String} 781 */ 782 programLog: function () { 783 return this._glContext.getProgramInfoLog(this._programObj); 784 }, 785 786 /** 787 * returns the program error log 788 * @return {String} 789 */ 790 getProgramLog: function () { 791 return this._glContext.getProgramInfoLog(this._programObj); 792 }, 793 794 /** 795 * reload all shaders, this function is designed for android <br/> 796 * when opengl context lost, so don't call it. 797 */ 798 reset: function () { 799 this._vertShader = null; 800 this._fragShader = null; 801 this._uniforms = []; 802 803 // it is already deallocated by android 804 //ccGLDeleteProgram(m_uProgram); 805 this._glContext.deleteProgram(this._programObj); 806 this._programObj = null; 807 808 // Purge uniform hash 809 for (var i = 0; i < this._hashForUniforms.length; i++) { 810 this._hashForUniforms[i].value = null; 811 this._hashForUniforms[i] = null; 812 } 813 814 this._hashForUniforms = []; 815 }, 816 817 /** 818 * get WebGLProgram object 819 * @return {WebGLProgram} 820 */ 821 getProgram: function () { 822 return this._programObj; 823 }, 824 825 /** 826 * Currently JavaScript Bindigns (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 827 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 828 * This is a hack, and should be removed once JSB fixes the retain/release bug 829 */ 830 retain: function () { 831 }, 832 release: function () { 833 } 834 }); 835 836 /** 837 * Create a cc.GLProgram object 838 * @param {String} vShaderFileName 839 * @param {String} fShaderFileName 840 * @returns {cc.GLProgram} 841 */ 842 cc.GLProgram.create = function (vShaderFileName, fShaderFileName) { 843 var program = new cc.GLProgram(); 844 if (program.init(vShaderFileName, fShaderFileName)) 845 return program; 846 return null; 847 }; 848