1 /**************************************************************************** 2 Copyright (c) 2008-2010 Ricardo Quesada 3 Copyright (c) 2011-2012 cocos2d-x.org 4 Copyright (c) 2013-2014 Chukong Technologies Inc. 5 Copyright 2011 Jeff Lamarche 6 Copyright 2012 Goffredo Marocchi 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 cc.HashUniformEntry = function (value, location, hh) { 30 this.value = value; 31 this.location = location; 32 this.hh = hh || {}; 33 }; 34 35 /** 36 * Class that implements a WebGL program 37 * @class 38 * @extends cc.Class 39 */ 40 cc.GLProgram = cc.Class.extend(/** @lends cc.GLProgram# */{ 41 _glContext: null, 42 _programObj: null, 43 _vertShader: null, 44 _fragShader: null, 45 _uniforms: null, 46 _hashForUniforms: null, 47 _usesTime: false, 48 49 // Uniform cache 50 _updateUniformLocation: function (location, data, bytes) { 51 if (location == null) 52 return false; 53 54 var updated = true; 55 var element = null; 56 for (var i = 0; i < this._hashForUniforms.length; i++) 57 if (this._hashForUniforms[i].location == location) 58 element = this._hashForUniforms[i]; 59 60 if (!element) { 61 element = new cc.HashUniformEntry(); 62 // key 63 element.location = location; 64 // value 65 element.value = data; 66 this._hashForUniforms.push(element); 67 } else { 68 if (element.value == data) 69 updated = false; 70 else 71 element.value = data; 72 } 73 74 return updated; 75 }, 76 77 _description: function () { 78 return "<CCGLProgram = " + this.toString() + " | Program = " + this._programObj.toString() + ", VertexShader = " + 79 this._vertShader.toString() + ", FragmentShader = " + this._fragShader.toString() + ">"; 80 }, 81 82 _compileShader: function (shader, type, source) { 83 if (!source || !shader) 84 return false; 85 86 //var preStr = (type == this._glContext.VERTEX_SHADER) ? "precision highp float;\n" : "precision mediump float;\n"; 87 source = "precision highp float; \n" 88 + "uniform mat4 CC_PMatrix; \n" 89 + "uniform mat4 CC_MVMatrix; \n" 90 + "uniform mat4 CC_MVPMatrix; \n" 91 + "uniform vec4 CC_Time; \n" 92 + "uniform vec4 CC_SinTime; \n" 93 + "uniform vec4 CC_CosTime; \n" 94 + "uniform vec4 CC_Random01; \n" 95 + "//CC INCLUDES END \n" + source; 96 97 this._glContext.shaderSource(shader, source); 98 this._glContext.compileShader(shader); 99 var status = this._glContext.getShaderParameter(shader, this._glContext.COMPILE_STATUS); 100 101 if (!status) { 102 cc.log("cocos2d: ERROR: Failed to compile shader:\n" + this._glContext.getShaderSource(shader)); 103 if (type == this._glContext.VERTEX_SHADER) 104 cc.log("cocos2d: \n" + this.vertexShaderLog()); 105 else 106 cc.log("cocos2d: \n" + this.fragmentShaderLog()); 107 } 108 return ( status == 1 ); 109 }, 110 111 /** 112 * Create a cc.GLProgram object 113 * @param {String} vShaderFileName 114 * @param {String} fShaderFileName 115 * @returns {cc.GLProgram} 116 */ 117 ctor: function (vShaderFileName, fShaderFileName, glContext) { 118 this._uniforms = []; 119 this._hashForUniforms = []; 120 this._glContext = glContext || cc._renderContext; 121 122 vShaderFileName && fShaderFileName && this.init(vShaderFileName, fShaderFileName); 123 }, 124 125 /** 126 * destroy program 127 */ 128 destroyProgram: function () { 129 this._vertShader = null; 130 this._fragShader = null; 131 this._uniforms = null; 132 this._hashForUniforms = null; 133 134 this._glContext.deleteProgram(this._programObj); 135 }, 136 137 /** 138 * Initializes the cc.GLProgram with a vertex and fragment with string 139 * @param {String} vertShaderStr 140 * @param {String} fragShaderStr 141 * @return {Boolean} 142 */ 143 initWithVertexShaderByteArray: function (vertShaderStr, fragShaderStr) { 144 var locGL = this._glContext; 145 this._programObj = locGL.createProgram(); 146 //cc.checkGLErrorDebug(); 147 148 this._vertShader = null; 149 this._fragShader = null; 150 151 if (vertShaderStr) { 152 this._vertShader = locGL.createShader(locGL.VERTEX_SHADER); 153 if (!this._compileShader(this._vertShader, locGL.VERTEX_SHADER, vertShaderStr)) { 154 cc.log("cocos2d: ERROR: Failed to compile vertex shader"); 155 } 156 } 157 158 // Create and compile fragment shader 159 if (fragShaderStr) { 160 this._fragShader = locGL.createShader(locGL.FRAGMENT_SHADER); 161 if (!this._compileShader(this._fragShader, locGL.FRAGMENT_SHADER, fragShaderStr)) { 162 cc.log("cocos2d: ERROR: Failed to compile fragment shader"); 163 } 164 } 165 166 if (this._vertShader) 167 locGL.attachShader(this._programObj, this._vertShader); 168 cc.checkGLErrorDebug(); 169 170 if (this._fragShader) 171 locGL.attachShader(this._programObj, this._fragShader); 172 this._hashForUniforms.length = 0; 173 174 cc.checkGLErrorDebug(); 175 return true; 176 }, 177 178 /** 179 * Initializes the cc.GLProgram with a vertex and fragment with string 180 * @param {String} vertShaderStr 181 * @param {String} fragShaderStr 182 * @return {Boolean} 183 */ 184 initWithString: function (vertShaderStr, fragShaderStr) { 185 return this.initWithVertexShaderByteArray(vertShaderStr, fragShaderStr); 186 }, 187 188 /** 189 * Initializes the CCGLProgram with a vertex and fragment with contents of filenames 190 * @param {String} vShaderFilename 191 * @param {String} fShaderFileName 192 * @return {Boolean} 193 */ 194 initWithVertexShaderFilename: function (vShaderFilename, fShaderFileName) { 195 var vertexSource = cc.loader.getRes(vShaderFilename); 196 if(!vertexSource) throw "Please load the resource firset : " + vShaderFilename; 197 var fragmentSource = cc.loader.getRes(fShaderFileName); 198 if(!fragmentSource) throw "Please load the resource firset : " + fShaderFileName; 199 return this.initWithVertexShaderByteArray(vertexSource, fragmentSource); 200 }, 201 202 /** 203 * Initializes the CCGLProgram with a vertex and fragment with contents of filenames 204 * @param {String} vShaderFilename 205 * @param {String} fShaderFileName 206 * @return {Boolean} 207 */ 208 init: function (vShaderFilename, fShaderFileName) { 209 return this.initWithVertexShaderFilename(vShaderFilename, fShaderFileName); 210 }, 211 212 /** 213 * It will add a new attribute to the shader 214 * @param {String} attributeName 215 * @param {Number} index 216 */ 217 addAttribute: function (attributeName, index) { 218 this._glContext.bindAttribLocation(this._programObj, index, attributeName); 219 }, 220 221 /** 222 * links the glProgram 223 * @return {Boolean} 224 */ 225 link: function () { 226 if(!this._programObj) { 227 cc.log("cc.GLProgram.link(): Cannot link invalid program"); 228 return false; 229 } 230 231 this._glContext.linkProgram(this._programObj); 232 233 if (this._vertShader) 234 this._glContext.deleteShader(this._vertShader); 235 if (this._fragShader) 236 this._glContext.deleteShader(this._fragShader); 237 238 this._vertShader = null; 239 this._fragShader = null; 240 241 if (cc.game.config[cc.game.CONFIG_KEY.debugMode]) { 242 var status = this._glContext.getProgramParameter(this._programObj, this._glContext.LINK_STATUS); 243 if (!status) { 244 cc.log("cocos2d: ERROR: Failed to link program: " + this._glContext.getProgramInfoLog(this._programObj)); 245 cc.glDeleteProgram(this._programObj); 246 this._programObj = null; 247 return false; 248 } 249 } 250 251 return true; 252 }, 253 254 /** 255 * it will call glUseProgram() 256 */ 257 use: function () { 258 cc.glUseProgram(this._programObj); 259 }, 260 261 /** 262 * It will create 4 uniforms: 263 * cc.UNIFORM_PMATRIX 264 * cc.UNIFORM_MVMATRIX 265 * cc.UNIFORM_MVPMATRIX 266 * cc.UNIFORM_SAMPLER 267 */ 268 updateUniforms: function () { 269 this._uniforms[cc.UNIFORM_PMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_PMATRIX_S); 270 this._uniforms[cc.UNIFORM_MVMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVMATRIX_S); 271 this._uniforms[cc.UNIFORM_MVPMATRIX] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_MVPMATRIX_S); 272 this._uniforms[cc.UNIFORM_TIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_TIME_S); 273 this._uniforms[cc.UNIFORM_SINTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SINTIME_S); 274 this._uniforms[cc.UNIFORM_COSTIME] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_COSTIME_S); 275 276 this._usesTime = (this._uniforms[cc.UNIFORM_TIME] != null || this._uniforms[cc.UNIFORM_SINTIME] != null || this._uniforms[cc.UNIFORM_COSTIME] != null); 277 278 this._uniforms[cc.UNIFORM_RANDOM01] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_RANDOM01_S); 279 this._uniforms[cc.UNIFORM_SAMPLER] = this._glContext.getUniformLocation(this._programObj, cc.UNIFORM_SAMPLER_S); 280 281 this.use(); 282 // Since sample most probably won't change, set it to 0 now. 283 this.setUniformLocationWith1i(this._uniforms[cc.UNIFORM_SAMPLER], 0); 284 }, 285 286 /** 287 * calls retrieves the named uniform location for this shader program. 288 * @param {String} name 289 * @returns {Number} 290 */ 291 getUniformLocationForName:function(name){ 292 if(!name) 293 throw "cc.GLProgram.getUniformLocationForName(): uniform name should be non-null"; 294 if(!this._programObj) 295 throw "cc.GLProgram.getUniformLocationForName(): Invalid operation. Cannot get uniform location when program is not initialized"; 296 297 return this._glContext.getUniformLocation(this._programObj, name); 298 }, 299 300 /** 301 * get uniform MVP matrix 302 * @returns {WebGLUniformLocation} 303 */ 304 getUniformMVPMatrix: function () { 305 return this._uniforms[cc.UNIFORM_MVPMATRIX]; 306 }, 307 308 /** 309 * get uniform sampler 310 * @returns {WebGLUniformLocation} 311 */ 312 getUniformSampler: function () { 313 return this._uniforms[cc.UNIFORM_SAMPLER]; 314 }, 315 316 /** 317 * calls glUniform1i only if the values are different than the previous call for this same shader program. 318 * @param {WebGLUniformLocation} location 319 * @param {Number} i1 320 */ 321 setUniformLocationWith1i: function (location, i1) { 322 var updated = this._updateUniformLocation(location, i1); 323 if (updated) 324 this._glContext.uniform1i(location, i1); 325 }, 326 327 /** 328 * calls glUniform2i only if the values are different than the previous call for this same shader program. 329 * @param {WebGLUniformLocation} location 330 * @param {Number} i1 331 * @param {Number} i2 332 */ 333 setUniformLocationWith2i:function(location, i1,i2){ 334 var intArray= [i1,i2]; 335 var updated = this._updateUniformLocation(location, intArray); 336 337 if( updated ) 338 this._glContext.uniform2i(location, i1, i2); 339 }, 340 341 /** 342 * calls glUniform3i only if the values are different than the previous call for this same shader program. 343 * @param {WebGLUniformLocation} location 344 * @param {Number} i1 345 * @param {Number} i2 346 * @param {Number} i3 347 */ 348 setUniformLocationWith3i:function(location, i1, i2, i3){ 349 var intArray = [i1,i2,i3]; 350 var updated = this._updateUniformLocation(location, intArray); 351 352 if( updated ) 353 this._glContext.uniform3i(location, i1, i2, i3); 354 }, 355 356 /** 357 * calls glUniform4i only if the values are different than the previous call for this same shader program. 358 * @param {WebGLUniformLocation} location 359 * @param {Number} i1 360 * @param {Number} i2 361 * @param {Number} i3 362 * @param {Number} i4 363 */ 364 setUniformLocationWith4i:function(location, i1, i2, i3, i4){ 365 var intArray = [i1,i2,i3,i4]; 366 var updated = this._updateUniformLocation(location, intArray); 367 368 if( updated ) 369 this._glContext.uniform4i(location, i1, i2, i3, i4); 370 }, 371 372 /** 373 * calls glUniform2iv only if the values are different than the previous call for this same shader program. 374 * @param {WebGLUniformLocation} location 375 * @param {Int32Array} intArray 376 * @param {Number} numberOfArrays 377 */ 378 setUniformLocationWith2iv:function(location, intArray, numberOfArrays){ 379 var updated = this._updateUniformLocation(location, intArray); 380 381 if( updated ) 382 this._glContext.uniform2iv(location, intArray); 383 }, 384 385 /** 386 * calls glUniform3iv only if the values are different than the previous call for this same shader program. 387 * @param {WebGLUniformLocation} location 388 * @param {Int32Array} intArray 389 * @param {Number} numberOfArrays 390 */ 391 setUniformLocationWith3iv:function(location, intArray, numberOfArrays){ 392 var updated = this._updateUniformLocation(location, intArray); 393 394 if( updated ) 395 this._glContext.uniform3iv(location, intArray); 396 }, 397 398 /** 399 * calls glUniform4iv only if the values are different than the previous call for this same shader program. 400 * @param {WebGLUniformLocation} location 401 * @param {Int32Array} intArray 402 * @param {Number} numberOfArrays 403 */ 404 setUniformLocationWith4iv:function(location, intArray, numberOfArrays){ 405 var updated = this._updateUniformLocation(location, intArray); 406 407 if( updated ) 408 this._glContext.uniform4iv(location, intArray); 409 }, 410 411 /** 412 * calls glUniform1i only if the values are different than the previous call for this same shader program. 413 * @param {WebGLUniformLocation} location 414 * @param {Number} i1 415 */ 416 setUniformLocationI32: function (location, i1) { 417 this.setUniformLocationWith1i(arguments[0], arguments[1]); 418 }, 419 420 /** 421 * calls glUniform1f only if the values are different than the previous call for this same shader program. 422 * @param {WebGLUniformLocation} location 423 * @param {Number} f1 424 */ 425 setUniformLocationWith1f: function (location, f1) { 426 var updated = this._updateUniformLocation(location, f1); 427 if (updated) 428 this._glContext.uniform1f(location, f1); 429 }, 430 431 /** 432 * calls glUniform2f only if the values are different than the previous call for this same shader program. 433 * @param {WebGLUniformLocation} location 434 * @param {Number} f1 435 * @param {Number} f2 436 */ 437 setUniformLocationWith2f: function (location, f1, f2) { 438 var floats = [f1, f2]; 439 var updated = this._updateUniformLocation(location, floats); 440 if (updated) 441 this._glContext.uniform2f(location, f1, f2); 442 }, 443 444 /** 445 * calls glUniform3f only if the values are different than the previous call for this same shader program. 446 * @param {WebGLUniformLocation} location 447 * @param {Number} f1 448 * @param {Number} f2 449 * @param {Number} f3 450 */ 451 setUniformLocationWith3f: function (location, f1, f2, f3) { 452 var floats = [f1, f2, f3]; 453 var updated = this._updateUniformLocation(location, floats); 454 if (updated) 455 this._glContext.uniform3f(location, f1, f2, f3); 456 }, 457 458 /** 459 * calls glUniform4f only if the values are different than the previous call for this same shader program. 460 * @param {WebGLUniformLocation} location 461 * @param {Number} f1 462 * @param {Number} f2 463 * @param {Number} f3 464 * @param {Number} f4 465 */ 466 setUniformLocationWith4f: function (location, f1, f2, f3, f4) { 467 var floats = [f1, f2, f3, f4]; 468 var updated = this._updateUniformLocation(location, floats); 469 if (updated) 470 this._glContext.uniform4f(location, f1, f2, f3, f4); 471 }, 472 473 /** 474 * calls glUniform2fv only if the values are different than the previous call for this same shader program. 475 * @param {WebGLUniformLocation} location 476 * @param {Float32Array} floatArray 477 * @param {Number} numberOfArrays 478 */ 479 setUniformLocationWith2fv: function (location, floatArray, numberOfArrays) { 480 var updated = this._updateUniformLocation(location, floatArray); 481 if (updated) 482 this._glContext.uniform2fv(location, floatArray); 483 }, 484 485 /** 486 * calls glUniform3fv only if the values are different than the previous call for this same shader program. 487 * @param {WebGLUniformLocation} location 488 * @param {Float32Array} floatArray 489 * @param {Number} numberOfArrays 490 */ 491 setUniformLocationWith3fv: function (location, floatArray, numberOfArrays) { 492 var updated = this._updateUniformLocation(location, floatArray); 493 if (updated) 494 this._glContext.uniform3fv(location, floatArray); 495 }, 496 497 /** 498 * calls glUniform4fv only if the values are different than the previous call for this same shader program. 499 * @param {WebGLUniformLocation} location 500 * @param {Float32Array} floatArray 501 * @param {Number} numberOfArrays 502 */ 503 setUniformLocationWith4fv: function (location, floatArray, numberOfArrays) { 504 var updated = this._updateUniformLocation(location, floatArray); 505 if (updated) 506 this._glContext.uniform4fv(location, floatArray); 507 }, 508 509 /** 510 * calls glUniformMatrix4fv only if the values are different than the previous call for this same shader program. 511 * @param {WebGLUniformLocation} location 512 * @param {Float32Array} matrixArray 513 * @param {Number} numberOfMatrices 514 */ 515 setUniformLocationWithMatrix4fv: function (location, matrixArray, numberOfMatrices) { 516 var updated = this._updateUniformLocation(location, matrixArray); 517 if (updated) 518 this._glContext.uniformMatrix4fv(location, false, matrixArray); 519 }, 520 521 setUniformLocationF32: function () { 522 if (arguments.length < 2) 523 return; 524 525 switch (arguments.length) { 526 case 2: 527 this.setUniformLocationWith1f(arguments[0], arguments[1]); 528 break; 529 case 3: 530 this.setUniformLocationWith2f(arguments[0], arguments[1], arguments[2]); 531 break; 532 case 4: 533 this.setUniformLocationWith3f(arguments[0], arguments[1], arguments[2], arguments[3]); 534 break; 535 case 5: 536 this.setUniformLocationWith4f(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]); 537 break; 538 } 539 }, 540 541 /** 542 * will update the builtin uniforms if they are different than the previous call for this same shader program. 543 */ 544 setUniformsForBuiltins: function () { 545 var matrixP = new cc.kmMat4(); 546 var matrixMV = new cc.kmMat4(); 547 var matrixMVP = new cc.kmMat4(); 548 549 cc.kmGLGetMatrix(cc.KM_GL_PROJECTION, matrixP); 550 cc.kmGLGetMatrix(cc.KM_GL_MODELVIEW, matrixMV); 551 552 cc.kmMat4Multiply(matrixMVP, matrixP, matrixMV); 553 554 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], matrixP.mat, 1); 555 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], matrixMV.mat, 1); 556 this.setUniformLocationWithMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], matrixMVP.mat, 1); 557 558 if (this._usesTime) { 559 var director = cc.director; 560 // This doesn't give the most accurate global time value. 561 // Cocos2D doesn't store a high precision time value, so this will have to do. 562 // Getting Mach time per frame per shader using time could be extremely expensive. 563 var time = director.getTotalFrames() * director.getAnimationInterval(); 564 565 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_TIME], time / 10.0, time, time * 2, time * 4); 566 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_SINTIME], time / 8.0, time / 4.0, time / 2.0, Math.sin(time)); 567 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_COSTIME], time / 8.0, time / 4.0, time / 2.0, Math.cos(time)); 568 } 569 570 if (this._uniforms[cc.UNIFORM_RANDOM01] != -1) 571 this.setUniformLocationWith4f(this._uniforms[cc.UNIFORM_RANDOM01], Math.random(), Math.random(), Math.random(), Math.random()); 572 }, 573 574 /** 575 * will update the MVP matrix on the MVP uniform if it is different than the previous call for this same shader program. 576 */ 577 setUniformForModelViewProjectionMatrix: function () { 578 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, 579 cc.getMat4MultiplyValue(cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top)); 580 }, 581 582 setUniformForModelViewProjectionMatrixWithMat4: function (swapMat4) { 583 cc.kmMat4Multiply(swapMat4, cc.projection_matrix_stack.top, cc.modelview_matrix_stack.top); 584 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVPMATRIX], false, swapMat4.mat); 585 }, 586 587 setUniformForModelViewAndProjectionMatrixWithMat4: function () { 588 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_MVMATRIX], false, cc.modelview_matrix_stack.top.mat); 589 this._glContext.uniformMatrix4fv(this._uniforms[cc.UNIFORM_PMATRIX], false, cc.projection_matrix_stack.top.mat); 590 }, 591 592 593 /** 594 * returns the vertexShader error log 595 * @return {String} 596 */ 597 vertexShaderLog: function () { 598 return this._glContext.getShaderInfoLog(this._vertShader); 599 }, 600 601 /** 602 * returns the vertexShader error log 603 * @return {String} 604 */ 605 getVertexShaderLog: function () { 606 return this._glContext.getShaderInfoLog(this._vertShader); 607 }, 608 609 /** 610 * returns the fragmentShader error log 611 * @returns {String} 612 */ 613 getFragmentShaderLog: function () { 614 return this._glContext.getShaderInfoLog(this._vertShader); 615 }, 616 617 /** 618 * returns the fragmentShader error log 619 * @return {String} 620 */ 621 fragmentShaderLog: function () { 622 return this._glContext.getShaderInfoLog(this._fragShader); 623 }, 624 625 /** 626 * returns the program error log 627 * @return {String} 628 */ 629 programLog: function () { 630 return this._glContext.getProgramInfoLog(this._programObj); 631 }, 632 633 /** 634 * returns the program error log 635 * @return {String} 636 */ 637 getProgramLog: function () { 638 return this._glContext.getProgramInfoLog(this._programObj); 639 }, 640 641 /** 642 * reload all shaders, this function is designed for android <br/> 643 * when opengl context lost, so don't call it. 644 */ 645 reset: function () { 646 this._vertShader = null; 647 this._fragShader = null; 648 this._uniforms.length = 0; 649 650 // it is already deallocated by android 651 //ccGLDeleteProgram(m_uProgram); 652 this._glContext.deleteProgram(this._programObj); 653 this._programObj = null; 654 655 // Purge uniform hash 656 for (var i = 0; i < this._hashForUniforms.length; i++) { 657 this._hashForUniforms[i].value = null; 658 this._hashForUniforms[i] = null; 659 } 660 661 this._hashForUniforms.length = 0; 662 }, 663 664 /** 665 * get WebGLProgram object 666 * @return {WebGLProgram} 667 */ 668 getProgram: function () { 669 return this._programObj; 670 }, 671 672 /** 673 * Currently JavaScript Bindings (JSB), in some cases, needs to use retain and release. This is a bug in JSB, 674 * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. 675 * This is a hack, and should be removed once JSB fixes the retain/release bug 676 */ 677 retain: function () { 678 }, 679 release: function () { 680 } 681 }); 682 683 /** 684 * Create a cc.GLProgram object 685 * @deprecated since v3.0, please use new cc.GLProgram(vShaderFileName, fShaderFileName) instead 686 * @param {String} vShaderFileName 687 * @param {String} fShaderFileName 688 * @returns {cc.GLProgram} 689 */ 690 cc.GLProgram.create = function (vShaderFileName, fShaderFileName) { 691 return new cc.GLProgram(vShaderFileName, fShaderFileName); 692 }; 693