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