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