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