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