13787204c76aebc1084e395f697ed2e2eb8377eb
[mupen64plus-pandora.git] / source / gles2rice / src / OGLES2FragmentShaders.cpp
1 /*
2 Copyright (C) 2003 Rice1964
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18
19 #include "OGLDebug.h"
20 #include "OGLES2FragmentShaders.h"
21 #include "OGLRender.h"
22 #include "OGLGraphicsContext.h"
23 #include "OGLTexture.h"
24
25 #define ALPHA_TEST "    if(gl_FragColor.a < AlphaRef) discard;                        \n"
26 //#define ALPHA_TEST
27 #define ENABLE  true
28 #define DISABLE  false
29
30 GLuint vertexProgram = 9999;
31 const char *vertexShader =
32 "#version " GLSL_VERSION "\n"
33 "attribute mediump vec4 aPosition;                          \n"\
34 "attribute lowp vec4    aColor;                             \n"\
35 "attribute lowp vec2    aTexCoord0;                         \n"\
36 "attribute lowp vec2    aTexCoord1;                         \n"\
37 "attribute lowp vec2    aAtlasTransform;                    \n"\
38 "attribute mediump float aFogCoord;                         \n"\
39 "                                                           \n"\
40 "uniform vec2 FogMinMax;                                    \n"\
41 "                                                           \n"\
42 "varying lowp float vFactor;                                \n"\
43 "varying lowp vec4  vShadeColor;                            \n"\
44 "varying mediump vec2 vTexCoord0;                           \n"\
45 "varying lowp vec2    vTexCoord1;                           \n"\
46 "varying lowp float   vFog;                                 \n"\
47 "                                                           \n"\
48 "void main()                                                \n"\
49 "{                                                          \n"\
50 "gl_Position = aPosition; //gl_Position.z = max(0.0,gl_Position.z);                                  \n"\
51 "vShadeColor = aColor;                                      \n"\
52 "vTexCoord0 = aTexCoord0;                                   \n"\
53 "vTexCoord1 = aTexCoord1;                                   \n"\
54 "vFog = (FogMinMax[1] - aFogCoord) / (FogMinMax[1] - FogMinMax[0]);  \n"\
55 "                                                           \n"\
56 "vFog = clamp(vFog, 0.0, 1.0);                              \n"\
57 "}                                                          \n"\
58 "                                                           \n";
59
60 const char *fragmentHeader =
61 "#define saturate(x) clamp( x, 0.0, 1.0 )                   \n"\
62 "precision lowp float;                                      \n"\
63 "#ifdef NEED_TEX0                                           \n"\
64 "uniform sampler2D uTex0;                                   \n"\
65 "#endif                                                     \n"\
66 "                                                           \n"\
67 "#ifdef NEED_TEX1                                           \n"\
68 "uniform sampler2D uTex1;                                   \n"\
69 "#endif                                                     \n"\
70 "                                                           \n"\
71 "uniform vec4 EnvColor;                                     \n"\
72 "uniform vec4 PrimColor;                                    \n"\
73 "uniform vec4 EnvFrac;                                      \n"\
74 "uniform vec4 PrimFrac;                                     \n"\
75 "uniform float AlphaRef;                                    \n"\
76 "uniform vec4 FogColor;                                     \n"\
77 "                                                           \n"\
78 "varying lowp vec4  vShadeColor;                            \n"\
79 "varying mediump vec2  vTexCoord0;                          \n"\
80 "varying lowp vec2  vTexCoord1;                             \n"\
81 "varying lowp float vFog;                                   \n"\
82 "                                                           \n"\
83 "void main()                                                \n"\
84 "{                                                          \n"\
85 "vec4 comb,comb2;                                           \n"\
86 "                                                           \n"\
87 "#ifdef NEED_TEX0                                           \n"\
88 "vec4 t0 = texture2D(uTex0,vTexCoord0);                     \n"\
89 "#endif                                                     \n"\
90 "                                                           \n"\
91 "#ifdef NEED_TEX1                                           \n"\
92 "vec4 t1 = texture2D(uTex1,vTexCoord1);                     \n"\
93 "#endif                                                     \n";
94
95 const char *fragmentFooter =
96 "                                                           \n"\
97 "#ifdef FOG                                                 \n"\
98 "gl_FragColor.rgb = mix(FogColor.rgb,comb.rgb,vFog);        \n"\
99 "gl_FragColor.a = comb.a;                                   \n"\
100 "#else                                                      \n"\
101 "gl_FragColor = comb;                                       \n"\
102 "#endif                                                     \n"\
103 "                                                           \n"\
104 "#ifdef ALPHA_TEST                                          \n"\
105    ALPHA_TEST                                                                  
106 "#endif                                                     \n"\
107 "}                                                          \n";
108
109 //Fragment shader for InitCycleCopy
110 const char *fragmentCopy =
111 "#version " GLSL_VERSION "\n"\
112 "precision lowp float;                                      \n"\
113 "uniform sampler2D uTex0;                                   \n"\
114 "uniform float AlphaRef;                                    \n"\
115 "varying lowp vec2 vTexCoord0;                              \n"\
116 "void main()                                                \n"\
117 "{                                                          \n"\
118 "   gl_FragColor = texture2D(uTex0,vTexCoord0).bgra;        \n"\
119 ALPHA_TEST
120 "}";
121
122 GLuint copyProgram,copyAlphaLocation;
123
124 //Fragment shader for InitCycleFill
125 const char *fragmentFill =
126 "#version " GLSL_VERSION "\n"\
127 "precision lowp float;                                      \n"
128 "uniform vec4 uColor;                                       \n"
129 "void main()                                                \n"
130 "{                                                          \n"
131 "   gl_FragColor = uColor;                                  \n"
132 "}";
133
134 GLuint fillProgram,fillColorLocation;
135
136 COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender)
137 : COGLColorCombiner(pRender)
138 {
139     m_bShaderIsSupported = true;
140 }
141 COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner()
142 {
143 }
144
145 bool COGLFragmentShaderCombiner::Initialize(void)
146 {
147     if( !COGLColorCombiner::Initialize() )
148         return false;
149
150     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
151 //    if( pcontext->IsExtensionSupported("GL_fragment_shader") )
152 //    {
153         m_bShaderIsSupported = true;
154 //    }
155
156     return true;
157 }
158
159 void COGLFragmentShaderCombiner::InitCombinerCycle12(void)
160 {
161 }
162 void COGLFragmentShaderCombiner::DisableCombiner(void)
163 {
164     COGLColorCombiner::DisableCombiner();
165 }
166
167 void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void)
168 {
169     COGLColorCombiner::InitCombinerCycleCopy();
170 }
171
172 void COGLFragmentShaderCombiner::InitCombinerCycleFill(void)
173 {
174     COGLColorCombiner::InitCombinerCycleFill();
175 }
176 void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
177 {
178     COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);
179 }
180
181 #ifdef DEBUGGER
182 void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void)
183 {
184     COGLColorCombiner::DisplaySimpleMuxString();
185 }
186 #endif
187
188
189
190 COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender)
191 : COGLColorCombiner4(pRender)
192 {
193     delete m_pDecodedMux;
194     m_pDecodedMux = new DecodedMuxForPixelShader;
195     m_bFragmentProgramIsSupported = true;
196     m_AlphaRef = 0.0f;
197     bAlphaTestState = false;
198     bAlphaTestPreviousState = false;
199     bFogState = false;
200     bFogPreviousState = false;
201
202     //Create shaders for fill and copy
203     GLint success;
204     GLuint vs,fs;
205     copyProgram = glCreateProgram();
206     vs = glCreateShader(GL_VERTEX_SHADER);
207     glShaderSource(vs,1,&vertexShader,NULL);
208     glCompileShader(vs);
209
210     glGetShaderiv(vs,GL_COMPILE_STATUS,&success);
211     if(!success)
212     {
213         char log[1024];
214         glGetShaderInfoLog(vs,1024,NULL,log);
215         printf("%s\n",log);
216     }
217
218     fs = glCreateShader(GL_FRAGMENT_SHADER);
219     glShaderSource(fs,1,&fragmentCopy,NULL);
220     glCompileShader(fs);
221
222     glGetShaderiv(fs,GL_COMPILE_STATUS,&success);
223     if(!success)
224     {
225         char log[1024];
226         glGetShaderInfoLog(fs,1024,NULL,log);
227         printf("%s\n",log);
228     }
229
230     glAttachShader(copyProgram,vs);
231     glAttachShader(copyProgram,fs);
232
233     glBindAttribLocation(copyProgram,VS_TEXCOORD0,"aTexCoord0");
234     OPENGL_CHECK_ERRORS;
235     glBindAttribLocation(copyProgram,VS_POSITION,"aPosition");
236     OPENGL_CHECK_ERRORS;
237
238     glLinkProgram(copyProgram);
239     copyAlphaLocation = glGetUniformLocation(copyProgram,"AlphaRef");
240     glGetProgramiv(copyProgram,GL_LINK_STATUS,&success);
241     if(!success)
242     {
243         char log[1024];
244         glGetProgramInfoLog(copyProgram,1024,NULL,log);
245         printf("%s\n",log);
246     }
247
248     glDeleteShader(fs);
249
250     //Fill shader
251     fs = glCreateShader(GL_FRAGMENT_SHADER);
252     glShaderSource(fs,1,&fragmentFill,NULL);
253     glCompileShader(fs);
254
255     glGetShaderiv(fs,GL_COMPILE_STATUS,&success);
256     if(!success)
257     {
258         char log[1024];
259         glGetShaderInfoLog(fs,1024,NULL,log);
260         printf("%s\n",log);
261     }
262
263     fillProgram = glCreateProgram();
264     glAttachShader(fillProgram,vs);
265     glAttachShader(fillProgram,fs);
266
267     glBindAttribLocation(fillProgram,VS_POSITION,"aPosition");
268     OPENGL_CHECK_ERRORS;
269
270     glLinkProgram(fillProgram);
271
272
273     fillColorLocation = glGetUniformLocation(fillProgram,"uColor");
274
275     glDeleteShader(fs);
276     glDeleteShader(vs);
277 }
278 COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner()
279 {
280     int size = m_vCompiledShaders.size();
281     for (int i=0; i<size; i++)
282     {
283         GLuint ID = m_vCompiledShaders[i].programID;
284         glDeleteProgram(ID);
285
286         OPENGL_CHECK_ERRORS;
287         m_vCompiledShaders[i].programID = 0;
288     }
289
290     m_vCompiledShaders.clear();
291 }
292
293 bool COGL_FragmentProgramCombiner::Initialize(void)
294 {
295     if( !COGLColorCombiner4::Initialize() )
296         return false;
297
298     COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
299 //    if( pcontext->IsExtensionSupported("GL_fragment_program") )
300 //    {
301         m_bFragmentProgramIsSupported = true;
302 //    }
303
304     return true;
305 }
306
307
308
309 void COGL_FragmentProgramCombiner::DisableCombiner(void)
310 {
311     //glDisable(GL_FRAGMENT_PROGRAM);
312     //OPENGL_CHECK_ERRORS;
313     COGLColorCombiner4::DisableCombiner();
314 }
315
316 void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)
317 {
318     m_pOGLRender->DisableMultiTexture();
319     m_pOGLRender->EnableTexUnit(0,TRUE);
320     glUseProgram(copyProgram);
321     glUniform1f(copyAlphaLocation,m_AlphaRef);
322     OPENGL_CHECK_ERRORS;
323     glEnableVertexAttribArray(VS_POSITION);
324     OPENGL_CHECK_ERRORS;
325     glEnableVertexAttribArray(VS_TEXCOORD0);
326     OPENGL_CHECK_ERRORS;
327     glDisableVertexAttribArray(VS_COLOR);
328     OPENGL_CHECK_ERRORS;
329     glDisableVertexAttribArray(VS_TEXCOORD1);
330     OPENGL_CHECK_ERRORS;
331         glDisableVertexAttribArray(VS_FOG);
332         OPENGL_CHECK_ERRORS;
333     COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
334     if( pTexture )
335     {
336         m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
337         m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile);
338     }
339 }
340
341 void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void)
342 {
343     glUseProgram(fillProgram);
344     glUniform4f(fillColorLocation,((gRDP.fillColor>>16)&0xFF)/255.0f,((gRDP.fillColor>>8)&0xFF)/255.0f,((gRDP.fillColor)&0xFF)/255.0f,((gRDP.fillColor>>24)&0xFF)/255.0f);
345     OPENGL_CHECK_ERRORS;
346 }
347
348 #ifdef BGR_SHADER
349 const char *muxToFP_Maps[][2] = {
350 //color -- alpha
351 {"vec3(0.0)", "0.0"},                      //MUX_0 = 0,
352 {"vec3(1.0)", "1.0"},                      //MUX_1,
353 {"comb.rgb", "comb.a"},                    //MUX_COMBINED,
354 {"t0.rgb", "t0.a"},                        //MUX_TEXEL0,
355 {"t1.rgb", "t1.a"},                        //MUX_TEXEL1,
356 {"PrimColor.rgb", "PrimColor.a"},          //MUX_PRIM,
357 {"vShadeColor.rgb", "vShadeColor.a"},      //MUX_SHADE,
358 {"EnvColor.rgb", "EnvColor.a"},            //MUX_ENV,
359 {"comb.rgb", "comb.a"},                    //MUX_COMBALPHA,
360 {"t0.rgb", "t0.a"},                        //MUX_T0_ALPHA,
361 {"t1.rgb", "t1.a"},                        //MUX_T1_ALPHA,
362 {"PrimColor.rgb", "PrimColor.a"},          //MUX_PRIM_ALPHA,
363 {"vShadeColor.rgb", "vShadeColor.a"},      //MUX_SHADE_ALPHA,
364 {"EnvColor.rgb", "EnvColor.a"},            //MUX_ENV_ALPHA,
365 {"EnvFrac.a", "EnvFrac.a"},                //MUX_LODFRAC,
366 {"PrimFrac.a", "PrimFrac.a"},              //MUX_PRIMLODFRAC,
367 {"vec3(1.0)", "1.0"},                      //MUX_K5,
368 {"vec3(1.0)", "1.0"},                      //MUX_UNK,  // Should not be used
369 };
370 #else
371 const char *muxToFP_Maps[][2] = {
372 //color -- alpha
373 {"vec3(0.0)", "0.0"}, //MUX_0 = 0,
374 {"vec3(1.0)", "1.0"}, //MUX_1,
375 {"comb.rgb", "comb.a"}, //MUX_COMBINED,
376 {"t0.bgr", "t0.a"}, //MUX_TEXEL0,
377 {"t1.bgr", "t1.a"}, //MUX_TEXEL1,
378 {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM,
379 {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE,
380 {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV,
381 {"comb.rgb", "comb.a"}, //MUX_COMBALPHA,
382 {"t0.bgr", "t0.a"}, //MUX_T0_ALPHA,
383 {"t1.bgr", "t1.a"}, //MUX_T1_ALPHA,
384 {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA,
385 {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA,
386 {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA,
387 {"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC,
388 {"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC,
389 {"vec3(1.0)", "1.0"}, //MUX_K5,
390 {"vec3(1.0)", "1.0"}, //MUX_UNK,  // Should not be used
391 };
392 #endif
393
394
395 char oglNewFP[4092];
396
397 char* MuxToOC(uint8 val)
398 {
399 // For color channel
400 if( val&MUX_ALPHAREPLICATE )
401     return (char*)muxToFP_Maps[val&0x1F][1];
402 else
403     return (char*)muxToFP_Maps[val&0x1F][0];
404 }
405
406 char* MuxToOA(uint8 val)
407 {
408 // For alpha channel
409 return (char*)muxToFP_Maps[val&0x1F][1];
410 }
411
412 static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1)
413 {
414     MuxVar &= 0x1f;
415     if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA)
416         bNeedT0 = true;
417     if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA)
418         bNeedT1 = true;
419 }
420
421 void COGL_FragmentProgramCombiner::GenerateProgramStr()
422 {
423     DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
424
425     mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;
426     m_pDecodedMux->Reformat(false);
427
428     char tempstr[500], newFPBody[4092];
429     bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false;
430     newFPBody[0] = 0;
431
432     for( int cycle=0; cycle<2; cycle++ )
433     {
434         for( int channel=0; channel<2; channel++)
435         {
436             char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA;
437             char *dst = channel==0?(char*)"rgb":(char*)"a";
438             N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel];
439             switch( mux.splitType[cycle*2+channel] )
440             {
441             case CM_FMT_TYPE_NOT_USED:
442                 tempstr[0] = 0;
443                 break;
444             case CM_FMT_TYPE_D:
445                 sprintf(tempstr, "comb.%s = %s;\n", dst, func(m.d));
446                 CheckFpVars(m.d, bNeedT0, bNeedT1);
447                 break;
448             case CM_FMT_TYPE_A_MOD_C:
449                 sprintf(tempstr, "comb.%s = %s * %s;\n", dst, func(m.a), func(m.c));
450                 CheckFpVars(m.a, bNeedT0, bNeedT1);
451                 CheckFpVars(m.c, bNeedT0, bNeedT1);
452                 break;
453             case CM_FMT_TYPE_A_ADD_D:
454                 sprintf(tempstr, "comb.%s = saturate(%s + %s);\n", dst, func(m.a), func(m.d));
455                 CheckFpVars(m.a, bNeedT0, bNeedT1);
456                 CheckFpVars(m.d, bNeedT0, bNeedT1);
457                 break;
458             case CM_FMT_TYPE_A_SUB_B:
459                 sprintf(tempstr, "comb.%s = %s - %s;\n", dst, func(m.a), func(m.b));
460                 CheckFpVars(m.a, bNeedT0, bNeedT1);
461                 CheckFpVars(m.b, bNeedT0, bNeedT1);
462                 break;
463             case CM_FMT_TYPE_A_MOD_C_ADD_D:
464                 sprintf(tempstr, "comb.%s = saturate(%s * %s + %s);\n", dst, func(m.a), func(m.c),func(m.d));
465                 CheckFpVars(m.a, bNeedT0, bNeedT1);
466                 CheckFpVars(m.c, bNeedT0, bNeedT1);
467                 CheckFpVars(m.d, bNeedT0, bNeedT1);
468                 break;
469             case CM_FMT_TYPE_A_LERP_B_C:
470                 //ARB ASM LERP and mix have different parameter ordering.
471                 //sprintf(tempstr, "comb.%s = saturate(mix(%s, %s, %s));\n", dst,func(m.a),func(m.b), func(m.c));
472                 sprintf(tempstr, "comb.%s = (%s - %s) * %s + %s;\n", dst,func(m.a),func(m.b), func(m.c),func(m.b));
473                 CheckFpVars(m.a, bNeedT0, bNeedT1);
474                 CheckFpVars(m.b, bNeedT0, bNeedT1);
475                 CheckFpVars(m.c, bNeedT0, bNeedT1);
476                 //sprintf(tempstr, "SUB comb.%s, %s, %s;\nMAD_SAT comb.%s, comb, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.b));
477                 break;
478             default:
479                 sprintf(tempstr, "comb2.%s = %s - %s;\ncomb.%s = saturate(comb2.%s * %s + %s);\n", dst, func(m.a), func(m.b),  dst,dst, func(m.c),func(m.d));
480                 CheckFpVars(m.a, bNeedT0, bNeedT1);
481                 CheckFpVars(m.b, bNeedT0, bNeedT1);
482                 CheckFpVars(m.c, bNeedT0, bNeedT1);
483                 CheckFpVars(m.d, bNeedT0, bNeedT1);
484                 bNeedComb2 = true;
485                 break;
486             }
487             strcat(newFPBody, tempstr);
488         }
489     }
490
491     oglNewFP[0] = 0;
492     if (bNeedT0)
493         strcat(oglNewFP, "#define NEED_TEX0\n");
494     if (bNeedT1)
495         strcat(oglNewFP, "#define NEED_TEX1\n");
496     strcat(oglNewFP, fragmentHeader);
497     strcat(oglNewFP, newFPBody);
498     strcat(oglNewFP, fragmentFooter);
499
500 }
501
502 int COGL_FragmentProgramCombiner::ParseDecodedMux()
503 {
504     if( !m_bFragmentProgramIsSupported )
505         return COGLColorCombiner4::ParseDecodedMux();
506
507     OGLShaderCombinerSaveType res;
508     GLint success;
509
510     if(vertexProgram == 9999)
511     {
512         vertexProgram = res.vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
513         glShaderSource(res.vertexShaderID, 1, &vertexShader,NULL);
514         OPENGL_CHECK_ERRORS;
515         glCompileShader(res.vertexShaderID);
516         OPENGL_CHECK_ERRORS;
517     }
518     else
519     {
520         res.vertexShaderID = vertexProgram;
521     }
522
523
524     //Create 4 shaders, with and without alphatest + with and without fog
525     GenerateProgramStr();
526
527     for(int alphaTest = 0;alphaTest < 2;alphaTest++)
528     {
529                 for(int fog = 0;fog < 2;fog++) {
530                         res.fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
531
532                         char* tmpShader = (char*)malloc(sizeof(char) * 4096);
533                         strcpy(tmpShader,"#version " GLSL_VERSION "\n");
534
535                         if(alphaTest == 1)
536                         {
537                                 strcat(tmpShader,"#define ALPHA_TEST\n");
538                         }
539                         if(fog == 1)
540                         {
541                                 strcat(tmpShader,"#define FOG\n");
542                         }
543
544                         res.fogIsUsed = fog == 1;
545                         res.alphaTest = alphaTest == 1;
546                         strcat(tmpShader,oglNewFP);
547
548                         glShaderSource(res.fragmentShaderID, 1,(const char**) &tmpShader,NULL);
549                         free(tmpShader);
550
551
552                         OPENGL_CHECK_ERRORS;
553                         glCompileShader(res.fragmentShaderID);
554
555                         glGetShaderiv(res.fragmentShaderID, GL_COMPILE_STATUS, &success);
556                         if (!success)
557                         {
558                                 char Log[1024];
559                                 GLint nLength;
560                                 glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);
561                                 printf("Error compiling shader!\n %s",oglNewFP);
562                                 printf("%s", Log);
563                         }
564
565                         res.programID = glCreateProgram();
566                         glAttachShader(res.programID,res.vertexShaderID);
567                         glAttachShader(res.programID,res.fragmentShaderID);
568
569                         //Bind Attributes
570                         glBindAttribLocation(res.programID,VS_COLOR,"aColor");
571                         OPENGL_CHECK_ERRORS;
572                         glBindAttribLocation(res.programID,VS_TEXCOORD0,"aTexCoord0");
573                         OPENGL_CHECK_ERRORS;
574                         glBindAttribLocation(res.programID,VS_TEXCOORD1,"aTexCoord1");
575                         OPENGL_CHECK_ERRORS;
576                         glBindAttribLocation(res.programID,VS_POSITION,"aPosition");
577                         OPENGL_CHECK_ERRORS;
578                         glBindAttribLocation(res.programID,VS_FOG,"aFogCoord");
579                         OPENGL_CHECK_ERRORS;
580
581                         glLinkProgram(res.programID);
582                         OPENGL_CHECK_ERRORS;
583
584                         glGetProgramiv(res.programID, GL_LINK_STATUS, &success);
585                         if (!success)
586                         {
587                                 char Log[1024];
588                                 GLint nLength;
589                                 glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);
590                                 printf("Error linking program!\n");
591                                 printf("%s\n",Log);
592                         }
593
594                         glUseProgram(res.programID);
595                         OPENGL_CHECK_ERRORS;
596
597                         //Bind texture samplers
598                         GLint tex0 = glGetUniformLocation(res.programID,"uTex0");
599                         GLint tex1 = glGetUniformLocation(res.programID,"uTex1");
600
601                         if(tex0 != -1)
602                                 glUniform1i(tex0,0);
603                         if(tex1 != -1)
604                                 glUniform1i(tex1,1);
605
606                         //Bind Uniforms
607                         res.PrimColorLocation = glGetUniformLocation(res.programID,"PrimColor");
608                         OPENGL_CHECK_ERRORS;
609                         res.EnvColorLocation = glGetUniformLocation(res.programID,"EnvColor");
610                         OPENGL_CHECK_ERRORS;
611                         res.PrimFracLocation = glGetUniformLocation(res.programID,"PrimFrac");
612                         OPENGL_CHECK_ERRORS;
613                         res.EnvFracLocation = glGetUniformLocation(res.programID,"EnvFrac");
614                         OPENGL_CHECK_ERRORS;
615                         res.AlphaRefLocation = glGetUniformLocation(res.programID,"AlphaRef");
616                         OPENGL_CHECK_ERRORS;
617                         res.FogColorLocation = glGetUniformLocation(res.programID,"FogColor");
618                         OPENGL_CHECK_ERRORS;
619                         res.FogMinMaxLocation = glGetUniformLocation(res.programID,"FogMinMax");
620                         OPENGL_CHECK_ERRORS;
621
622                         res.dwMux0 = m_pDecodedMux->m_dwMux0;
623                         res.dwMux1 = m_pDecodedMux->m_dwMux1;
624
625                         m_vCompiledShaders.push_back(res);
626                 }
627     }
628     m_lastIndex = m_vCompiledShaders.size()-4;
629
630     return m_lastIndex;
631 }
632
633 void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)
634 {
635     GLuint ID = m_vCompiledShaders[index].programID;
636
637     glUseProgram(ID);
638     glEnableVertexAttribArray(VS_POSITION);
639     OPENGL_CHECK_ERRORS;
640     glVertexAttribPointer(VS_POSITION,4,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][0]));
641     OPENGL_CHECK_ERRORS;
642
643     glEnableVertexAttribArray(VS_TEXCOORD0);
644     OPENGL_CHECK_ERRORS;
645     glVertexAttribPointer(VS_TEXCOORD0,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[0].u));
646     OPENGL_CHECK_ERRORS;
647
648     glEnableVertexAttribArray(VS_TEXCOORD1);
649     OPENGL_CHECK_ERRORS;
650     glVertexAttribPointer(VS_TEXCOORD1,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[1].u));
651     OPENGL_CHECK_ERRORS;
652
653     glEnableVertexAttribArray(VS_COLOR);
654     OPENGL_CHECK_ERRORS;
655     glVertexAttribPointer(VS_COLOR, 4, GL_UNSIGNED_BYTE,GL_TRUE, sizeof(uint8)*4, &(g_oglVtxColors[0][0]) );
656     OPENGL_CHECK_ERRORS;
657         
658         glEnableVertexAttribArray(VS_FOG);
659         OPENGL_CHECK_ERRORS;
660         glVertexAttribPointer(VS_FOG,1,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][4]));
661         OPENGL_CHECK_ERRORS;
662 }
663
664 void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index)
665 {
666     OGLShaderCombinerSaveType prog = m_vCompiledShaders[index];
667
668     glUseProgram(prog.programID);
669     float *pf;
670     if(prog.EnvColorLocation != -1)
671     {
672         pf = GetEnvColorfv();
673         glUniform4fv(prog.EnvColorLocation,1, pf);
674         OPENGL_CHECK_ERRORS;
675     }
676
677     if(prog.PrimColorLocation != -1)
678     {
679         pf = GetPrimitiveColorfv();
680         glUniform4fv(prog.PrimColorLocation,1, pf);
681         OPENGL_CHECK_ERRORS;
682     }
683
684     if(prog.EnvFracLocation != -1)
685     {
686         float frac = gRDP.LODFrac / 255.0f;
687         float tempf[4] = {frac,frac,frac,frac};
688         glUniform4fv(prog.EnvFracLocation,1, tempf);
689         OPENGL_CHECK_ERRORS;
690     }
691
692     if(prog.PrimFracLocation != -1)
693     {
694         float frac2 = gRDP.primLODFrac / 255.0f;
695         float tempf2[4] = {frac2,frac2,frac2,frac2};
696         glUniform4fv(prog.PrimFracLocation,1, tempf2);
697         OPENGL_CHECK_ERRORS;
698     }
699
700         if(prog.FogColorLocation != -1)
701     {
702         glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2], gRDP.fvFogColor[3]);
703         OPENGL_CHECK_ERRORS;
704     }
705         
706         if(prog.FogMinMaxLocation != -1)        
707         {
708         glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);
709         OPENGL_CHECK_ERRORS;
710     }
711         
712     if(prog.AlphaRefLocation != -1)
713         {
714         glUniform1f(prog.AlphaRefLocation,m_AlphaRef);
715                 OPENGL_CHECK_ERRORS;
716         }
717 }
718
719 int COGL_FragmentProgramCombiner::FindCompiledMux()
720 {
721 #ifdef DEBUGGER
722     if( debuggerDropCombiners )
723     {
724         m_vCompiledShaders.clear();
725         //m_dwLastMux0 = m_dwLastMux1 = 0;
726         debuggerDropCombiners = false;
727     }
728 #endif
729     for( uint32 i=0; i<m_vCompiledShaders.size(); i++ )
730     {
731         if( m_vCompiledShaders[i].dwMux0 == m_pDecodedMux->m_dwMux0 
732             && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1 
733             && m_vCompiledShaders[i].fogIsUsed == bFogState
734             && m_vCompiledShaders[i].alphaTest == bAlphaTestState)
735         {
736             return (int)i;
737         }
738     }
739
740     return -1;
741 }
742
743 //////////////////////////////////////////////////////////////////////////
744 void COGL_FragmentProgramCombiner::InitCombinerCycle12(void)
745 {
746     if( !m_bFragmentProgramIsSupported )    
747     {
748         COGLColorCombiner4::InitCombinerCycle12();
749         return;
750     }
751
752 #ifdef DEBUGGER
753     if( debuggerDropCombiners )
754     {
755         UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1);
756         m_vCompiledShaders.clear();
757         m_dwLastMux0 = m_dwLastMux1 = 0;
758         debuggerDropCombiners = false;
759     }
760 #endif
761
762     m_pOGLRender->EnableMultiTexture();
763
764     bool combinerIsChanged = false;
765
766     if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 
767           || bAlphaTestState != bAlphaTestPreviousState || bFogState != bFogPreviousState || m_lastIndex < 0 )
768     {
769         combinerIsChanged = true;
770         m_lastIndex = FindCompiledMux();
771         if( m_lastIndex < 0 )       // Can not found
772         {
773             m_lastIndex = ParseDecodedMux();
774         }
775
776         m_dwLastMux0 = m_pDecodedMux->m_dwMux0;
777         m_dwLastMux1 = m_pDecodedMux->m_dwMux1;
778         bAlphaTestPreviousState = bAlphaTestState;
779         bFogPreviousState = bFogState;
780         m_AlphaRef = (float)(m_pOGLRender->m_dwAlpha)/255.0f;    
781         }
782
783
784     GenerateCombinerSettingConstants(m_lastIndex);
785     if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )
786     {
787         if( m_bCycleChanged || combinerIsChanged )
788         {
789             GenerateCombinerSettingConstants(m_lastIndex);
790             GenerateCombinerSetting(m_lastIndex);
791         }
792         else if( gRDP.colorsAreReloaded )
793         {
794             GenerateCombinerSettingConstants(m_lastIndex);
795         }
796
797         m_pOGLRender->SetAllTexelRepeatFlag();
798
799         gRDP.colorsAreReloaded = false;
800         gRDP.texturesAreReloaded = false;
801     }
802     else
803     {
804         m_pOGLRender->SetAllTexelRepeatFlag();
805     }
806 }
807
808 #ifdef DEBUGGER
809 void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void)
810 {
811     COGLColorCombiner::DisplaySimpleMuxString();
812     DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
813     mux.Reformat(false);
814     GenerateProgramStr();
815     //sprintf(oglNewFP, oglFP, 
816     //  MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0),
817     //  MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0),
818     //  MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1),
819     //  MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1)
820     //  );
821
822     TRACE0("OGL Fragment Program:");
823     TRACE0(oglNewFP);
824 }
825 #endif
826