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