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 source = "precision highp float; \n" 263 + "uniform mat4 CC_PMatrix; \n" 264 + "uniform mat4 CC_MVMatrix; \n" 265 + "uniform mat4 CC_MVPMatrix; \n" 266 + "uniform vec4 CC_Time; \n" 267 + "uniform vec4 CC_SinTime; \n" 268 + "uniform vec4 CC_CosTime; \n" 269 + "uniform vec4 CC_Random01; \n" 270 + "//CC INCLUDES END \n" + source; 271 272 this._glContext.shaderSource(shader, source); 273 this._glContext.compileShader(shader); 274 var status = this._glContext.getShaderParameter(shader, this._glContext.COMPILE_STATUS); 275 276 if (!status) { 277 cc.log("cocos2d: ERROR: Failed to compile shader:\n" + this._glContext.getShaderSource(shader)); 278 if (type == this._glContext.VERTEX_SHADER) 279 cc.log("cocos2d: \n" + this.vertexShaderLog()); 280 else 281 cc.log("cocos2d: \n" + this.fragmentShaderLog()); 282 } 283 return ( status == 1 ); 284 }, 285 286 ctor: function (glContext) { 287 this._programObj = null; 288 this._vertShader = null; 289 this._fragShader = null; 290 this._uniforms = []; 291 this._hashForUniforms = []; 292 this._glContext = glContext || cc._renderContext; 293 }, 294 295 destroyProgram: function () { 296 this._vertShader = null; 297 this._fragShader = null; 298 this._uniforms = null; 299 this._hashForUniforms = null; 300 301 this._glContext.deleteProgram(this._programObj); 302 }, 303 304 /** 305 * Initializes the cc.GLProgram with a vertex and fragment with string 306 * @param {String} vertShaderStr 307 * @param {String} fragShaderStr 308 * @return {Boolean} 309 */ 310 initWithVertexShaderByteArray: function (vertShaderStr, fragShaderStr) { 311 var locGL = this._glContext; 312 this._programObj = locGL.createProgram(); 313 //cc.CHECK_GL_ERROR_DEBUG(); 314 315 this._vertShader = null; 316 this._fragShader = null; 317 318 if (vertShaderStr) { 319 this._vertShader = locGL.createShader(locGL.VERTEX_SHADER); 320 if (!this._compileShader(this._vertShader, locGL.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 = locGL.createShader(locGL.FRAGMENT_SHADER); 328 if (!this._compileShader(this._fragShader, locGL.FRAGMENT_SHADER, fragShaderStr)) { 329 cc.log("cocos2d: ERROR: Failed to compile fragment shader"); 330 } 331 } 332 333 if (this._vertShader) 334 locGL.attachShader(this._programObj, this._vertShader); 335 cc.CHECK_GL_ERROR_DEBUG(); 336 337 if (this._fragShader) 338 locGL.attachShader(this._programObj, this._fragShader); 339 this._hashForUniforms.length = 0; 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 vertexSource = cc.loader.getRes(vShaderFilename); 363 if(!vertexSource) throw "Please load the resource firset : " + vShaderFilename; 364 var fragmentSource = cc.loader.getRes(fShaderFileName); 365 if(!fragmentSource) throw "Please load the resource firset : " + fShaderFileName; 366 return this.initWithVertexShaderByteArray(vertexSource, fragmentSource); 367 }, 368 369 /** 370 * Initializes the CCGLProgram with a vertex and fragment with contents of filenames 371 * @param {String} vShaderFilename 372 * @param {String} fShaderFileName 373 * @return {Boolean} 374 */ 375 init: function (vShaderFilename, fShaderFileName) { 376 return this.initWithVertexShaderFilename(vShaderFilename, fShaderFileName); 377 }, 378 379 /** 380 * It will add a new attribute to the shader 381 * @param {String} attributeName 382 * @param {Number} index 383 */ 384 addAttribute: function (attributeName, index) { 385 this._glContext.bindAttribLocation(this._programObj, index, attributeName); 386 }, 387 388 /** 389 * links the glProgram 390 * @return {Boolean} 391 */ 392 link: function () { 393 if(!this._programObj) { 394 cc.log("cc.GLProgram.link(): Cannot link invalid program"); 395 return false; 396 } 397 398 this._glContext.linkProgram(this._programObj); 399 400 if (this._vertShader) 401 this._glContext.deleteShader(this._vertShader); 402 if (this._fragShader) 403 this._glContext.deleteShader(this._fragShader); 404 405 this._vertShader = null; 406 this._fragShader = null; 407 408 if (cc.game.config[cc.game.CONFIG_KEY.debugMode]) { 409 var status = this._glContext.getProgramParameter(this._programObj, this._glContext.LINK_STATUS); 410 if (!status) { 411 cc.log("cocos2d: ERROR: Failed to link program: " + this._glContext.getProgramInfoLog(this._programObj)); 412 cc.glDeleteProgram(this._programObj); 413 this._programObj = null; 414 return false; 415 } 416 } 417 418 return true; 419 }, 420 421 /** 422 * it will call glUseProgram() 423 */ 424 use: function () { 425 cc.glUseProgram(this._programObj); 426 }, 427 428 /** 429 * It will create 4 uniforms: 430 * cc.UNIFORM_PMATRIX 431 * cc.UNIFORM_MVMATRIX 432 * cc.UNIFORM_MVPMATRIX 433 * cc.UNIFORM_SAMPLER 434 */ 435 updateUniforms: function () { 436 this._uniforms[cc.UNIFORM_PMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_PMATRIX_S); 437 this._uniforms[cc.UNIFORM_MVMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVMATRIX_S); 438 this._uniforms[cc.UNIFORM_MVPMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVPMATRIX_S); 439 this._uniforms[cc.UNIFORM_TIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_TIME_S); 440 this._uniforms[cc.UNIFORM_SINTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SINTIME_S); 441 this._uniforms[cc.UNIFORM_COSTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_COSTIME_S); 442 443 this._usesTime = (this._uniforms[cc.UNIFORM_TIME] != null || this._uniforms[cc.UNIFORM_SINTIME] != null || this._uniforms[cc.UNIFORM_COSTIME] != null); 444 445 this._uniforms[cc.UNIFORM_RANDOM01] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_RANDOM01_S); 446 this._uniforms[cc.UNIFORM_SAMPLER] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SAMPLER_S); 447 448 this.use(); 449 // Since sample most probably won't change, set it to 0 now. 450 this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER], 0); 451 }, 452 453 /** 454 * calls retrieves the named uniform location for this shader program. 455 * @param {String} name 456 * @returns {Number} 457 */ 458 getUniformLocationForName:function(name){ 459 if(!name) 460 throw "cc.GLProgram.getUniformLocationForName(): uniform name should be non-null"; 461 if(!this._programObj) 462 throw "cc.GLProgram.getUniformLocationForName(): Invalid operation. Cannot get uniform location when program is not initialized"; 463 464 return this._glContext.getUniformLocation(this._programObj, name); 465 }, 466 467 getUniformMVPMatrix: function () { 468 return this._uniforms[cc.UNIFORM_MVPMATRIX]; 469 }, 470 471 getUniformSampler: function () { 472 return this._uniforms[cc.UNIFORM_SAMPLER]; 473 }, 474 475 /** 476 * calls glUniform1i only if the values are different than the previous call for this same shader program. 477 * @param {WebGLUniformLocation} location 478 * @param {Number} i1 479 */ 480 setUniformLocationWith1i: function (location, i1) { 481 var updated = this._updateUniformLocation(location, i1); 482 if (updated) 483 this._glContext.uniform1i(location, i1); 484 }, 485 486 /** 487 * calls glUniform2i only if the values are different than the previous call for this same shader program. 488 * @param {WebGLUniformLocation} location 489 * @param {Number} i1 490 * @param {Number} i2 491 */ 492 setUniformLocationWith2i:function(location, i1,i2){ 493 var intArray= [i1,i2]; 494 var updated = this._updateUniformLocation(location, intArray); 495 496 if( updated ) 497 this._glContext.uniform2i(location, i1, i2); 498 }, 499 500 /** 501 * calls glUniform3i only if the values are different than the previous call for this same shader program. 502 * @param {WebGLUniformLocation} location 503 * @param {Number} i1 504 * @param {Number} i2 505 * @param {Number} i3 506 */ 507 setUniformLocationWith3i:function(location, i1, i2, i3){ 508 var intArray = [i1,i2,i3]; 509 var updated = this._updateUniformLocation(location, intArray); 510 511 if( updated ) 512 this._glContext.uniform3i(location, i1, i2, i3); 513 }, 514 515 /** 516 * calls glUniform4i only if the values are different than the previous call for this same shader program. 517 * @param {WebGLUniformLocation} location 518 * @param {Number} i1 519 * @param {Number} i2 520 * @param {Number} i3 521 * @param {Number} i4 522 */ 523 setUniformLocationWith4i:function(location, i1, i2, i3, i4){ 524 var intArray = [i1,i2,i3,i4]; 525 var updated = this._updateUniformLocation(location, intArray); 526 527 if( updated ) 528 this._glContext.uniform4i(location, i1, i2, i3, i4); 529 }, 530 531 /** 532 * calls glUniform2iv only if the values are different than the previous call for this same shader program. 533 * @param {WebGLUniformLocation} location 534 * @param {Int32Array} intArray 535 * @param {Number} numberOfArrays 536 */ 537 setUniformLocationWith2iv:function(location, intArray, numberOfArrays){ 538 var updated = this._updateUniformLocation(location, intArray); 539 540 if( updated ) 541 this._glContext.uniform2iv(location, intArray); 542 }, 543 544 /** 545 * calls glUniform3iv only if the values are different than the previous call for this same shader program. 546 * @param {WebGLUniformLocation} location 547 * @param {Int32Array} intArray 548 * @param {Number} numberOfArrays 549 */ 550 setUniformLocationWith3iv:function(location, intArray, numberOfArrays){ 551 var updated = this._updateUniformLocation(location, intArray); 552 553 if( updated ) 554 this._glContext.uniform3iv(location, intArray); 555 }, 556 557 /** 558 * calls glUniform4iv only if the values are different than the previous call for this same shader program. 559 * @param {WebGLUniformLocation} location 560 * @param {Int32Array} intArray 561 * @param {Number} numberOfArrays 562 */ 563 setUniformLocationWith4iv:function(location, intArray, numberOfArrays){ 564 var updated = this._updateUniformLocation(location, intArray); 565 566 if( updated ) 567 this._glContext.uniform4iv(location, intArray); 568 }, 569 570 /** 571 * calls glUniform1i only if the values are different than the previous call for this same shader program. 572 * @param {WebGLUniformLocation} location 573 * @param {Number} i1 574 */ 575 setUniformLocationI32: function (location, i1) { 576 this.setUniformLocationWith1i(arguments[0], arguments[1]); 577 }, 578 579 /** 580 * calls glUniform1f only if the values are different than the previous call for this same shader program. 581 * @param {WebGLUniformLocation} location 582 * @param {Number} f1 583 */ 584 setUniformLocationWith1f: function (location, f1) { 585 var updated = this._updateUniformLocation(location, f1); 586 if (updated) 587 this._glContext.uniform1f(location, f1); 588 }, 589 590 /** 591 * calls glUniform2f only if the values are different than the previous call for this same shader program. 592 * @param {WebGLUniformLocation} location 593 * @param {Number} f1 594 * @param {Number} f2 595 */ 596 setUniformLocationWith2f: function (location, f1, f2) { 597 var floats = [f1, f2]; 598 var updated = this._updateUniformLocation(location, floats); 599 if (updated) 600 this._glContext.uniform2f(location, f1, f2); 601 }, 602 603 /** 604 * calls glUniform3f only if the values are different than the previous call for this same shader program. 605 * @param {WebGLUniformLocation} location 606 * @param {Number} f1 607 * @param {Number} f2 608 * @param {Number} f3 609 */ 610 setUniformLocationWith3f: function (location, f1, f2, f3) { 611 var floats = [f1, f2, f3]; 612 var updated = this._updateUniformLocation(location, floats); 613 if (updated) 614 this._glContext.uniform3f(location, f1, f2, f3); 615 }, 616 617 /** 618 * calls glUniform4f only if the values are different than the previous call for this same shader program. 619 * @param {WebGLUniformLocation} location 620 * @param {Number} f1 621 * @param {Number} f2 622 * @param {Number} f3 623 * @param {Number} f4 624 */ 625 setUniformLocationWith4f: function (location, f1, f2, f3, f4) { 626 var floats = [f1, f2, f3, f4]; 627 var updated = this._updateUniformLocation(location, floats); 628 if (updated) 629 this._glContext.uniform4f(location, f1, f2, f3, f4); 630 }, 631 632 /** 633 * calls glUniform2fv only if the values are different than the previous call for this same shader program. 634 * @param {WebGLUniformLocation} location 635 * @param {Float32Array} floatArray 636 * @param {Number} numberOfArrays 637 */ 638 setUniformLocationWith2fv: function (location, floatArray, numberOfArrays) { 639 var updated = this._updateUniformLocation(location, floatArray); 640 if (updated) 641 this._glContext.uniform2fv(location, floatArray); 642 }, 643 644 /** 645 * calls glUniform3fv only if the values are different than the previous call for this same shader program. 646 * @param {WebGLUniformLocation} location 647 * @param {Float32Array} floatArray 648 * @param {Number} numberOfArrays 649 */ 650 setUniformLocationWith3fv: function (location, floatArray, numberOfArrays) { 651 var updated = this._updateUniformLocation(location, floatArray); 652 if (updated) 653 this._glContext.uniform3fv(location, floatArray); 654 }, 655 656 /** 657 * calls glUniform4fv only if the values are different than the previous call for this same shader program. 658 * @param {WebGLUniformLocation} location 659 * @param {Float32Array} floatArray 660 * @param {Number} numberOfArrays 661 */ 662 setUniformLocationWith4fv: function (location, floatArray, numberOfArrays) { 663 var updated = this._updateUniformLocation(location, floatArray); 664 if (updated) 665 this._glContext.uniform4fv(location, floatArray); 666 }, 667 668 /** 669 * calls glUniformMatrix4fv only if the values are different than the previous call for this same shader program. 670 * @param {WebGLUniformLocation} location 671 * @param {Float32Array} matrixArray 672 * @param {Number} numberOfMatrices 673 */ 674 setUniformLocationWithMatrix4fv: function (location, matrixArray, numberOfMatrices) { 675 var updated = this._updateUniformLocation(location, matrixArray); 676 if (updated) 677 this._glContext.uniformMatrix4fv(location, false, matrixArray); 678 }, 679 680 setUniformLocationF32: function () { 681 if (arguments.length < 2) 682 return; 683 684 switch (arguments.length) { 685 case 2: 686 this.setUniformLocationWith1f(arguments[0], arguments[1]); 687 break; 688 case 3: 689 this.setUniformLocationWith2f(arguments[0], arguments[1], arguments[2]); 690 break; 691 case 4: 692 this.setUniformLocationWith3f(arguments[0], arguments[1], arguments[2], arguments[3]); 693 break; 694 case 5: 695 this.setUniformLocationWith4f(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); 696 break; 697 } 698 }, 699 700 /** 701 * will update the builtin uniforms if they are different than the previous call for this same shader program. 702 */ 703 setUniformsForBuiltins: function () { 704 var matrixP = new cc.kmMat4(); 705 var matrixMV = new cc.kmMat4(); 706 var matrixMVP = new cc.kmMat4(); 707 708 cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP); 709 cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, matrixMV); 710 711 cc.kmMat4Multiply(matrixMVP, matrixP, matrixMV); 712 713 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], matrixP.mat, 1); 714 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], matrixMV.mat, 1); 715 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], matrixMVP.mat, 1); 716 717 if (this._usesTime) { 718 var director = cc.director; 719 // This doesn't give the most accurate global time value. 720 // Cocos2D doesn't store a high precision time value, so this will have to do. 721 // Getting Mach time per frame per shader using time could be extremely expensive. 722 var time = director.getTotalFrames() * director.getAnimationInterval(); 723 724 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME], time / 10.0, time, time * 2, time * 4); 725 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME], time / 8.0, time / 4.0, time / 2.0, Math.sin(time)); 726 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME], time / 8.0, time / 4.0, time / 2.0, Math.cos(time)); 727 } 728 729 if (this._uniforms[cc.UNIFORM_RANDOM01] != -1) 730 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01], Math.random(), Math.random(), Math.random(), Math.random()); 731 }, 732 733 /** 734 * will update the MVP matrix on the MVP uniform if it is different than the previous call for this same shader program. 735 */ 736 setUniformForModelViewProjectionMatrix: function () { 737 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, 738 cc.getMat4MultiplyValue(cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top)); 739 }, 740 741 setUniformForModelViewProjectionMatrixWithMat4: function (swapMat4) { 742 cc.kmMat4Multiply(swapMat4, cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top); 743 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, swapMat4.mat); 744 }, 745 746 setUniformForModelViewAndProjectionMatrixWithMat4: function () { 747 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], false, cc.modelview_matrix_stack.top.mat); 748 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], false, cc.projection_matrix_stack.top.mat); 749 }, 750 751 752 /** 753 * returns the vertexShader error log 754 * @return {String} 755 */ 756 vertexShaderLog: function () { 757 return this._glContext.getShaderInfoLog(this._vertShader); 758 }, 759 760 /** 761 * returns the vertexShader error log 762 * @return {String} 763 */ 764 getVertexShaderLog: function () { 765 return this._glContext.getShaderInfoLog(this._vertShader); 766 }, 767 768 /** 769 * returns the fragmentShader error log 770 * @returns {String} 771 */ 772 getFragmentShaderLog: function () { 773 return this._glContext.getShaderInfoLog(this._vertShader); 774 }, 775 776 /** 777 * returns the fragmentShader error log 778 * @return {String} 779 */ 780 fragmentShaderLog: function () { 781 return this._glContext.getShaderInfoLog(this._fragShader); 782 }, 783 784 /** 785 * returns the program error log 786 * @return {String} 787 */ 788 programLog: function () { 789 return this._glContext.getProgramInfoLog(this._programObj); 790 }, 791 792 /** 793 * returns the program error log 794 * @return {String} 795 */ 796 getProgramLog: function () { 797 return this._glContext.getProgramInfoLog(this._programObj); 798 }, 799 800 /** 801 * reload all shaders, this function is designed for android <br/> 802 * when opengl context lost, so don't call it. 803 */ 804 reset: function () { 805 this._vertShader = null; 806 this._fragShader = null; 807 this._uniforms.length = 0; 808 809 // it is already deallocated by android 810 //ccGLDeleteProgram(m_uProgram); 811 this._glContext.deleteProgram(this._programObj); 812 this._programObj = null; 813 814 // Purge uniform hash 815 for (var i = 0; i < this._hashForUniforms.length; i++) { 816 this._hashForUniforms[i].value = null; 817 this._hashForUniforms[i] = null; 818 } 819 820 this._hashForUniforms.length = 0; 821 }, 822 823 /** 824 * get WebGLProgram object 825 * @return {WebGLProgram} 826 */ 827 getProgram: function () { 828 return this._programObj; 829 }, 830 831 /** 832 * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 833 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 834 * This is a hack, and should be removed once JSB fixes the retain/release bug 835 */ 836 retain: function () { 837 }, 838 release: function () { 839 } 840 }); 841 842 /** 843 * Create a cc.GLProgram object 844 * @param {String} vShaderFileName 845 * @param {String} fShaderFileName 846 * @returns {cc.GLProgram} 847 */ 848 cc.GLProgram.create = function (vShaderFileName, fShaderFileName) { 849 var program = new cc.GLProgram(); 850 if (program.init(vShaderFileName, fShaderFileName)) 851 return program; 852 return null; 853 }; 854