/* Copyright (C) 2003 Rice1964 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "OGLDebug.h" #include "OGLES2FragmentShaders.h" #include "OGLRender.h" #include "OGLGraphicsContext.h" #include "OGLTexture.h" #define ALPHA_TEST " if(gl_FragColor.a < AlphaRef) discard; \n" //#define ALPHA_TEST GLuint vertexProgram = 9999; const char *vertexShader = "#version " GLSL_VERSION "\n" "attribute mediump vec4 aPosition; \n"\ "attribute lowp vec4 aColor; \n"\ "attribute lowp vec2 aTexCoord0; \n"\ "attribute lowp vec2 aTexCoord1; \n"\ "attribute lowp vec2 aAtlasTransform; \n"\ " \n"\ "uniform lowp vec2 FogMinMax; \n"\ " \n"\ "varying lowp float vFactor; \n"\ "varying lowp vec4 vShadeColor; \n"\ "varying mediump vec2 vTexCoord0; \n"\ "varying lowp vec2 vTexCoord1; \n"\ "varying lowp float vFog; \n"\ " \n"\ "void main() \n"\ "{ \n"\ "gl_Position = aPosition; //gl_Position.z = max(0.0,gl_Position.z); \n"\ "vShadeColor = aColor; \n"\ "vTexCoord0 = aTexCoord0; \n"\ "vTexCoord1 = aTexCoord1; \n"\ "vFog = clamp((FogMinMax[1] - (gl_Position.z/aPosition.w))/(FogMinMax[1]-FogMinMax[0]),0.0,1.0); \n"\ " \n"\ "} \n"\ " \n"; const char *fragmentHeader = "#define saturate(x) clamp( x, 0.0, 1.0 ) \n"\ "precision lowp float; \n"\ "#ifdef NEED_TEX0 \n"\ "uniform sampler2D uTex0; \n"\ "#endif \n"\ " \n"\ "#ifdef NEED_TEX1 \n"\ "uniform sampler2D uTex1; \n"\ "#endif \n"\ " \n"\ "uniform vec4 EnvColor; \n"\ "uniform vec4 PrimColor; \n"\ "uniform vec4 EnvFrac; \n"\ "uniform vec4 PrimFrac; \n"\ "uniform float AlphaRef; \n"\ "uniform vec4 FogColor; \n"\ " \n"\ "varying lowp float vFactor; \n"\ "varying lowp vec4 vShadeColor; \n"\ "varying mediump vec2 vTexCoord0; \n"\ "varying lowp vec2 vTexCoord1; \n"\ "varying lowp float vFog; \n"\ " \n"\ "void main() \n"\ "{ \n"\ "vec4 comb,comb2; \n"\ " \n"\ "#ifdef NEED_TEX0 \n"\ "vec4 t0 = texture2D(uTex0,vTexCoord0); \n"\ "#endif \n"\ " \n"\ "#ifdef NEED_TEX1 \n"\ "vec4 t1 = texture2D(uTex1,vTexCoord1); \n"\ "#endif \n"; const char *fragmentFooter = " \n"\ "#ifdef FOG \n"\ "gl_FragColor.rgb = mix(FogColor.rgb,comb.rgb,vFog * step(0.5,1.0-FogColor.a)); \n"\ "gl_FragColor.a = comb.a; \n"\ "#else \n"\ "gl_FragColor = comb; \n"\ "#endif \n"\ " \n"\ "#ifdef ALPHA_TEST \n"\ ALPHA_TEST "#endif \n"\ " \n"\ " \n"\ " \n"\ " \n"\ "} \n"; //Fragment shader for InitCycleCopy const char *fragmentCopy = "#version " GLSL_VERSION "\n"\ "precision lowp float; \n"\ "uniform sampler2D uTex0; \n"\ "uniform float AlphaRef; \n"\ "varying lowp vec2 vTexCoord0; \n"\ "void main() \n"\ "{ \n"\ " gl_FragColor = texture2D(uTex0,vTexCoord0).bgra; \n"\ ALPHA_TEST "}"; GLuint copyProgram,copyAlphaLocation; //Fragment shader for InitCycleFill const char *fragmentFill = "#version " GLSL_VERSION "\n"\ "precision lowp float; \n" "uniform vec4 uColor; \n" "void main() \n" "{ \n" " gl_FragColor = uColor; \n" "}"; GLuint fillProgram,fillColorLocation; COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender) : COGLColorCombiner(pRender) { m_bShaderIsSupported = true; } COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner() { } bool COGLFragmentShaderCombiner::Initialize(void) { if( !COGLColorCombiner::Initialize() ) return false; COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext); // if( pcontext->IsExtensionSupported("GL_fragment_shader") ) // { m_bShaderIsSupported = true; // } return true; } void COGLFragmentShaderCombiner::InitCombinerCycle12(void) { } void COGLFragmentShaderCombiner::DisableCombiner(void) { COGLColorCombiner::DisableCombiner(); } void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void) { COGLColorCombiner::InitCombinerCycleCopy(); } void COGLFragmentShaderCombiner::InitCombinerCycleFill(void) { COGLColorCombiner::InitCombinerCycleFill(); } void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile) { COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile); } #ifdef DEBUGGER void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void) { COGLColorCombiner::DisplaySimpleMuxString(); } #endif COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender) : COGLColorCombiner4(pRender) { delete m_pDecodedMux; m_pDecodedMux = new DecodedMuxForPixelShader; m_bFragmentProgramIsSupported = true; m_AlphaRef = 0.0f; //Create shaders for fill and copy GLint success; GLuint vs,fs; copyProgram = glCreateProgram(); vs = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs,1,&vertexShader,NULL); glCompileShader(vs); glGetShaderiv(vs,GL_COMPILE_STATUS,&success); if(!success) { char log[1024]; glGetShaderInfoLog(vs,1024,NULL,log); printf("%s\n",log); } fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs,1,&fragmentCopy,NULL); glCompileShader(fs); glGetShaderiv(fs,GL_COMPILE_STATUS,&success); if(!success) { char log[1024]; glGetShaderInfoLog(fs,1024,NULL,log); printf("%s\n",log); } glAttachShader(copyProgram,vs); glAttachShader(copyProgram,fs); glBindAttribLocation(copyProgram,VS_TEXCOORD0,"aTexCoord0"); OPENGL_CHECK_ERRORS; glBindAttribLocation(copyProgram,VS_POSITION,"aPosition"); OPENGL_CHECK_ERRORS; glLinkProgram(copyProgram); copyAlphaLocation = glGetUniformLocation(copyProgram,"AlphaRef"); glGetProgramiv(copyProgram,GL_LINK_STATUS,&success); if(!success) { char log[1024]; glGetProgramInfoLog(copyProgram,1024,NULL,log); printf("%s\n",log); } glDeleteShader(fs); //Fill shader fs = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs,1,&fragmentFill,NULL); glCompileShader(fs); glGetShaderiv(fs,GL_COMPILE_STATUS,&success); if(!success) { char log[1024]; glGetShaderInfoLog(fs,1024,NULL,log); printf("%s\n",log); } fillProgram = glCreateProgram(); glAttachShader(fillProgram,vs); glAttachShader(fillProgram,fs); glBindAttribLocation(fillProgram,VS_POSITION,"aPosition"); OPENGL_CHECK_ERRORS; glLinkProgram(fillProgram); fillColorLocation = glGetUniformLocation(fillProgram,"uColor"); glDeleteShader(fs); glDeleteShader(vs); } COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner() { int size = m_vCompiledShaders.size(); for (int i=0; iIsExtensionSupported("GL_fragment_program") ) // { m_bFragmentProgramIsSupported = true; // } return true; } void COGL_FragmentProgramCombiner::DisableCombiner(void) { //glDisable(GL_FRAGMENT_PROGRAM); //OPENGL_CHECK_ERRORS; COGLColorCombiner4::DisableCombiner(); } void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void) { m_pOGLRender->DisableMultiTexture(); m_pOGLRender->EnableTexUnit(0,TRUE); glUseProgram(copyProgram); glUniform1f(copyAlphaLocation,m_AlphaRef); OPENGL_CHECK_ERRORS; glEnableVertexAttribArray(VS_POSITION); OPENGL_CHECK_ERRORS; glEnableVertexAttribArray(VS_TEXCOORD0); OPENGL_CHECK_ERRORS; glDisableVertexAttribArray(VS_COLOR); OPENGL_CHECK_ERRORS; glDisableVertexAttribArray(VS_TEXCOORD1); OPENGL_CHECK_ERRORS; COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture; if( pTexture ) { m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0); m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile); } } void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void) { glUseProgram(fillProgram); 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); OPENGL_CHECK_ERRORS; } #ifdef BGR_SHADER const char *muxToFP_Maps[][2] = { //color -- alpha {"vec3(0.0)", "0.0"}, //MUX_0 = 0, {"vec3(1.0)", "1.0"}, //MUX_1, {"comb.rgb", "comb.a"}, //MUX_COMBINED, {"t0.rgb", "t0.a"}, //MUX_TEXEL0, {"t1.rgb", "t1.a"}, //MUX_TEXEL1, {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM, {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE, {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV, {"comb.rgb", "comb.a"}, //MUX_COMBALPHA, {"t0.rgb", "t0.a"}, //MUX_T0_ALPHA, {"t1.rgb", "t1.a"}, //MUX_T1_ALPHA, {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA, {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA, {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA, {"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC, {"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC, {"vec3(1.0)", "1.0"}, //MUX_K5, {"vec3(1.0)", "1.0"}, //MUX_UNK, // Should not be used }; #else const char *muxToFP_Maps[][2] = { //color -- alpha {"vec3(0.0)", "0.0"}, //MUX_0 = 0, {"vec3(1.0)", "1.0"}, //MUX_1, {"comb.rgb", "comb.a"}, //MUX_COMBINED, {"t0.bgr", "t0.a"}, //MUX_TEXEL0, {"t1.bgr", "t1.a"}, //MUX_TEXEL1, {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM, {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE, {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV, {"comb.rgb", "comb.a"}, //MUX_COMBALPHA, {"t0.bgr", "t0.a"}, //MUX_T0_ALPHA, {"t1.bgr", "t1.a"}, //MUX_T1_ALPHA, {"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA, {"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA, {"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA, {"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC, {"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC, {"vec3(1.0)", "1.0"}, //MUX_K5, {"vec3(1.0)", "1.0"}, //MUX_UNK, // Should not be used }; #endif char oglNewFP[4092]; char* MuxToOC(uint8 val) { // For color channel if( val&MUX_ALPHAREPLICATE ) return (char*)muxToFP_Maps[val&0x1F][1]; else return (char*)muxToFP_Maps[val&0x1F][0]; } char* MuxToOA(uint8 val) { // For alpha channel return (char*)muxToFP_Maps[val&0x1F][1]; } static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1) { MuxVar &= 0x1f; if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA) bNeedT0 = true; if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA) bNeedT1 = true; } void COGL_FragmentProgramCombiner::GenerateProgramStr() { DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux; mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED; m_pDecodedMux->Reformat(false); char tempstr[500], newFPBody[4092]; bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false; newFPBody[0] = 0; for( int cycle=0; cycle<2; cycle++ ) { for( int channel=0; channel<2; channel++) { char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA; char *dst = channel==0?(char*)"rgb":(char*)"a"; N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel]; switch( mux.splitType[cycle*2+channel] ) { case CM_FMT_TYPE_NOT_USED: tempstr[0] = 0; break; case CM_FMT_TYPE_D: sprintf(tempstr, "comb.%s = %s;\n", dst, func(m.d)); CheckFpVars(m.d, bNeedT0, bNeedT1); break; case CM_FMT_TYPE_A_MOD_C: sprintf(tempstr, "comb.%s = %s * %s;\n", dst, func(m.a), func(m.c)); CheckFpVars(m.a, bNeedT0, bNeedT1); CheckFpVars(m.c, bNeedT0, bNeedT1); break; case CM_FMT_TYPE_A_ADD_D: sprintf(tempstr, "comb.%s = saturate(%s + %s);\n", dst, func(m.a), func(m.d)); CheckFpVars(m.a, bNeedT0, bNeedT1); CheckFpVars(m.d, bNeedT0, bNeedT1); break; case CM_FMT_TYPE_A_SUB_B: sprintf(tempstr, "comb.%s = %s - %s;\n", dst, func(m.a), func(m.b)); CheckFpVars(m.a, bNeedT0, bNeedT1); CheckFpVars(m.b, bNeedT0, bNeedT1); break; case CM_FMT_TYPE_A_MOD_C_ADD_D: sprintf(tempstr, "comb.%s = saturate(%s * %s + %s);\n", dst, func(m.a), func(m.c),func(m.d)); CheckFpVars(m.a, bNeedT0, bNeedT1); CheckFpVars(m.c, bNeedT0, bNeedT1); CheckFpVars(m.d, bNeedT0, bNeedT1); break; case CM_FMT_TYPE_A_LERP_B_C: //ARB ASM LERP and mix have different parameter ordering. //sprintf(tempstr, "comb.%s = saturate(mix(%s, %s, %s));\n", dst,func(m.a),func(m.b), func(m.c)); sprintf(tempstr, "comb.%s = (%s - %s) * %s + %s;\n", dst,func(m.a),func(m.b), func(m.c),func(m.b)); CheckFpVars(m.a, bNeedT0, bNeedT1); CheckFpVars(m.b, bNeedT0, bNeedT1); CheckFpVars(m.c, bNeedT0, bNeedT1); //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)); break; default: 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)); CheckFpVars(m.a, bNeedT0, bNeedT1); CheckFpVars(m.b, bNeedT0, bNeedT1); CheckFpVars(m.c, bNeedT0, bNeedT1); CheckFpVars(m.d, bNeedT0, bNeedT1); bNeedComb2 = true; break; } strcat(newFPBody, tempstr); } } oglNewFP[0] = 0; if (bNeedT0) strcat(oglNewFP, "#define NEED_TEX0\n"); if (bNeedT1) strcat(oglNewFP, "#define NEED_TEX1\n"); if(gRDP.bFogEnableInBlender && gRSP.bFogEnabled && options.fogMethod > 0) strcat(oglNewFP,"#define FOG"); strcat(oglNewFP, fragmentHeader); strcat(oglNewFP, newFPBody); strcat(oglNewFP, fragmentFooter); } int COGL_FragmentProgramCombiner::ParseDecodedMux() { if( !m_bFragmentProgramIsSupported ) return COGLColorCombiner4::ParseDecodedMux(); OGLShaderCombinerSaveType res; GLint success; if(vertexProgram == 9999) { vertexProgram = res.vertexShaderID = glCreateShader(GL_VERTEX_SHADER); glShaderSource(res.vertexShaderID, 1, &vertexShader,NULL); OPENGL_CHECK_ERRORS; glCompileShader(res.vertexShaderID); OPENGL_CHECK_ERRORS; } else { res.vertexShaderID = vertexProgram; } //Create 2 shaders, with and without alphatest GenerateProgramStr(); for(int alphaTest = 0;alphaTest < 2;alphaTest++) { res.fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); char* tmpShader = (char*)malloc(sizeof(char) * 4096); strcpy(tmpShader,"#version " GLSL_VERSION "\n"); if(alphaTest == 1) { strcat(tmpShader,"#define ALPHA_TEST\n"); } res.alphaTest = alphaTest == 1; strcat(tmpShader,oglNewFP); glShaderSource(res.fragmentShaderID, 1,(const char**) &tmpShader,NULL); free(tmpShader); OPENGL_CHECK_ERRORS; glCompileShader(res.fragmentShaderID); glGetShaderiv(res.fragmentShaderID, GL_COMPILE_STATUS, &success); if (!success) { char Log[1024]; GLint nLength; glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log); printf("Error compiling shader!\n %s",oglNewFP); printf(Log); } res.programID = glCreateProgram(); glAttachShader(res.programID,res.vertexShaderID); glAttachShader(res.programID,res.fragmentShaderID); //Bind Attributes glBindAttribLocation(res.programID,VS_COLOR,"aColor"); OPENGL_CHECK_ERRORS; glBindAttribLocation(res.programID,VS_TEXCOORD0,"aTexCoord0"); OPENGL_CHECK_ERRORS; glBindAttribLocation(res.programID,VS_TEXCOORD1,"aTexCoord1"); OPENGL_CHECK_ERRORS; glBindAttribLocation(res.programID,VS_POSITION,"aPosition"); OPENGL_CHECK_ERRORS; glLinkProgram(res.programID); OPENGL_CHECK_ERRORS; glGetProgramiv(res.programID, GL_LINK_STATUS, &success); if (!success) { char Log[1024]; GLint nLength; glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log); printf("Error linking program!\n"); printf("%s\n",Log); } glUseProgram(res.programID); OPENGL_CHECK_ERRORS; //Bind texture samplers GLint tex0 = glGetUniformLocation(res.programID,"uTex0"); GLint tex1 = glGetUniformLocation(res.programID,"uTex1"); if(tex0 != -1) glUniform1i(tex0,0); if(tex1 != -1) glUniform1i(tex1,1); //Bind Uniforms res.PrimColorLocation = glGetUniformLocation(res.programID,"PrimColor"); OPENGL_CHECK_ERRORS; res.EnvColorLocation = glGetUniformLocation(res.programID,"EnvColor"); OPENGL_CHECK_ERRORS; res.PrimFracLocation = glGetUniformLocation(res.programID,"PrimFrac"); OPENGL_CHECK_ERRORS; res.EnvFracLocation = glGetUniformLocation(res.programID,"EnvFrac"); OPENGL_CHECK_ERRORS; res.AlphaRefLocation = glGetUniformLocation(res.programID,"AlphaRef"); OPENGL_CHECK_ERRORS; res.FogColorLocation = glGetUniformLocation(res.programID,"FogColor"); OPENGL_CHECK_ERRORS; res.FogMinMaxLocation = glGetUniformLocation(res.programID,"FogMinMax"); OPENGL_CHECK_ERRORS; res.dwMux0 = m_pDecodedMux->m_dwMux0; res.dwMux1 = m_pDecodedMux->m_dwMux1; res.fogIsUsed = gRDP.bFogEnableInBlender && gRSP.bFogEnabled; m_vCompiledShaders.push_back(res); } m_lastIndex = m_vCompiledShaders.size()-2; return m_lastIndex; } void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index) { GLuint ID = m_vCompiledShaders[index].programID; glUseProgram(ID); glEnableVertexAttribArray(VS_POSITION); OPENGL_CHECK_ERRORS; glVertexAttribPointer(VS_POSITION,4,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][0])); OPENGL_CHECK_ERRORS; glEnableVertexAttribArray(VS_TEXCOORD0); OPENGL_CHECK_ERRORS; glVertexAttribPointer(VS_TEXCOORD0,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[0].u)); OPENGL_CHECK_ERRORS; glEnableVertexAttribArray(VS_TEXCOORD1); OPENGL_CHECK_ERRORS; glVertexAttribPointer(VS_TEXCOORD1,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[1].u)); OPENGL_CHECK_ERRORS; glEnableVertexAttribArray(VS_COLOR); OPENGL_CHECK_ERRORS; glVertexAttribPointer(VS_COLOR, 4, GL_UNSIGNED_BYTE,GL_TRUE, sizeof(uint8)*4, &(g_oglVtxColors[0][0]) ); OPENGL_CHECK_ERRORS; } void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index) { OGLShaderCombinerSaveType prog = m_vCompiledShaders[index]; glUseProgram(prog.programID); float *pf; if(prog.EnvColorLocation != -1) { pf = GetEnvColorfv(); glUniform4fv(prog.EnvColorLocation,1, pf); OPENGL_CHECK_ERRORS; } if(prog.PrimColorLocation != -1) { pf = GetPrimitiveColorfv(); glUniform4fv(prog.PrimColorLocation,1, pf); OPENGL_CHECK_ERRORS; } if(prog.EnvFracLocation != -1) { float frac = gRDP.LODFrac / 255.0f; float tempf[4] = {frac,frac,frac,frac}; glUniform4fv(prog.EnvFracLocation,1, tempf); OPENGL_CHECK_ERRORS; } if(prog.PrimFracLocation != -1) { float frac2 = gRDP.primLODFrac / 255.0f; float tempf2[4] = {frac2,frac2,frac2,frac2}; glUniform4fv(prog.PrimFracLocation,1, tempf2); OPENGL_CHECK_ERRORS; } //if(prog.FogColorLocation != -1 && prog.FogMinMaxLocation != -1) //{ // //Pass fog colour and distance, use 0 alpha if fog disabled // glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2], // gRSP.bFogEnabled ? gRDP.fvFogColor[0] : 0.0f); // glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax); //} if(prog.AlphaRefLocation != -1) glUniform1f(prog.AlphaRefLocation,m_AlphaRef); OPENGL_CHECK_ERRORS; } void COGL_FragmentProgramCombiner::UpdateFog(bool bEnable) { if(m_lastIndex < 0 || m_lastIndex >= m_vCompiledShaders.size()) return; OGLShaderCombinerSaveType prog = m_vCompiledShaders[m_lastIndex]; //if(bEnable) // DebugMessage(M64MSG_INFO,"Fog Color %x Min %f Max %f",gRDP.fogColor,gRSPfFogMin,gRSPfFogMax); if(prog.FogColorLocation != -1 && prog.FogMinMaxLocation != -1) { //Pass fog colour and distance, use 0 alpha if fog disabled glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2], bEnable ? gRDP.fvFogColor[0] : 0.0f); //glUniform4f(prog.FogColorLocation, 1.0f,0.3f,0.3f,1.0f); //OPENGL_CHECK_ERRORS; glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax); OPENGL_CHECK_ERRORS; } } int COGL_FragmentProgramCombiner::FindCompiledMux() { #ifdef DEBUGGER if( debuggerDropCombiners ) { m_vCompiledShaders.clear(); //m_dwLastMux0 = m_dwLastMux1 = 0; debuggerDropCombiners = false; } #endif for( uint32 i=0; im_dwMux0 && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1 && m_vCompiledShaders[i].fogIsUsed == (gRDP.bFogEnableInBlender && gRSP.bFogEnabled) && m_vCompiledShaders[i].alphaTest == m_AlphaRef > 0.0f) { return (int)i; } } return -1; } ////////////////////////////////////////////////////////////////////////// void COGL_FragmentProgramCombiner::InitCombinerCycle12(void) { if( !m_bFragmentProgramIsSupported ) { COGLColorCombiner4::InitCombinerCycle12(); return; } #ifdef DEBUGGER if( debuggerDropCombiners ) { UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1); m_vCompiledShaders.clear(); m_dwLastMux0 = m_dwLastMux1 = 0; debuggerDropCombiners = false; } #endif m_pOGLRender->EnableMultiTexture(); bool combinerIsChanged = false; if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 ) { combinerIsChanged = true; m_lastIndex = FindCompiledMux(); if( m_lastIndex < 0 ) // Can not found { m_lastIndex = ParseDecodedMux(); } m_dwLastMux0 = m_pDecodedMux->m_dwMux0; m_dwLastMux1 = m_pDecodedMux->m_dwMux1; } GenerateCombinerSettingConstants(m_lastIndex); if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded ) { if( m_bCycleChanged || combinerIsChanged ) { GenerateCombinerSettingConstants(m_lastIndex); GenerateCombinerSetting(m_lastIndex); } else if( gRDP.colorsAreReloaded ) { GenerateCombinerSettingConstants(m_lastIndex); } m_pOGLRender->SetAllTexelRepeatFlag(); gRDP.colorsAreReloaded = false; gRDP.texturesAreReloaded = false; } else { m_pOGLRender->SetAllTexelRepeatFlag(); } } #ifdef DEBUGGER void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void) { COGLColorCombiner::DisplaySimpleMuxString(); DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux; mux.Reformat(false); GenerateProgramStr(); //sprintf(oglNewFP, oglFP, // MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0), // MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0), // MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1), // MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1) // ); TRACE0("OGL Fragment Program:"); TRACE0(oglNewFP); } #endif