/* * 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 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= 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; iformat == 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 }