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