GLE2RICE: Some fixes from muppen64plus-ae
[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"\
38" \n"\
292f9317 39"varying lowp float vFactor; \n"\
40"varying lowp vec4 vShadeColor; \n"\
41"varying mediump vec2 vTexCoord0; \n"\
42"varying lowp vec2 vTexCoord1; \n"\
43"varying lowp float vFog; \n"\
44" \n"\
45"void main() \n"\
46"{ \n"\
47"gl_Position = aPosition; //gl_Position.z = max(0.0,gl_Position.z); \n"\
48"vShadeColor = aColor; \n"\
49"vTexCoord0 = aTexCoord0; \n"\
50"vTexCoord1 = aTexCoord1; \n"\
292f9317 51" \n"\
52"} \n"\
53" \n";
54
55const char *fragmentHeader =
56"#define saturate(x) clamp( x, 0.0, 1.0 ) \n"\
57"precision lowp float; \n"\
58"#ifdef NEED_TEX0 \n"\
59"uniform sampler2D uTex0; \n"\
60"#endif \n"\
61" \n"\
62"#ifdef NEED_TEX1 \n"\
63"uniform sampler2D uTex1; \n"\
64"#endif \n"\
65" \n"\
66"uniform vec4 EnvColor; \n"\
67"uniform vec4 PrimColor; \n"\
68"uniform vec4 EnvFrac; \n"\
69"uniform vec4 PrimFrac; \n"\
70"uniform float AlphaRef; \n"\
71"uniform vec4 FogColor; \n"\
0c9dca78 72"uniform vec2 FogMinMax; \n"\
292f9317 73" \n"\
74"varying lowp float vFactor; \n"\
75"varying lowp vec4 vShadeColor; \n"\
76"varying mediump vec2 vTexCoord0; \n"\
77"varying lowp vec2 vTexCoord1; \n"\
292f9317 78" \n"\
79"void main() \n"\
80"{ \n"\
81"vec4 comb,comb2; \n"\
82" \n"\
83"#ifdef NEED_TEX0 \n"\
84"vec4 t0 = texture2D(uTex0,vTexCoord0); \n"\
85"#endif \n"\
86" \n"\
87"#ifdef NEED_TEX1 \n"\
88"vec4 t1 = texture2D(uTex1,vTexCoord1); \n"\
89"#endif \n";
90
91const char *fragmentFooter =
92" \n"\
93"#ifdef FOG \n"\
0c9dca78 94" float z = gl_FragCoord.z * 2.0 - 1.0; \n"\
95" float FogFactor = (FogMinMax[1] - z) / (FogMinMax[1] - FogMinMax[0]); \n"\
96" FogFactor = clamp(FogFactor, 0.0, 1.0); \n"\
97" \n"\
98" gl_FragColor.rgb = mix(FogColor.rgb, comb.rgb, FogFactor ); \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"\
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;
0c9dca78 197 bAlphaTestState = DISABLE;
198 bAlphaTestPreviousState = DISABLE;
199 bFogState = DISABLE;
200 bFogPreviousState = DISABLE;
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;
331 COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;
332 if( pTexture )
333 {
334 m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);
335 m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile);
336 }
337}
338
339void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void)
340{
341 glUseProgram(fillProgram);
342 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);
343 OPENGL_CHECK_ERRORS;
344}
345
346#ifdef BGR_SHADER
347const char *muxToFP_Maps[][2] = {
348//color -- alpha
349{"vec3(0.0)", "0.0"}, //MUX_0 = 0,
350{"vec3(1.0)", "1.0"}, //MUX_1,
351{"comb.rgb", "comb.a"}, //MUX_COMBINED,
352{"t0.rgb", "t0.a"}, //MUX_TEXEL0,
353{"t1.rgb", "t1.a"}, //MUX_TEXEL1,
354{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM,
355{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE,
356{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV,
357{"comb.rgb", "comb.a"}, //MUX_COMBALPHA,
358{"t0.rgb", "t0.a"}, //MUX_T0_ALPHA,
359{"t1.rgb", "t1.a"}, //MUX_T1_ALPHA,
360{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA,
361{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA,
362{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA,
363{"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC,
364{"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC,
365{"vec3(1.0)", "1.0"}, //MUX_K5,
366{"vec3(1.0)", "1.0"}, //MUX_UNK, // Should not be used
367};
368#else
369const char *muxToFP_Maps[][2] = {
370//color -- alpha
371{"vec3(0.0)", "0.0"}, //MUX_0 = 0,
372{"vec3(1.0)", "1.0"}, //MUX_1,
373{"comb.rgb", "comb.a"}, //MUX_COMBINED,
374{"t0.bgr", "t0.a"}, //MUX_TEXEL0,
375{"t1.bgr", "t1.a"}, //MUX_TEXEL1,
376{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM,
377{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE,
378{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV,
379{"comb.rgb", "comb.a"}, //MUX_COMBALPHA,
380{"t0.bgr", "t0.a"}, //MUX_T0_ALPHA,
381{"t1.bgr", "t1.a"}, //MUX_T1_ALPHA,
382{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA,
383{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA,
384{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA,
385{"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC,
386{"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC,
387{"vec3(1.0)", "1.0"}, //MUX_K5,
388{"vec3(1.0)", "1.0"}, //MUX_UNK, // Should not be used
389};
390#endif
391
392
393char oglNewFP[4092];
394
395char* MuxToOC(uint8 val)
396{
397// For color channel
398if( val&MUX_ALPHAREPLICATE )
399 return (char*)muxToFP_Maps[val&0x1F][1];
400else
401 return (char*)muxToFP_Maps[val&0x1F][0];
402}
403
404char* MuxToOA(uint8 val)
405{
406// For alpha channel
407return (char*)muxToFP_Maps[val&0x1F][1];
408}
409
410static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1)
411{
412 MuxVar &= 0x1f;
413 if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA)
414 bNeedT0 = true;
415 if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA)
416 bNeedT1 = true;
417}
418
419void COGL_FragmentProgramCombiner::GenerateProgramStr()
420{
421 DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
422
423 mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;
424 m_pDecodedMux->Reformat(false);
425
426 char tempstr[500], newFPBody[4092];
427 bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false;
428 newFPBody[0] = 0;
429
430 for( int cycle=0; cycle<2; cycle++ )
431 {
432 for( int channel=0; channel<2; channel++)
433 {
434 char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA;
435 char *dst = channel==0?(char*)"rgb":(char*)"a";
436 N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel];
437 switch( mux.splitType[cycle*2+channel] )
438 {
439 case CM_FMT_TYPE_NOT_USED:
440 tempstr[0] = 0;
441 break;
442 case CM_FMT_TYPE_D:
443 sprintf(tempstr, "comb.%s = %s;\n", dst, func(m.d));
444 CheckFpVars(m.d, bNeedT0, bNeedT1);
445 break;
446 case CM_FMT_TYPE_A_MOD_C:
447 sprintf(tempstr, "comb.%s = %s * %s;\n", dst, func(m.a), func(m.c));
448 CheckFpVars(m.a, bNeedT0, bNeedT1);
449 CheckFpVars(m.c, bNeedT0, bNeedT1);
450 break;
451 case CM_FMT_TYPE_A_ADD_D:
452 sprintf(tempstr, "comb.%s = saturate(%s + %s);\n", dst, func(m.a), func(m.d));
453 CheckFpVars(m.a, bNeedT0, bNeedT1);
454 CheckFpVars(m.d, bNeedT0, bNeedT1);
455 break;
456 case CM_FMT_TYPE_A_SUB_B:
457 sprintf(tempstr, "comb.%s = %s - %s;\n", dst, func(m.a), func(m.b));
458 CheckFpVars(m.a, bNeedT0, bNeedT1);
459 CheckFpVars(m.b, bNeedT0, bNeedT1);
460 break;
461 case CM_FMT_TYPE_A_MOD_C_ADD_D:
462 sprintf(tempstr, "comb.%s = saturate(%s * %s + %s);\n", dst, func(m.a), func(m.c),func(m.d));
463 CheckFpVars(m.a, bNeedT0, bNeedT1);
464 CheckFpVars(m.c, bNeedT0, bNeedT1);
465 CheckFpVars(m.d, bNeedT0, bNeedT1);
466 break;
467 case CM_FMT_TYPE_A_LERP_B_C:
468 //ARB ASM LERP and mix have different parameter ordering.
469 //sprintf(tempstr, "comb.%s = saturate(mix(%s, %s, %s));\n", dst,func(m.a),func(m.b), func(m.c));
470 sprintf(tempstr, "comb.%s = (%s - %s) * %s + %s;\n", dst,func(m.a),func(m.b), func(m.c),func(m.b));
471 CheckFpVars(m.a, bNeedT0, bNeedT1);
472 CheckFpVars(m.b, bNeedT0, bNeedT1);
473 CheckFpVars(m.c, bNeedT0, bNeedT1);
474 //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));
475 break;
476 default:
477 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));
478 CheckFpVars(m.a, bNeedT0, bNeedT1);
479 CheckFpVars(m.b, bNeedT0, bNeedT1);
480 CheckFpVars(m.c, bNeedT0, bNeedT1);
481 CheckFpVars(m.d, bNeedT0, bNeedT1);
482 bNeedComb2 = true;
483 break;
484 }
485 strcat(newFPBody, tempstr);
486 }
487 }
488
489 oglNewFP[0] = 0;
490 if (bNeedT0)
491 strcat(oglNewFP, "#define NEED_TEX0\n");
492 if (bNeedT1)
493 strcat(oglNewFP, "#define NEED_TEX1\n");
292f9317 494 strcat(oglNewFP, fragmentHeader);
495 strcat(oglNewFP, newFPBody);
496 strcat(oglNewFP, fragmentFooter);
497
498}
499
500int 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
0c9dca78 522 //Create 4 shaders, with and without alphatest + with and without fog
292f9317 523 GenerateProgramStr();
524
525 for(int alphaTest = 0;alphaTest < 2;alphaTest++)
526 {
0c9dca78 527 for(int fog = 0;fog < 2;fog++) {
528 res.fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
529
530 char* tmpShader = (char*)malloc(sizeof(char) * 4096);
531 strcpy(tmpShader,"#version " GLSL_VERSION "\n");
532
533 if(alphaTest == 1)
534 {
535 strcat(tmpShader,"#define ALPHA_TEST\n");
536 }
537 if(fog == 1)
538 {
539 strcat(tmpShader,"#define FOG\n");
540 }
541
542 res.fogIsUsed = fog == 1;
543 res.alphaTest = alphaTest == 1;
544 strcat(tmpShader,oglNewFP);
545
546 glShaderSource(res.fragmentShaderID, 1,(const char**) &tmpShader,NULL);
547 free(tmpShader);
548
549
550 OPENGL_CHECK_ERRORS;
551 glCompileShader(res.fragmentShaderID);
552
553 glGetShaderiv(res.fragmentShaderID, GL_COMPILE_STATUS, &success);
554 if (!success)
555 {
556 char Log[1024];
557 GLint nLength;
558 glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);
559 printf("Error compiling shader!\n %s",oglNewFP);
560 printf("%s", Log);
561 }
562
563 res.programID = glCreateProgram();
564 glAttachShader(res.programID,res.vertexShaderID);
565 glAttachShader(res.programID,res.fragmentShaderID);
566
567 //Bind Attributes
568 glBindAttribLocation(res.programID,VS_COLOR,"aColor");
569 OPENGL_CHECK_ERRORS;
570 glBindAttribLocation(res.programID,VS_TEXCOORD0,"aTexCoord0");
571 OPENGL_CHECK_ERRORS;
572 glBindAttribLocation(res.programID,VS_TEXCOORD1,"aTexCoord1");
573 OPENGL_CHECK_ERRORS;
574 glBindAttribLocation(res.programID,VS_POSITION,"aPosition");
575 OPENGL_CHECK_ERRORS;
576
577 glLinkProgram(res.programID);
578 OPENGL_CHECK_ERRORS;
579
580 glGetProgramiv(res.programID, GL_LINK_STATUS, &success);
581 if (!success)
582 {
583 char Log[1024];
584 GLint nLength;
585 glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);
586 printf("Error linking program!\n");
587 printf("%s\n",Log);
588 }
589
590 glUseProgram(res.programID);
591 OPENGL_CHECK_ERRORS;
592
593 //Bind texture samplers
594 GLint tex0 = glGetUniformLocation(res.programID,"uTex0");
595 GLint tex1 = glGetUniformLocation(res.programID,"uTex1");
596
597 if(tex0 != -1)
598 glUniform1i(tex0,0);
599 if(tex1 != -1)
600 glUniform1i(tex1,1);
601
602 //Bind Uniforms
603 res.PrimColorLocation = glGetUniformLocation(res.programID,"PrimColor");
604 OPENGL_CHECK_ERRORS;
605 res.EnvColorLocation = glGetUniformLocation(res.programID,"EnvColor");
606 OPENGL_CHECK_ERRORS;
607 res.PrimFracLocation = glGetUniformLocation(res.programID,"PrimFrac");
608 OPENGL_CHECK_ERRORS;
609 res.EnvFracLocation = glGetUniformLocation(res.programID,"EnvFrac");
610 OPENGL_CHECK_ERRORS;
611 res.AlphaRefLocation = glGetUniformLocation(res.programID,"AlphaRef");
612 OPENGL_CHECK_ERRORS;
613 res.FogColorLocation = glGetUniformLocation(res.programID,"FogColor");
614 OPENGL_CHECK_ERRORS;
615 res.FogMinMaxLocation = glGetUniformLocation(res.programID,"FogMinMax");
616 OPENGL_CHECK_ERRORS;
617
618 res.dwMux0 = m_pDecodedMux->m_dwMux0;
619 res.dwMux1 = m_pDecodedMux->m_dwMux1;
620
621 m_vCompiledShaders.push_back(res);
622 }
292f9317 623 }
0c9dca78 624 m_lastIndex = m_vCompiledShaders.size()-4;
292f9317 625
626 return m_lastIndex;
627}
628
629void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)
630{
631 GLuint ID = m_vCompiledShaders[index].programID;
632
633 glUseProgram(ID);
634 glEnableVertexAttribArray(VS_POSITION);
635 OPENGL_CHECK_ERRORS;
636 glVertexAttribPointer(VS_POSITION,4,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][0]));
637 OPENGL_CHECK_ERRORS;
638
639 glEnableVertexAttribArray(VS_TEXCOORD0);
640 OPENGL_CHECK_ERRORS;
641 glVertexAttribPointer(VS_TEXCOORD0,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[0].u));
642 OPENGL_CHECK_ERRORS;
643
644 glEnableVertexAttribArray(VS_TEXCOORD1);
645 OPENGL_CHECK_ERRORS;
646 glVertexAttribPointer(VS_TEXCOORD1,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[1].u));
647 OPENGL_CHECK_ERRORS;
648
649 glEnableVertexAttribArray(VS_COLOR);
650 OPENGL_CHECK_ERRORS;
651 glVertexAttribPointer(VS_COLOR, 4, GL_UNSIGNED_BYTE,GL_TRUE, sizeof(uint8)*4, &(g_oglVtxColors[0][0]) );
652 OPENGL_CHECK_ERRORS;
653}
654
655void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index)
656{
657 OGLShaderCombinerSaveType prog = m_vCompiledShaders[index];
658
659 glUseProgram(prog.programID);
660 float *pf;
661 if(prog.EnvColorLocation != -1)
662 {
663 pf = GetEnvColorfv();
664 glUniform4fv(prog.EnvColorLocation,1, pf);
665 OPENGL_CHECK_ERRORS;
666 }
667
668 if(prog.PrimColorLocation != -1)
669 {
670 pf = GetPrimitiveColorfv();
671 glUniform4fv(prog.PrimColorLocation,1, pf);
672 OPENGL_CHECK_ERRORS;
673 }
674
675 if(prog.EnvFracLocation != -1)
676 {
677 float frac = gRDP.LODFrac / 255.0f;
678 float tempf[4] = {frac,frac,frac,frac};
679 glUniform4fv(prog.EnvFracLocation,1, tempf);
680 OPENGL_CHECK_ERRORS;
681 }
682
683 if(prog.PrimFracLocation != -1)
684 {
685 float frac2 = gRDP.primLODFrac / 255.0f;
686 float tempf2[4] = {frac2,frac2,frac2,frac2};
687 glUniform4fv(prog.PrimFracLocation,1, tempf2);
688 OPENGL_CHECK_ERRORS;
689 }
690
0c9dca78 691 if(prog.FogColorLocation != -1)
292f9317 692 {
0c9dca78 693 glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2], gRDP.fvFogColor[3]);
694 OPENGL_CHECK_ERRORS;
695 }
696
697 if(prog.FogMinMaxLocation != -1)
698 {
292f9317 699 glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);
700 OPENGL_CHECK_ERRORS;
701 }
0c9dca78 702
703 if(prog.AlphaRefLocation != -1)
704 {
705 glUniform1f(prog.AlphaRefLocation,m_AlphaRef);
706 OPENGL_CHECK_ERRORS;
707 }
292f9317 708}
709
710int COGL_FragmentProgramCombiner::FindCompiledMux()
711{
712#ifdef DEBUGGER
713 if( debuggerDropCombiners )
714 {
715 m_vCompiledShaders.clear();
716 //m_dwLastMux0 = m_dwLastMux1 = 0;
717 debuggerDropCombiners = false;
718 }
719#endif
720 for( uint32 i=0; i<m_vCompiledShaders.size(); i++ )
721 {
722 if( m_vCompiledShaders[i].dwMux0 == m_pDecodedMux->m_dwMux0
723 && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1
0c9dca78 724 && m_vCompiledShaders[i].fogIsUsed == bFogState
725 && m_vCompiledShaders[i].alphaTest == bAlphaTestState)
292f9317 726 {
727 return (int)i;
728 }
729 }
730
731 return -1;
732}
733
734//////////////////////////////////////////////////////////////////////////
735void COGL_FragmentProgramCombiner::InitCombinerCycle12(void)
736{
737 if( !m_bFragmentProgramIsSupported )
738 {
739 COGLColorCombiner4::InitCombinerCycle12();
740 return;
741 }
742
743#ifdef DEBUGGER
744 if( debuggerDropCombiners )
745 {
746 UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1);
747 m_vCompiledShaders.clear();
748 m_dwLastMux0 = m_dwLastMux1 = 0;
749 debuggerDropCombiners = false;
750 }
751#endif
752
753 m_pOGLRender->EnableMultiTexture();
754
755 bool combinerIsChanged = false;
756
0c9dca78 757 if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1
758 || bAlphaTestState != bAlphaTestPreviousState || bFogState != bFogPreviousState || m_lastIndex < 0 )
292f9317 759 {
760 combinerIsChanged = true;
761 m_lastIndex = FindCompiledMux();
762 if( m_lastIndex < 0 ) // Can not found
763 {
764 m_lastIndex = ParseDecodedMux();
765 }
766
767 m_dwLastMux0 = m_pDecodedMux->m_dwMux0;
768 m_dwLastMux1 = m_pDecodedMux->m_dwMux1;
0c9dca78 769 bAlphaTestPreviousState = bAlphaTestState;
770 bFogPreviousState = bFogState;
771 m_AlphaRef = (float)(m_pOGLRender->m_dwAlpha)/255.0f;
772 }
292f9317 773
774
775 GenerateCombinerSettingConstants(m_lastIndex);
776 if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )
777 {
778 if( m_bCycleChanged || combinerIsChanged )
779 {
780 GenerateCombinerSettingConstants(m_lastIndex);
781 GenerateCombinerSetting(m_lastIndex);
782 }
783 else if( gRDP.colorsAreReloaded )
784 {
785 GenerateCombinerSettingConstants(m_lastIndex);
786 }
787
788 m_pOGLRender->SetAllTexelRepeatFlag();
789
790 gRDP.colorsAreReloaded = false;
791 gRDP.texturesAreReloaded = false;
792 }
793 else
794 {
795 m_pOGLRender->SetAllTexelRepeatFlag();
796 }
797}
798
799#ifdef DEBUGGER
800void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void)
801{
802 COGLColorCombiner::DisplaySimpleMuxString();
803 DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;
804 mux.Reformat(false);
805 GenerateProgramStr();
806 //sprintf(oglNewFP, oglFP,
807 // MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0),
808 // MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0),
809 // MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1),
810 // MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1)
811 // );
812
813 TRACE0("OGL Fragment Program:");
814 TRACE0(oglNewFP);
815}
816#endif
817