CORE: Inhibit assertions
[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
27
28
29GLuint vertexProgram = 9999;
30const 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
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"\
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
93const 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"\
103ALPHA_TEST
104"#endif \n"\
105" \n"\
106" \n"\
107" \n"\
108" \n"\
109"} \n";
110
111//Fragment shader for InitCycleCopy
112const 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"\
121ALPHA_TEST
122"}";
123
124GLuint copyProgram,copyAlphaLocation;
125
126//Fragment shader for InitCycleFill
127const 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
136GLuint fillProgram,fillColorLocation;
137
138COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender)
139: COGLColorCombiner(pRender)
140{
141 m_bShaderIsSupported = true;
142}
143COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner()
144{
145}
146
147bool 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
161void COGLFragmentShaderCombiner::InitCombinerCycle12(void)
162{
163}
164void COGLFragmentShaderCombiner::DisableCombiner(void)
165{
166 COGLColorCombiner::DisableCombiner();
167}
168
169void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void)
170{
171 COGLColorCombiner::InitCombinerCycleCopy();
172}
173
174void COGLFragmentShaderCombiner::InitCombinerCycleFill(void)
175{
176 COGLColorCombiner::InitCombinerCycleFill();
177}
178void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
179{
180 COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);
181}
182
183#ifdef DEBUGGER
184void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void)
185{
186 COGLColorCombiner::DisplaySimpleMuxString();
187}
188#endif
189
190
191
192COGL_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}
276COGL_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
291bool 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
307void COGL_FragmentProgramCombiner::DisableCombiner(void)
308{
309 //glDisable(GL_FRAGMENT_PROGRAM);
310 //OPENGL_CHECK_ERRORS;
311 COGLColorCombiner4::DisableCombiner();
312}
313
314void 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
337void 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
345const 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
367const 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
391char oglNewFP[4092];
392
393char* MuxToOC(uint8 val)
394{
395// For color channel
396if( val&MUX_ALPHAREPLICATE )
397 return (char*)muxToFP_Maps[val&0x1F][1];
398else
399 return (char*)muxToFP_Maps[val&0x1F][0];
400}
401
402char* MuxToOA(uint8 val)
403{
404// For alpha channel
405return (char*)muxToFP_Maps[val&0x1F][1];
406}
407
408static 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
417void 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
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
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
623void 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
649void 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
698void 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
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
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//////////////////////////////////////////////////////////////////////////
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
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
805void 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