GLES2RICE: Fix for good this time the shader not compiling
[mupen64plus-pandora.git] / source / gles2rice / src / OGLES2FragmentShaders.cpp
CommitLineData
292f9317 1/*
2Copyright (C) 2003 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, 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
0c9dca78 27#define ENABLE true
28#define DISABLE false
292f9317 29
30GLuint vertexProgram = 9999;
31const 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"\
ea03ad21 38"attribute mediump float aFogCoord; \n"\
292f9317 39" \n"\
74e43de0 40"uniform vec2 FogMinMax; \n"\
41" \n"\
292f9317 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"\
74e43de0 54"vFog = (FogMinMax[1] - aFogCoord) / (FogMinMax[1] - FogMinMax[0]); \n"\
292f9317 55" \n"\
74e43de0 56"vFog = clamp(vFog, 0.0, 1.0); \n"\
292f9317 57"} \n"\
58" \n";
59
60const 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"\
292f9317 78"varying lowp vec4 vShadeColor; \n"\
79"varying mediump vec2 vTexCoord0; \n"\
80"varying lowp vec2 vTexCoord1; \n"\
7ec5739f 81"varying lowp float vFog; \n"\
292f9317 82" \n"\
83"void main() \n"\
84"{ \n"\
85"vec4 comb,comb2; \n"\
86" \n"\
ea03ad21 87"#ifdef NEED_TEX0 \n"\
292f9317 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
95const char *fragmentFooter =
96" \n"\
97"#ifdef FOG \n"\
ea03ad21 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"\
0c9dca78 105 ALPHA_TEST
ea03ad21 106"#endif \n"\
292f9317 107"} \n";
108
109//Fragment shader for InitCycleCopy
110const 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"\
119ALPHA_TEST
120"}";
121
122GLuint copyProgram,copyAlphaLocation;
123
124//Fragment shader for InitCycleFill
125const 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
134GLuint fillProgram,fillColorLocation;
135
136COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender)
137: COGLColorCombiner(pRender)
138{
139 m_bShaderIsSupported = true;
140}
141COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner()
142{
143}
144
145bool 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
159void COGLFragmentShaderCombiner::InitCombinerCycle12(void)
160{
161}
162void COGLFragmentShaderCombiner::DisableCombiner(void)
163{
164 COGLColorCombiner::DisableCombiner();
165}
166
167void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void)
168{
169 COGLColorCombiner::InitCombinerCycleCopy();
170}
171
172void COGLFragmentShaderCombiner::InitCombinerCycleFill(void)
173{
174 COGLColorCombiner::InitCombinerCycleFill();
175}
176void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
177{
178 COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);
179}
180
181#ifdef DEBUGGER
182void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void)
183{
184 COGLColorCombiner::DisplaySimpleMuxString();
185}
186#endif
187
188
189
190COGL_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;
ea03ad21 197 bAlphaTestState = false;
198 bAlphaTestPreviousState = false;
199 bFogState = false;
200 bFogPreviousState = false;
292f9317 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}
278COGL_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
293bool 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
309void COGL_FragmentProgramCombiner::DisableCombiner(void)
310{
311 //glDisable(GL_FRAGMENT_PROGRAM);
312 //OPENGL_CHECK_ERRORS;
313 COGLColorCombiner4::DisableCombiner();
314}
315
316void 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;
ea03ad21 331 glDisableVertexAttribArray(VS_FOG);
332 OPENGL_CHECK_ERRORS;
292f9317 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
341void 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
349const 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
371const 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
395char oglNewFP[4092];
396
397char* MuxToOC(uint8 val)
398{
399// For color channel
400if( val&MUX_ALPHAREPLICATE )
401 return (char*)muxToFP_Maps[val&0x1F][1];
402else
403 return (char*)muxToFP_Maps[val&0x1F][0];
404}
405
406char* MuxToOA(uint8 val)
407{
408// For alpha channel
409return (char*)muxToFP_Maps[val&0x1F][1];
410}
411
412static 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
421void 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");
292f9317 496 strcat(oglNewFP, fragmentHeader);
497 strcat(oglNewFP, newFPBody);
498 strcat(oglNewFP, fragmentFooter);
499
500}
501
502int 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
0c9dca78 524 //Create 4 shaders, with and without alphatest + with and without fog
292f9317 525 GenerateProgramStr();
526
527 for(int alphaTest = 0;alphaTest < 2;alphaTest++)
528 {
0c9dca78 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;
ea03ad21 578 glBindAttribLocation(res.programID,VS_FOG,"aFogCoord");
579 OPENGL_CHECK_ERRORS;
0c9dca78 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 }
292f9317 627 }
0c9dca78 628 m_lastIndex = m_vCompiledShaders.size()-4;
292f9317 629
630 return m_lastIndex;
631}
632
633void 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;
ea03ad21 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;
292f9317 662}
663
664void 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
0c9dca78 700 if(prog.FogColorLocation != -1)
292f9317 701 {
0c9dca78 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 {
292f9317 708 glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);
709 OPENGL_CHECK_ERRORS;
710 }
0c9dca78 711
712 if(prog.AlphaRefLocation != -1)
713 {
714 glUniform1f(prog.AlphaRefLocation,m_AlphaRef);
715 OPENGL_CHECK_ERRORS;
716 }
292f9317 717}
718
719int 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
0c9dca78 733 && m_vCompiledShaders[i].fogIsUsed == bFogState
734 && m_vCompiledShaders[i].alphaTest == bAlphaTestState)
292f9317 735 {
736 return (int)i;
737 }
738 }
739
740 return -1;
741}
742
743//////////////////////////////////////////////////////////////////////////
744void 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
0c9dca78 766 if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1
767 || bAlphaTestState != bAlphaTestPreviousState || bFogState != bFogPreviousState || m_lastIndex < 0 )
292f9317 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;
0c9dca78 778 bAlphaTestPreviousState = bAlphaTestState;
779 bFogPreviousState = bFogState;
780 m_AlphaRef = (float)(m_pOGLRender->m_dwAlpha)/255.0f;
781 }
292f9317 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
809void 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