1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 /**
 28  * @constant
 29  * @type {Number}
 30  */
 31 cc.SHADERTYPE_POSITION_TEXTURECOLOR = 0;
 32 /**
 33  * @constant
 34  * @type {Number}
 35  */
 36 cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST = 1;
 37 /**
 38  * @constant
 39  * @type {Number}
 40  */
 41 cc.SHADERTYPE_POSITION_COLOR = 2;
 42 /**
 43  * @constant
 44  * @type {Number}
 45  */
 46 cc.SHADERTYPE_POSITION_TEXTURE = 3;
 47 /**
 48  * @constant
 49  * @type {Number}
 50  */
 51 cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR = 4;
 52 /**
 53  * @constant
 54  * @type {Number}
 55  */
 56 cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR = 5;
 57 /**
 58  * @constant
 59  * @type {Number}
 60  */
 61 cc.SHADERTYPE_POSITION_UCOLOR = 6;
 62 /**
 63  * @constant
 64  * @type {Number}
 65  */
 66 cc.SHADERTYPE_POSITION_LENGTH_TEXTURECOLOR = 7;
 67 
 68 /**
 69  * @constant
 70  * @type {Number}
 71  */
 72 cc.SHADERTYPE_MAX = 8;
 73 
 74 cc._sharedShaderCache = null;
 75 
 76 /**
 77  * Singleton that stores manages GL shaders
 78  * @class
 79  * @extends cc.Class
 80  */
 81 cc.ShaderCache = cc.Class.extend({
 82     _programs: null,
 83 
 84     _init: function () {
 85         this.loadDefaultShaders();
 86         return true;
 87     },
 88 
 89     _loadDefaultShader: function (program, type) {
 90         switch (type) {
 91             case cc.SHADERTYPE_POSITION_TEXTURECOLOR:
 92                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_FRAG);
 93 
 94                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
 95                 program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
 96                 program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
 97                 break;
 98             case cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST:
 99                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_COLOR_VERT, cc.SHADER_POSITION_TEXTURE_COLOR_ALPHATEST_FRAG);
100 
101                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
102                 program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
103                 program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
104                 break;
105             case cc.SHADERTYPE_POSITION_COLOR:
106                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_COLOR_VERT, cc.SHADER_POSITION_COLOR_FRAG);
107 
108                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
109                 program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
110                 break;
111             case cc.SHADERTYPE_POSITION_TEXTURE:
112                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_VERT, cc.SHADER_POSITION_TEXTURE_FRAG);
113 
114                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
115                 program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
116                 break;
117             case cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR:
118                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_UCOLOR_VERT, cc.SHADER_POSITION_TEXTURE_UCOLOR_FRAG);
119 
120                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
121                 program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
122                 break;
123             case cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR:
124                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_TEXTURE_A8COLOR_VERT, cc.SHADER_POSITION_TEXTURE_A8COLOR_FRAG);
125 
126                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
127                 program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
128                 program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
129                 break;
130             case cc.SHADERTYPE_POSITION_UCOLOR:
131                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_UCOLOR_VERT, cc.SHADER_POSITION_UCOLOR_FRAG);
132                 program.addAttribute("aVertex", cc.VERTEX_ATTRIB_POSITION);
133                 break;
134             case cc.SHADERTYPE_POSITION_LENGTH_TEXTURECOLOR:
135                 program.initWithVertexShaderByteArray(cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_VERT, cc.SHADER_POSITION_COLOR_LENGTH_TEXTURE_FRAG);
136 
137                 program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
138                 program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
139                 program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
140                 break;
141             default:
142                 cc.log("cocos2d: cc.ShaderCache._loadDefaultShader, error shader type");
143                 return;
144         }
145 
146         program.link();
147         program.updateUniforms();
148 
149         //cc.CHECK_GL_ERROR_DEBUG();
150     },
151 
152     /**
153      * Constructor
154      * @override
155      */
156     ctor: function () {
157         this._programs = {};
158     },
159 
160     /**
161      * loads the default shaders
162      */
163     loadDefaultShaders: function () {
164         // Position Texture Color shader
165         var program = new cc.GLProgram();
166         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR);
167         this._programs[cc.SHADER_POSITION_TEXTURECOLOR] = program;
168         this._programs["ShaderPositionTextureColor"] = program;
169 
170         // Position Texture Color alpha test
171         program = new cc.GLProgram();
172         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST);
173         this._programs[cc.SHADER_POSITION_TEXTURECOLORALPHATEST] = program;
174         this._programs["ShaderPositionTextureColorAlphaTest"] = program;
175 
176         //
177         // Position, Color shader
178         //
179         program = new cc.GLProgram();
180         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_COLOR);
181         this._programs[cc.SHADER_POSITION_COLOR] = program;
182         this._programs["ShaderPositionColor"] = program;
183 
184         //
185         // Position Texture shader
186         //
187         program = new cc.GLProgram();
188         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE);
189         this._programs[cc.SHADER_POSITION_TEXTURE] = program;
190         this._programs["ShaderPositionTexture"] = program;
191 
192         //
193         // Position, Texture attribs, 1 Color as uniform shader
194         //
195         program = new cc.GLProgram();
196         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR);
197         this._programs[cc.SHADER_POSITION_TEXTURE_UCOLOR] = program;
198         this._programs["ShaderPositionTextureUColor"] = program;
199 
200         //
201         // Position Texture A8 Color shader
202         //
203         program = new cc.GLProgram();
204         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR);
205         this._programs[cc.SHADER_POSITION_TEXTUREA8COLOR] = program;
206         this._programs["ShaderPositionTextureA8Color"] = program;
207 
208         //
209         // Position and 1 color passed as a uniform (to similate glColor4ub )
210         //
211         program = new cc.GLProgram();
212         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_UCOLOR);
213         this._programs[cc.SHADER_POSITION_UCOLOR] = program;
214         this._programs["ShaderPositionUColor"] = program;
215 
216         //
217         // Position, Legth(TexCoords, Color (used by Draw Node basically )
218         //
219         program = new cc.GLProgram();
220         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_LENGTH_TEXTURECOLOR);
221         this._programs[cc.SHADER_POSITION_LENGTHTEXTURECOLOR] = program;
222         this._programs["ShaderPositionLengthTextureColor"] = program;
223     },
224 
225     /**
226      * reload the default shaders
227      */
228     reloadDefaultShaders: function () {
229         // reset all programs and reload them
230 
231         // Position Texture Color shader
232         var program = this.programForKey(cc.SHADER_POSITION_TEXTURECOLOR);
233         program.reset();
234         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR);
235 
236         // Position Texture Color alpha test
237         program = this.programForKey(cc.SHADER_POSITION_TEXTURECOLORALPHATEST);
238         program.reset();
239         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURECOLOR_ALPHATEST);
240 
241         //
242         // Position, Color shader
243         //
244         program = this.programForKey(cc.SHADER_POSITION_COLOR);
245         program.reset();
246         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_COLOR);
247 
248         //
249         // Position Texture shader
250         //
251         program = this.programForKey(cc.SHADER_POSITION_TEXTURE);
252         program.reset();
253         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE);
254 
255         //
256         // Position, Texture attribs, 1 Color as uniform shader
257         //
258         program = this.programForKey(cc.SHADER_POSITION_TEXTURE_UCOLOR);
259         program.reset();
260         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_UCOLOR);
261 
262         //
263         // Position Texture A8 Color shader
264         //
265         program = this.programForKey(cc.SHADER_POSITION_TEXTUREA8COLOR);
266         program.reset();
267         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_TEXTURE_A8COLOR);
268 
269         //
270         // Position and 1 color passed as a uniform (to similate glColor4ub )
271         //
272         program = this.programForKey(cc.SHADER_POSITION_UCOLOR);
273         program.reset();
274         this._loadDefaultShader(program, cc.SHADERTYPE_POSITION_UCOLOR);
275     },
276 
277     /** returns a GL program for a given key */
278     programForKey: function (key) {
279         return this._programs[key];
280     },
281 
282     /**
283      * returns a GL program for a shader name
284      * @param {String} shaderName
285      * @return cc.GLProgram
286      */
287     getProgram: function (shaderName) {
288         return this._programs[shaderName];
289     },
290 
291     /** adds a CCGLProgram to the cache for a given name */
292     addProgram: function (program, key) {
293         this._programs[key] = program;
294     }
295 });
296 
297 /**  */
298 /**
299  *  returns the cc.ShaderCache instance
300  * @return {cc.ShaderCache}
301  */
302 cc.ShaderCache.getInstance = function () {
303     if (!cc._sharedShaderCache) {
304         cc._sharedShaderCache = new cc.ShaderCache();
305         cc._sharedShaderCache._init();
306     }
307     return cc._sharedShaderCache;
308 };
309 
310 /**
311  *  purges the cache. It releases the retained instance.
312  */
313 cc.ShaderCache.purgeSharedShaderCache = function () {
314     cc._sharedShaderCache = null;
315 };