mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2025-04-02 10:52:35 -04:00
730 lines
23 KiB
C++
730 lines
23 KiB
C++
/*
|
|
* z64
|
|
*
|
|
* This program is free software; you can redistribute it and/
|
|
* or modify it under the terms of the GNU General Public Li-
|
|
* cence as published by the Free Software Foundation; either
|
|
* version 2 of the Licence, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be use-
|
|
* ful, but WITHOUT ANY WARRANTY; without even the implied war-
|
|
* ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public Licence for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* Licence along with this program; if not, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
|
|
* USA.
|
|
*
|
|
**/
|
|
|
|
#include "Gfx #1.3.h"
|
|
#include "rdp.h"
|
|
#include "rgl.h"
|
|
|
|
#include <SDL/SDL.h>
|
|
|
|
void rglRenderMode(rglRenderChunk_t & chunk)
|
|
{
|
|
int i;
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
if (RDP_GETOM_CYCLE_TYPE(chunk.rdpState.otherModes) < 2) {
|
|
glDepthMask(RDP_GETOM_Z_UPDATE_EN(chunk.rdpState.otherModes)? GL_TRUE:GL_FALSE);
|
|
if (RDP_GETOM_Z_COMPARE_EN(chunk.rdpState.otherModes))
|
|
glDepthFunc(GL_LESS);
|
|
else
|
|
glDepthFunc(GL_ALWAYS);
|
|
} else {
|
|
glDepthMask(GL_FALSE);
|
|
glDepthFunc(GL_ALWAYS);
|
|
}
|
|
|
|
|
|
// if (RDP_GETOM_Z_MODE(chunk.rdpState.otherModes) & 1) {
|
|
// glEnable( GL_POLYGON_OFFSET_FILL );
|
|
// switch(RDP_GETOM_Z_MODE(chunk.rdpState.otherModes)) {
|
|
// case 3:
|
|
// glPolygonOffset( -3, -300 );
|
|
// break;
|
|
// default:
|
|
// // FIXME tune this value
|
|
// //glPolygonOffset( -3.0f, -3.0f );
|
|
// glPolygonOffset( -3, -40 );
|
|
// break;
|
|
// }
|
|
// //glDepthMask(GL_FALSE);
|
|
// } else {
|
|
// glDisable( GL_POLYGON_OFFSET_FILL );
|
|
// }
|
|
}
|
|
|
|
|
|
|
|
struct rglCombiner_t {
|
|
rdpCombineModes_t combineModes;
|
|
rdpOtherModes_t otherModes;
|
|
rglShader_t * shader;
|
|
#ifndef RGL_EXACT_BLEND
|
|
GLuint srcBlend, dstBlend;
|
|
#endif
|
|
int format;
|
|
};
|
|
#define RGL_MAX_COMBINERS 128
|
|
static int rglNbCombiners;
|
|
static rglCombiner_t rglCombiners[RGL_MAX_COMBINERS];
|
|
|
|
void rglClearCombiners()
|
|
{
|
|
int i;
|
|
for (i=0; i<rglNbCombiners; i++)
|
|
rglDeleteShader(rglCombiners[i].shader);
|
|
rglNbCombiners = 0;
|
|
}
|
|
|
|
|
|
int rglT1Usage(rdpState_t & state)
|
|
{
|
|
//return 1;
|
|
int cycle = RDP_GETOM_CYCLE_TYPE(state.otherModes);
|
|
if (cycle == RDP_CYCLE_TYPE_COPY) return 1;
|
|
if (cycle >= 2) return 0;
|
|
if (cycle == 1 && (
|
|
RDP_GETCM_SUB_A_RGB1(state.combineModes)==2 ||
|
|
RDP_GETCM_SUB_B_RGB1(state.combineModes)==2 ||
|
|
RDP_GETCM_MUL_RGB1(state.combineModes)==2 ||
|
|
RDP_GETCM_MUL_RGB1(state.combineModes)==9 ||
|
|
RDP_GETCM_ADD_RGB1(state.combineModes)==2 ||
|
|
RDP_GETCM_SUB_A_A1(state.combineModes)==2 ||
|
|
RDP_GETCM_SUB_B_A1(state.combineModes)==2 ||
|
|
RDP_GETCM_MUL_A1(state.combineModes)==2 ||
|
|
RDP_GETCM_ADD_A1(state.combineModes)==2))
|
|
return 1;
|
|
if (
|
|
(RDP_GETOM_CVG_TIMES_ALPHA(state.otherModes) &&
|
|
!RDP_GETOM_ALPHA_CVG_SELECT(state.otherModes)) ||
|
|
|
|
RDP_GETCM_SUB_A_RGB0(state.combineModes)==1 ||
|
|
RDP_GETCM_SUB_B_RGB0(state.combineModes)==1 ||
|
|
RDP_GETCM_MUL_RGB0(state.combineModes)==1 ||
|
|
RDP_GETCM_MUL_RGB0(state.combineModes)==8 ||
|
|
RDP_GETCM_ADD_RGB0(state.combineModes)==1 ||
|
|
RDP_GETCM_SUB_A_A0(state.combineModes)==1 ||
|
|
RDP_GETCM_SUB_B_A0(state.combineModes)==1 ||
|
|
RDP_GETCM_MUL_A0(state.combineModes)==1 ||
|
|
RDP_GETCM_ADD_A0(state.combineModes)==1)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
int rglT2Usage(rdpState_t & state)
|
|
{
|
|
//return 1;
|
|
int cycle = RDP_GETOM_CYCLE_TYPE(state.otherModes);
|
|
if (cycle >= 2) return 0;
|
|
if (cycle == 1 && (
|
|
RDP_GETCM_SUB_A_RGB1(state.combineModes)==1 ||
|
|
RDP_GETCM_SUB_B_RGB1(state.combineModes)==1 ||
|
|
RDP_GETCM_MUL_RGB1(state.combineModes)==1 ||
|
|
RDP_GETCM_MUL_RGB1(state.combineModes)==8 ||
|
|
RDP_GETCM_ADD_RGB1(state.combineModes)==1 ||
|
|
RDP_GETCM_SUB_A_A1(state.combineModes)==1 ||
|
|
RDP_GETCM_SUB_B_A1(state.combineModes)==1 ||
|
|
RDP_GETCM_MUL_A1(state.combineModes)==1 ||
|
|
RDP_GETCM_ADD_A1(state.combineModes)==1))
|
|
return 1;
|
|
|
|
if (
|
|
RDP_GETCM_SUB_A_RGB0(state.combineModes)==2 ||
|
|
RDP_GETCM_SUB_B_RGB0(state.combineModes)==2 ||
|
|
RDP_GETCM_MUL_RGB0(state.combineModes)==2 ||
|
|
RDP_GETCM_MUL_RGB0(state.combineModes)==9 ||
|
|
RDP_GETCM_ADD_RGB0(state.combineModes)==2 ||
|
|
RDP_GETCM_SUB_A_A0(state.combineModes)==2 ||
|
|
RDP_GETCM_SUB_B_A0(state.combineModes)==2 ||
|
|
RDP_GETCM_MUL_A0(state.combineModes)==2 ||
|
|
RDP_GETCM_ADD_A0(state.combineModes)==2)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void rglSetCombiner(rglRenderChunk_t & chunk, int format)
|
|
{
|
|
static char _1ma[64];
|
|
static char t1[64];
|
|
static char t1a[64];
|
|
static char t2[64];
|
|
static char t2a[64];
|
|
static char prim_lod_frac[64];
|
|
|
|
static const char *saRGB[] = {
|
|
"c", t1, t2, "p/*PRIM*/",
|
|
"gl_Color", "e", "1.0/*NOISE*/", "1.0",
|
|
"0.0", "0.0", "0.0", "0.0",
|
|
"0.0", "0.0", "0.0", "0.0"
|
|
};
|
|
|
|
static const char *sbRGB[] = {
|
|
"c", t1, t2, "p/*PRIM*/",
|
|
"gl_Color", "e", "0.5/*CENTER*/", "t1/*K4*/",
|
|
"0.0", "0.0", "0.0", "0.0",
|
|
"0.0", "0.0", "0.0", "0.0"
|
|
};
|
|
|
|
static const char *mRGB[] = {
|
|
"c", t1, t2, "p/*PRIM*/",
|
|
"gl_Color/*SHADE*/", "e", "0.0/*SCALE*/", "c.a/*COMBINED_A*/",
|
|
"t1.a/*TEXEL0_A*/", "t2.a/*TEXEL1_A*/", "p.a/*PRIM_A*/", "gl_Color.a/*SHADEA*/",
|
|
"e.a/*ENV_ALPHA*/", "0.5/*LOD_FRACTION*/","0.5/*PRIM_LOD_FRAC*/", "k5/*K5*/",
|
|
"0.0", "0.0", "0.0", "0.0",
|
|
"0.0", "0.0", "0.0", "0.0",
|
|
"0.0", "0.0", "0.0", "0.0",
|
|
"0.0", "0.0", "0.0", "0.0"
|
|
};
|
|
|
|
static const char *aRGB[] = {
|
|
"c", t1, t2, "p/*PRIM*/",
|
|
"gl_Color/*SHADE*/", "e/*ENV*/", "1.0", "0.0",
|
|
};
|
|
|
|
static const char *saA[] = {
|
|
"c.a", t1a, t2a, "p.a/*PRIM*/",
|
|
"gl_Color.a", "e.a", "1.0", "0.0",
|
|
};
|
|
|
|
static const char *sbA[] = {
|
|
"c.a", t1a, t2a, "p.a/*PRIM*/",
|
|
"gl_Color.a", "e.a", "1.0", "0.0",
|
|
};
|
|
|
|
static const char *mA[] = {
|
|
"0.5/*LOD_FRACTION*/", t1a, t2a, "p.a/*PRIM*/",
|
|
"gl_Color.a/*SHADE*/", "e.a", prim_lod_frac, "0.0",
|
|
};
|
|
|
|
static const char *aA[] = {
|
|
"c.a", t1a, t2a, "p.a/*PRIM*/",
|
|
"gl_Color.a/*SHADE*/", "e.a", "1.0", "0.0",
|
|
};
|
|
|
|
const static char * bRGB[] =
|
|
{ "c/*PREV*/", "f", "b", "fog/*FOG*/" };
|
|
const static char * bA[2][4] =
|
|
{ {"c.a/*PREVA*/", "fog.a/*FOGA*/", "gl_Color.a/*SHADEA*/", "0.0/*ZERO*/"},
|
|
{_1ma/*"(1.0-c.a/*PREVA)"*/, "0.0/*f.a*//*FRAGA*/", "1.0", "0.0"}}; // need clamping on 1-alpha ?
|
|
|
|
|
|
rdpState_t & state = chunk.rdpState;
|
|
static rglCombiner_t * c;
|
|
int cycle = RDP_GETOM_CYCLE_TYPE(state.otherModes);
|
|
int i, fmt, size;
|
|
char * p;
|
|
char * alphaTest;
|
|
char * alphaTest2;
|
|
char * write;
|
|
static char src[4*4096];
|
|
|
|
float env[4];
|
|
env[0] = RDP_GETC32_R(state.envColor)/255.0f;
|
|
env[1] = RDP_GETC32_G(state.envColor)/255.0f;
|
|
env[2] = RDP_GETC32_B(state.envColor)/255.0f;
|
|
env[3] = RDP_GETC32_A(state.envColor)/255.0f;
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env);
|
|
|
|
env[0] = RDP_GETC32_R(state.blendColor)/255.0f;
|
|
env[1] = RDP_GETC32_G(state.blendColor)/255.0f;
|
|
env[2] = RDP_GETC32_B(state.blendColor)/255.0f;
|
|
env[3] = RDP_GETC32_A(state.blendColor)/255.0f;
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, env);
|
|
|
|
env[0] = RDP_GETC32_R(state.fogColor)/255.0f;
|
|
env[1] = RDP_GETC32_G(state.fogColor)/255.0f;
|
|
env[2] = RDP_GETC32_B(state.fogColor)/255.0f;
|
|
env[3] = RDP_GETC32_A(state.fogColor)/255.0f;
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, env);
|
|
|
|
glActiveTextureARB(GL_TEXTURE1_ARB);
|
|
env[0] = state.k5/255.0f;
|
|
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env);
|
|
if (cycle == RDP_CYCLE_TYPE_FILL) {
|
|
if (0/*fb_size == 3*/) { // FIXME
|
|
env[0] = RDP_GETC32_R(state.fillColor)/255.0f;
|
|
env[1] = RDP_GETC32_G(state.fillColor)/255.0f;
|
|
env[2] = RDP_GETC32_B(state.fillColor)/255.0f;
|
|
env[3] = RDP_GETC32_A(state.fillColor)/255.0f;
|
|
} else {
|
|
env[0] = RDP_GETC16_R(state.fillColor)/31.0f;
|
|
env[1] = RDP_GETC16_G(state.fillColor)/31.0f;
|
|
env[2] = RDP_GETC16_B(state.fillColor)/31.0f;
|
|
env[3] = RDP_GETC16_A(state.fillColor);
|
|
}
|
|
} else {
|
|
env[0] = RDP_GETC32_R(state.primColor)/255.0f;
|
|
env[1] = RDP_GETC32_G(state.primColor)/255.0f;
|
|
env[2] = RDP_GETC32_B(state.primColor)/255.0f;
|
|
env[3] = RDP_GETC32_A(state.primColor)/255.0f;
|
|
}
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, env);
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
|
rglAssert(glGetError() == GL_NO_ERROR);
|
|
|
|
// if (c && rglNbCombiners &&
|
|
// RDP_GETOM_CYCLE_TYPE(c->otherModes) == cycle &&
|
|
// (RDP_GETOM_CYCLE_TYPE(c->otherModes) >= 2 ||
|
|
// (!memcmp(&c->combineModes, &state.combineModes, sizeof(rdpCombineModes_t)) &&
|
|
// !memcmp(&c->otherModes, &state.otherModes, sizeof(rdpOtherModes_t))))) {
|
|
// return;
|
|
// }
|
|
|
|
for (i=0; i<rglNbCombiners; i++) {
|
|
c = rglCombiners + i;
|
|
if (c->format == format &&
|
|
RDP_GETOM_CYCLE_TYPE(c->otherModes) == cycle &&
|
|
(RDP_GETOM_CYCLE_TYPE(c->otherModes) >= 2 ||
|
|
(!memcmp(&c->combineModes, &state.combineModes, sizeof(rdpCombineModes_t))
|
|
&& !memcmp(&c->otherModes, &state.otherModes, sizeof(rdpOtherModes_t))
|
|
))) {
|
|
#ifdef RDP_DEBUG
|
|
chunk.shader = c->shader;
|
|
#endif
|
|
rglUseShader(c->shader);
|
|
goto ok;
|
|
}
|
|
}
|
|
|
|
if (rglNbCombiners == RGL_MAX_COMBINERS)
|
|
rglClearCombiners();
|
|
|
|
c = rglCombiners + rglNbCombiners++;
|
|
c->otherModes = state.otherModes;
|
|
c->combineModes = state.combineModes;
|
|
c->format = format;
|
|
#ifndef RGL_EXACT_BLEND
|
|
c->srcBlend = GL_ONE;
|
|
c->dstBlend = GL_ZERO;
|
|
#endif
|
|
|
|
switch (format & RGL_COMB_FMT) {
|
|
case RGL_COMB_FMT_RGBA:
|
|
write = "gl_FragColor = c;";
|
|
break;
|
|
case RGL_COMB_FMT_I:
|
|
write = "gl_FragColor = vec4(c[0]);";
|
|
break;
|
|
case RGL_COMB_FMT_DEPTH:
|
|
write = "gl_FragDepth = c[0];";
|
|
break;
|
|
}
|
|
|
|
if (cycle == RDP_CYCLE_TYPE_FILL) {
|
|
sprintf(
|
|
src,
|
|
"void main() \n"
|
|
"{ \n"
|
|
//" c = gl_TextureEnvColor[1];\n"
|
|
" vec4 c = gl_LightSource[0].specular;\n"
|
|
" %s\n"
|
|
"} \n",
|
|
write);
|
|
c->shader = rglCreateShader(
|
|
"void main() \n"
|
|
"{ \n"
|
|
" gl_Position = ftransform(); \n"
|
|
" gl_FrontColor = gl_Color; \n"
|
|
" gl_BackColor = gl_Color; \n"
|
|
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
|
"} \n"
|
|
,
|
|
src
|
|
);
|
|
#ifdef RDP_DEBUG
|
|
chunk.shader = c->shader;
|
|
#endif
|
|
rglUseShader(c->shader);
|
|
goto ok;
|
|
}
|
|
|
|
alphaTest = "";
|
|
alphaTest2 = "";
|
|
|
|
if (//cycle < 2 && // CHECK THIS
|
|
RDP_GETOM_CVG_TIMES_ALPHA(chunk.rdpState.otherModes)
|
|
//&& rglT1Usage(chunk.rdpState)
|
|
) {
|
|
if (RDP_GETOM_ALPHA_CVG_SELECT(chunk.rdpState.otherModes))
|
|
alphaTest = "if (c.a < 0.5) discard; \n";
|
|
else
|
|
alphaTest = "if (t1.a < 0.5) discard; \n";
|
|
alphaTest2 = "if (c.a < 0.5) discard; \n";
|
|
}
|
|
else if (RDP_GETOM_ALPHA_COMPARE_EN(chunk.rdpState.otherModes) &&
|
|
!RDP_GETOM_ALPHA_CVG_SELECT(chunk.rdpState.otherModes)) {
|
|
if (RDP_GETC32_A(chunk.rdpState.blendColor) > 0) {
|
|
alphaTest = "if (c.a < b.a) discard; \n";
|
|
alphaTest2 =
|
|
" vec4 b = gl_LightSource[0].ambient; \n"
|
|
" if (c.a < b.a) discard; \n";
|
|
//alphaTest2 = "if (c.a < 0.5) discard; \n";
|
|
} else {
|
|
alphaTest = "if (c.a == 0.0) discard; \n";
|
|
alphaTest2 = "if (c.a == 0.0) discard; \n";
|
|
}
|
|
}
|
|
|
|
if (cycle == RDP_CYCLE_TYPE_COPY) {
|
|
sprintf(
|
|
src,
|
|
"uniform sampler2D texture0; \n"
|
|
" \n"
|
|
"void main() \n"
|
|
"{ \n"
|
|
" vec4 c = texture2D(texture0, vec2(gl_TexCoord[0])); \n"
|
|
" %s"
|
|
" %s\n"
|
|
"} \n",
|
|
alphaTest2,
|
|
write
|
|
);
|
|
c->shader = rglCreateShader(
|
|
"void main() \n"
|
|
"{ \n"
|
|
" gl_Position = ftransform(); \n"
|
|
" gl_FrontColor = gl_Color; \n"
|
|
" gl_BackColor = gl_Color; \n"
|
|
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
|
"} \n"
|
|
,
|
|
src
|
|
);
|
|
#ifdef RDP_DEBUG
|
|
chunk.shader = c->shader;
|
|
#endif
|
|
rglUseShader(c->shader);
|
|
goto ok;
|
|
}
|
|
|
|
|
|
p = src;
|
|
p +=
|
|
sprintf(p,
|
|
"uniform sampler2D texture0; \n"
|
|
"uniform sampler2D texture2; \n"
|
|
#ifdef RGL_EXACT_BLEND
|
|
"uniform sampler2D texture1; \n"
|
|
#endif
|
|
" \n"
|
|
"void main() \n"
|
|
"{ \n"
|
|
"vec4 c = vec4(0,0,0,0);\n"
|
|
"vec4 e = gl_TextureEnvColor[0];\n"
|
|
"float k5 = gl_TextureEnvColor[1][0];\n"
|
|
"vec4 p = gl_LightSource[0].specular;\n"
|
|
#ifdef RGL_EXACT_BLEND
|
|
"vec4 f = texture2D(texture1, vec2(gl_FragCoord.x/(2048.0*gl_TexCoord[1].x), gl_FragCoord.y/(2048.0*gl_TexCoord[1].y))); \n"
|
|
#endif
|
|
"vec4 fog = gl_LightSource[0].diffuse; \n"
|
|
"vec4 b = gl_LightSource[0].ambient; \n");
|
|
|
|
switch (format & RGL_COMB_IN0) {
|
|
case 0:
|
|
p +=
|
|
sprintf(p,
|
|
"vec4 t1 = texture2D(texture0, vec2(gl_TexCoord[0]));\n");
|
|
break;
|
|
case RGL_COMB_IN0_DEPTH:
|
|
p +=
|
|
sprintf(p,
|
|
"vec4 t1 = vec4(texture2D(texture0, vec2(gl_TexCoord[0]))[0]);\n");
|
|
break;
|
|
}
|
|
switch (format & RGL_COMB_IN1) {
|
|
case 0:
|
|
p +=
|
|
sprintf(p,
|
|
"vec4 t2 = texture2D(texture2, vec2(gl_TexCoord[2]));\n");
|
|
break;
|
|
case RGL_COMB_IN1_DEPTH:
|
|
p +=
|
|
sprintf(p,
|
|
"vec4 t2 = vec4(texture2D(texture2, vec2(gl_TexCoord[2]))[0]);\n");
|
|
break;
|
|
}
|
|
|
|
char * comb, * comb2;
|
|
comb2 = 0;
|
|
// switch (RDP_GETOM_CVG_DEST(state.otherModes))
|
|
// {
|
|
// case 3:
|
|
// comb = "c = clamp(vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s), 0.0, 1.0);\n";
|
|
// break;
|
|
// case 2:
|
|
// comb = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s);\n";
|
|
// //comb = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), t1.a*((%s - %s) * %s + %s));\n";
|
|
// break;
|
|
// case 0:
|
|
// //comb2 = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), t1.a);\n";
|
|
// case 1:
|
|
// comb = "c = vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s);\n";
|
|
// break;
|
|
// }
|
|
comb = "c = clamp(vec4((vec3(%s) - vec3(%s)) * vec3(%s) + vec3(%s), (%s - %s) * %s + %s), 0.0, 1.0);\n";
|
|
strcpy(prim_lod_frac, "0.5/*PRIM_LOD_FRAC*/");
|
|
strcpy(t1, "t1");
|
|
strcpy(t1a, "t1.a");
|
|
if (format & RGL_COMB_TILE7) {
|
|
strcpy(t2, "t1");
|
|
strcpy(t2a, "t1.a");
|
|
} else {
|
|
strcpy(t2, "t2");
|
|
strcpy(t2a, "t2.a");
|
|
}
|
|
p +=
|
|
sprintf(p,
|
|
comb
|
|
,
|
|
saRGB[RDP_GETCM_SUB_A_RGB0(state.combineModes)],
|
|
saRGB[RDP_GETCM_SUB_B_RGB0(state.combineModes)],
|
|
mRGB[RDP_GETCM_MUL_RGB0(state.combineModes)],
|
|
aRGB[RDP_GETCM_ADD_RGB0(state.combineModes)],
|
|
saA[RDP_GETCM_SUB_A_A0(state.combineModes)],
|
|
sbA[RDP_GETCM_SUB_B_A0(state.combineModes)],
|
|
mA[RDP_GETCM_MUL_A0(state.combineModes)],
|
|
aA[RDP_GETCM_ADD_A0(state.combineModes)]
|
|
);
|
|
|
|
if (cycle == RDP_CYCLE_TYPE_2) {
|
|
if (!(format & RGL_COMB_TILE7)) {
|
|
strcpy(t1, "t2");
|
|
strcpy(t1a, "t2.a");
|
|
strcpy(t2, "t1");
|
|
strcpy(t2a, "t1.a");
|
|
}
|
|
//strcpy(prim_lod_frac, "0.0/*PRIM_LOD_FRAC*/");
|
|
// if (!RDP_GETOM_ALPHA_CVG_SELECT(chunk.rdpState.otherModes))
|
|
// p +=
|
|
// sprintf(p, " c.a = t1.a; \n");
|
|
|
|
p +=
|
|
sprintf(p,
|
|
comb2? comb2 : comb
|
|
,
|
|
saRGB[RDP_GETCM_SUB_A_RGB1(state.combineModes)],
|
|
saRGB[RDP_GETCM_SUB_B_RGB1(state.combineModes)],
|
|
mRGB[RDP_GETCM_MUL_RGB1(state.combineModes)],
|
|
aRGB[RDP_GETCM_ADD_RGB1(state.combineModes)],
|
|
saA[RDP_GETCM_SUB_A_A1(state.combineModes)],
|
|
sbA[RDP_GETCM_SUB_B_A1(state.combineModes)],
|
|
mA[RDP_GETCM_MUL_A1(state.combineModes)],
|
|
aA[RDP_GETCM_ADD_A1(state.combineModes)]
|
|
);
|
|
}
|
|
|
|
// if (!RDP_GETOM_CVG_TIMES_ALPHA(state.otherModes))
|
|
// p += sprintf(p, "c.a = t1.a; \n");
|
|
|
|
p += sprintf(p, alphaTest);
|
|
|
|
|
|
char * blender;
|
|
char * noblender;
|
|
blender = "c = vec4(float(%s)*vec3(%s) + float(%s)*vec3(%s), 1.0); \n";
|
|
noblender = "c.a = 1.0;\n";
|
|
|
|
int m1b, m1a, m2b, m2a;
|
|
|
|
//LOG("New combiner / blender :\n%s", rglCombiner2String(state));
|
|
|
|
if (cycle == RDP_CYCLE_TYPE_2) {
|
|
if (RDP_GETOM_FORCE_BLEND(state.otherModes)) {
|
|
#ifndef RGL_EXACT_BLEND
|
|
if (RDP_GETOM_BLEND_M1A_0(state.otherModes) != 1 &&
|
|
RDP_GETOM_BLEND_M2A_0(state.otherModes) != 1) {
|
|
#endif
|
|
sprintf(_1ma, "(1.0 - %s)", bA[0][RDP_GETOM_BLEND_M1B_0(state.otherModes)]);
|
|
p +=
|
|
sprintf(
|
|
p,
|
|
"c = vec4(float(%s)*vec3(%s) + float(%s)*vec3(%s), c.a); \n"
|
|
,bA[0][RDP_GETOM_BLEND_M1B_0(state.otherModes)],
|
|
bRGB[RDP_GETOM_BLEND_M1A_0(state.otherModes)],
|
|
bA[1][RDP_GETOM_BLEND_M2B_0(state.otherModes)],
|
|
bRGB[RDP_GETOM_BLEND_M2A_0(state.otherModes)]
|
|
);
|
|
#ifndef RGL_EXACT_BLEND
|
|
} else {
|
|
LOG("Blender error : fragment in cycle 1\n%s", rglCombiner2String(state));
|
|
}
|
|
#endif
|
|
|
|
m1b = RDP_GETOM_BLEND_M1B_1(state.otherModes);
|
|
m1a = RDP_GETOM_BLEND_M1A_1(state.otherModes);
|
|
m2b = RDP_GETOM_BLEND_M2B_1(state.otherModes);
|
|
m2a = RDP_GETOM_BLEND_M2A_1(state.otherModes);
|
|
} else {
|
|
m1b = RDP_GETOM_BLEND_M1B_0(state.otherModes);
|
|
m1a = RDP_GETOM_BLEND_M1A_0(state.otherModes);
|
|
m2b = RDP_GETOM_BLEND_M2B_0(state.otherModes);
|
|
m2a = RDP_GETOM_BLEND_M2A_0(state.otherModes);
|
|
}
|
|
} else {
|
|
m1b = RDP_GETOM_BLEND_M1B_0(state.otherModes);
|
|
m1a = RDP_GETOM_BLEND_M1A_0(state.otherModes);
|
|
m2b = RDP_GETOM_BLEND_M2B_0(state.otherModes);
|
|
m2a = RDP_GETOM_BLEND_M2A_0(state.otherModes);
|
|
}
|
|
|
|
if (RDP_GETOM_FORCE_BLEND(state.otherModes) || cycle == RDP_CYCLE_TYPE_2) {
|
|
#ifndef RGL_EXACT_BLEND
|
|
if (m1a == 1 || m2a == 1) {
|
|
if (/*(m1a != 1 || m1b == 3) &&*/ (m2a == 1 || m2b == 3)) {
|
|
int src = GL_ZERO, dst = GL_ONE;
|
|
char * alpha = "c.a";
|
|
switch (m1b) {
|
|
case 0: // c.a
|
|
src = GL_SRC_ALPHA;
|
|
break;
|
|
case 1: // fog.a
|
|
src = GL_SRC_ALPHA;
|
|
alpha = "fog.a";
|
|
// LOGERROR("Unsupported src alpha : FOG\n");
|
|
// LOGERROR(rglCombiner2String(state));
|
|
break;
|
|
case 2: // shade.a
|
|
src = GL_SRC_ALPHA;
|
|
alpha = "gl_Color.a";
|
|
// LOGERROR("Unsupported src alpha : SHADE\n");
|
|
// LOGERROR(rglCombiner2String(state));
|
|
break;
|
|
case 3: // 0
|
|
src = GL_ZERO;
|
|
break;
|
|
}
|
|
switch (m1a) {
|
|
case 0: // c
|
|
if (m1b != 0 /* c.a */)
|
|
p += sprintf(
|
|
p, "c.a = %s; \n", alpha);
|
|
break;
|
|
case 1: // f
|
|
LOGERROR("Unsupported src color : FRAG\n");
|
|
LOGERROR(rglCombiner2String(state));
|
|
break;
|
|
case 2: // b
|
|
p += sprintf(
|
|
p, "c = vec4(vec3(b), %s); \n", alpha);
|
|
break;
|
|
case 3: // fog
|
|
p += sprintf(
|
|
p, "c = vec4(vec3(fog), %s); \n", alpha);
|
|
break;
|
|
}
|
|
switch (m2b) {
|
|
case 0:
|
|
switch (m1b) {
|
|
case 3:
|
|
dst = GL_ONE;
|
|
break;
|
|
default:
|
|
dst = GL_ONE_MINUS_SRC_ALPHA;
|
|
break;
|
|
}
|
|
break;
|
|
case 1:
|
|
dst = GL_DST_ALPHA;
|
|
break;
|
|
case 2:
|
|
dst = GL_ONE;
|
|
break;
|
|
case 3:
|
|
dst = GL_ZERO;
|
|
break;
|
|
}
|
|
|
|
c->srcBlend = src;
|
|
c->dstBlend = dst;
|
|
} else {
|
|
LOGERROR("Unsuported blender :\n");
|
|
LOGERROR(rglCombiner2String(state));
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
sprintf(_1ma, "(1.0 - %s)", bA[0][m1b]);
|
|
p +=
|
|
sprintf(p, blender, bA[0][m1b], bRGB[m1a], bA[1][m2b], bRGB[m2a]);
|
|
}
|
|
} else {
|
|
#ifdef RGL_EXACT_BLEND
|
|
p +=
|
|
sprintf(p,
|
|
noblender
|
|
);
|
|
#endif
|
|
}
|
|
|
|
p +=
|
|
sprintf(
|
|
p,
|
|
"%s \n"
|
|
"} \n"
|
|
,write
|
|
);
|
|
|
|
rglAssert(p < src+sizeof(src));
|
|
|
|
#ifdef RGL_EXACT_BLEND
|
|
//printf("Creating combiner : \n%s", src);
|
|
#endif
|
|
|
|
c->shader = rglCreateShader(
|
|
"void main() \n"
|
|
"{ \n"
|
|
" gl_Position = ftransform(); \n"
|
|
" gl_FrontColor = gl_Color; \n"
|
|
" gl_BackColor = gl_FrontColor; \n"
|
|
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
|
|
#ifdef RGL_EXACT_BLEND
|
|
" gl_TexCoord[1] = gl_MultiTexCoord1; \n"
|
|
#endif
|
|
" gl_TexCoord[2] = gl_MultiTexCoord2; \n"
|
|
"} \n"
|
|
,
|
|
src);
|
|
|
|
#ifdef RDP_DEBUG
|
|
chunk.shader = c->shader;
|
|
#endif
|
|
rglUseShader(c->shader);
|
|
rglAssert(glGetError() == GL_NO_ERROR);
|
|
|
|
#if 1
|
|
int location;
|
|
location = glGetUniformLocationARB(c->shader->prog, "texture0");
|
|
glUniform1iARB(location, 0);
|
|
#ifdef RGL_EXACT_BLEND
|
|
location = glGetUniformLocationARB(c->shader->prog, "texture1");
|
|
glUniform1iARB(location, 1);
|
|
#endif
|
|
location = glGetUniformLocationARB(c->shader->prog, "texture2");
|
|
glUniform1iARB(location, 2);
|
|
rglAssert(glGetError() == GL_NO_ERROR);
|
|
#endif
|
|
|
|
ok:;
|
|
#ifndef RGL_EXACT_BLEND
|
|
if ((format & RGL_COMB_FMT) == RGL_COMB_FMT_DEPTH ||
|
|
(c->srcBlend == GL_ONE && c->dstBlend == GL_ZERO))
|
|
glDisable(GL_BLEND);
|
|
else {
|
|
glEnable(GL_BLEND);
|
|
if ((format & RGL_COMB_FMT) == RGL_COMB_FMT_RGBA)
|
|
glBlendFuncSeparate(c->srcBlend, c->dstBlend, GL_ZERO, GL_ONE);
|
|
else
|
|
glBlendFunc(c->srcBlend, c->dstBlend);
|
|
}
|
|
#endif
|
|
}
|