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