Path: blob/master/libmupen64plus/mupen64plus-video-rice/src/OGLES2FragmentShaders.cpp
2 views
/*1Copyright (C) 2003 Rice196423This program is free software; you can redistribute it and/or4modify it under the terms of the GNU General Public License5as published by the Free Software Foundation; either version 26of the License, or (at your option) any later version.78This program is distributed in the hope that it will be useful,9but WITHOUT ANY WARRANTY; without even the implied warranty of10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11GNU General Public License for more details.1213You should have received a copy of the GNU General Public License14along with this program; if not, write to the Free Software15Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.16*/1718#include "OGLDebug.h"19#include "OGLES2FragmentShaders.h"20#include "OGLRender.h"21#include "OGLGraphicsContext.h"22#include "OGLTexture.h"2324#define ALPHA_TEST " if(gl_FragColor.a < AlphaRef) discard; \n"25//#define ALPHA_TEST262728GLuint vertexProgram = 9999;29const char *vertexShader =30"#version " GLSL_VERSION "\n"31"attribute mediump vec4 aPosition; \n"\32"attribute lowp vec4 aColor; \n"\33"attribute lowp vec2 aTexCoord0; \n"\34"attribute lowp vec2 aTexCoord1; \n"\35"attribute lowp vec2 aAtlasTransform; \n"\36" \n"\37"uniform lowp vec2 FogMinMax; \n"\38" \n"\39"varying lowp float vFactor; \n"\40"varying lowp vec4 vShadeColor; \n"\41"varying mediump vec2 vTexCoord0; \n"\42"varying lowp vec2 vTexCoord1; \n"\43"varying lowp float vFog; \n"\44" \n"\45"void main() \n"\46"{ \n"\47"gl_Position = aPosition; //gl_Position.z = max(0.0,gl_Position.z); \n"\48"vShadeColor = aColor; \n"\49"vTexCoord0 = aTexCoord0; \n"\50"vTexCoord1 = aTexCoord1; \n"\51"vFog = clamp((FogMinMax[1] - (gl_Position.z/aPosition.w))/(FogMinMax[1]-FogMinMax[0]),0.0,1.0); \n"\52" \n"\53"} \n"\54" \n";5556const char *fragmentHeader =57"#define saturate(x) clamp( x, 0.0, 1.0 ) \n"\58"precision lowp float; \n"\59"#ifdef NEED_TEX0 \n"\60"uniform sampler2D uTex0; \n"\61"#endif \n"\62" \n"\63"#ifdef NEED_TEX1 \n"\64"uniform sampler2D uTex1; \n"\65"#endif \n"\66" \n"\67"uniform vec4 EnvColor; \n"\68"uniform vec4 PrimColor; \n"\69"uniform vec4 EnvFrac; \n"\70"uniform vec4 PrimFrac; \n"\71"uniform float AlphaRef; \n"\72"uniform vec4 FogColor; \n"\73" \n"\74"varying lowp float vFactor; \n"\75"varying lowp vec4 vShadeColor; \n"\76"varying mediump vec2 vTexCoord0; \n"\77"varying lowp vec2 vTexCoord1; \n"\78"varying lowp float vFog; \n"\79" \n"\80"void main() \n"\81"{ \n"\82"vec4 comb,comb2; \n"\83" \n"\84"#ifdef NEED_TEX0 \n"\85"vec4 t0 = texture2D(uTex0,vTexCoord0); \n"\86"#endif \n"\87" \n"\88"#ifdef NEED_TEX1 \n"\89"vec4 t1 = texture2D(uTex1,vTexCoord1); \n"\90"#endif \n";9192const char *fragmentFooter =93" \n"\94"#ifdef FOG \n"\95"gl_FragColor.rgb = mix(FogColor.rgb,comb.rgb,vFog * step(0.5,1.0-FogColor.a)); \n"\96"gl_FragColor.a = comb.a; \n"\97"#else \n"\98"gl_FragColor = comb; \n"\99"#endif \n"\100" \n"\101"#ifdef ALPHA_TEST \n"\102ALPHA_TEST103"#endif \n"\104" \n"\105" \n"\106" \n"\107" \n"\108"} \n";109110//Fragment shader for InitCycleCopy111const char *fragmentCopy =112"#version " GLSL_VERSION "\n"\113"precision lowp float; \n"\114"uniform sampler2D uTex0; \n"\115"uniform float AlphaRef; \n"\116"varying lowp vec2 vTexCoord0; \n"\117"void main() \n"\118"{ \n"\119" gl_FragColor = texture2D(uTex0,vTexCoord0).bgra; \n"\120ALPHA_TEST121"}";122123GLuint copyProgram,copyAlphaLocation;124125//Fragment shader for InitCycleFill126const char *fragmentFill =127"#version " GLSL_VERSION "\n"\128"precision lowp float; \n"129"uniform vec4 uColor; \n"130"void main() \n"131"{ \n"132" gl_FragColor = uColor; \n"133"}";134135GLuint fillProgram,fillColorLocation;136137COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender)138: COGLColorCombiner(pRender)139{140m_bShaderIsSupported = true;141}142COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner()143{144}145146bool COGLFragmentShaderCombiner::Initialize(void)147{148if( !COGLColorCombiner::Initialize() )149return false;150151COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);152// if( pcontext->IsExtensionSupported("GL_fragment_shader") )153// {154m_bShaderIsSupported = true;155// }156157return true;158}159160void COGLFragmentShaderCombiner::InitCombinerCycle12(void)161{162}163void COGLFragmentShaderCombiner::DisableCombiner(void)164{165COGLColorCombiner::DisableCombiner();166}167168void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void)169{170COGLColorCombiner::InitCombinerCycleCopy();171}172173void COGLFragmentShaderCombiner::InitCombinerCycleFill(void)174{175COGLColorCombiner::InitCombinerCycleFill();176}177void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)178{179COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);180}181182#ifdef DEBUGGER183void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void)184{185COGLColorCombiner::DisplaySimpleMuxString();186}187#endif188189190191COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender)192: COGLColorCombiner4(pRender)193{194delete m_pDecodedMux;195m_pDecodedMux = new DecodedMuxForPixelShader;196m_bFragmentProgramIsSupported = true;197m_AlphaRef = 0.0f;198199//Create shaders for fill and copy200GLint success;201GLuint vs,fs;202copyProgram = glCreateProgram();203vs = glCreateShader(GL_VERTEX_SHADER);204glShaderSource(vs,1,&vertexShader,NULL);205glCompileShader(vs);206207glGetShaderiv(vs,GL_COMPILE_STATUS,&success);208if(!success)209{210char log[1024];211glGetShaderInfoLog(vs,1024,NULL,log);212printf("%s\n",log);213}214215fs = glCreateShader(GL_FRAGMENT_SHADER);216glShaderSource(fs,1,&fragmentCopy,NULL);217glCompileShader(fs);218219glGetShaderiv(fs,GL_COMPILE_STATUS,&success);220if(!success)221{222char log[1024];223glGetShaderInfoLog(fs,1024,NULL,log);224printf("%s\n",log);225}226227glAttachShader(copyProgram,vs);228glAttachShader(copyProgram,fs);229230glBindAttribLocation(copyProgram,VS_TEXCOORD0,"aTexCoord0");231OPENGL_CHECK_ERRORS;232glBindAttribLocation(copyProgram,VS_POSITION,"aPosition");233OPENGL_CHECK_ERRORS;234235glLinkProgram(copyProgram);236copyAlphaLocation = glGetUniformLocation(copyProgram,"AlphaRef");237glGetProgramiv(copyProgram,GL_LINK_STATUS,&success);238if(!success)239{240char log[1024];241glGetProgramInfoLog(copyProgram,1024,NULL,log);242printf("%s\n",log);243}244245glDeleteShader(fs);246247//Fill shader248fs = glCreateShader(GL_FRAGMENT_SHADER);249glShaderSource(fs,1,&fragmentFill,NULL);250glCompileShader(fs);251252glGetShaderiv(fs,GL_COMPILE_STATUS,&success);253if(!success)254{255char log[1024];256glGetShaderInfoLog(fs,1024,NULL,log);257printf("%s\n",log);258}259260fillProgram = glCreateProgram();261glAttachShader(fillProgram,vs);262glAttachShader(fillProgram,fs);263264glBindAttribLocation(fillProgram,VS_POSITION,"aPosition");265OPENGL_CHECK_ERRORS;266267glLinkProgram(fillProgram);268269270fillColorLocation = glGetUniformLocation(fillProgram,"uColor");271272glDeleteShader(fs);273glDeleteShader(vs);274}275COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner()276{277int size = m_vCompiledShaders.size();278for (int i=0; i<size; i++)279{280GLuint ID = m_vCompiledShaders[i].programID;281glDeleteProgram(ID);282283OPENGL_CHECK_ERRORS;284m_vCompiledShaders[i].programID = 0;285}286287m_vCompiledShaders.clear();288}289290bool COGL_FragmentProgramCombiner::Initialize(void)291{292if( !COGLColorCombiner4::Initialize() )293return false;294295COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);296// if( pcontext->IsExtensionSupported("GL_fragment_program") )297// {298m_bFragmentProgramIsSupported = true;299// }300301return true;302}303304305306void COGL_FragmentProgramCombiner::DisableCombiner(void)307{308//glDisable(GL_FRAGMENT_PROGRAM);309//OPENGL_CHECK_ERRORS;310COGLColorCombiner4::DisableCombiner();311}312313void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void)314{315m_pOGLRender->DisableMultiTexture();316m_pOGLRender->EnableTexUnit(0,TRUE);317glUseProgram(copyProgram);318glUniform1f(copyAlphaLocation,m_AlphaRef);319OPENGL_CHECK_ERRORS;320glEnableVertexAttribArray(VS_POSITION);321OPENGL_CHECK_ERRORS;322glEnableVertexAttribArray(VS_TEXCOORD0);323OPENGL_CHECK_ERRORS;324glDisableVertexAttribArray(VS_COLOR);325OPENGL_CHECK_ERRORS;326glDisableVertexAttribArray(VS_TEXCOORD1);327OPENGL_CHECK_ERRORS;328COGLTexture* pTexture = g_textures[gRSP.curTile].m_pCOGLTexture;329if( pTexture )330{331m_pOGLRender->BindTexture(pTexture->m_dwTextureName, 0);332m_pOGLRender->SetTexelRepeatFlags(gRSP.curTile);333}334}335336void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void)337{338glUseProgram(fillProgram);339glUniform4f(fillColorLocation,((gRDP.fillColor>>16)&0xFF)/255.0f,((gRDP.fillColor>>8)&0xFF)/255.0f,((gRDP.fillColor)&0xFF)/255.0f,((gRDP.fillColor>>24)&0xFF)/255.0f);340OPENGL_CHECK_ERRORS;341}342343#ifdef BGR_SHADER344const char *muxToFP_Maps[][2] = {345//color -- alpha346{"vec3(0.0)", "0.0"}, //MUX_0 = 0,347{"vec3(1.0)", "1.0"}, //MUX_1,348{"comb.rgb", "comb.a"}, //MUX_COMBINED,349{"t0.rgb", "t0.a"}, //MUX_TEXEL0,350{"t1.rgb", "t1.a"}, //MUX_TEXEL1,351{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM,352{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE,353{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV,354{"comb.rgb", "comb.a"}, //MUX_COMBALPHA,355{"t0.rgb", "t0.a"}, //MUX_T0_ALPHA,356{"t1.rgb", "t1.a"}, //MUX_T1_ALPHA,357{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA,358{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA,359{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA,360{"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC,361{"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC,362{"vec3(1.0)", "1.0"}, //MUX_K5,363{"vec3(1.0)", "1.0"}, //MUX_UNK, // Should not be used364};365#else366const char *muxToFP_Maps[][2] = {367//color -- alpha368{"vec3(0.0)", "0.0"}, //MUX_0 = 0,369{"vec3(1.0)", "1.0"}, //MUX_1,370{"comb.rgb", "comb.a"}, //MUX_COMBINED,371{"t0.bgr", "t0.a"}, //MUX_TEXEL0,372{"t1.bgr", "t1.a"}, //MUX_TEXEL1,373{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM,374{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE,375{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV,376{"comb.rgb", "comb.a"}, //MUX_COMBALPHA,377{"t0.bgr", "t0.a"}, //MUX_T0_ALPHA,378{"t1.bgr", "t1.a"}, //MUX_T1_ALPHA,379{"PrimColor.rgb", "PrimColor.a"}, //MUX_PRIM_ALPHA,380{"vShadeColor.rgb", "vShadeColor.a"}, //MUX_SHADE_ALPHA,381{"EnvColor.rgb", "EnvColor.a"}, //MUX_ENV_ALPHA,382{"EnvFrac.a", "EnvFrac.a"}, //MUX_LODFRAC,383{"PrimFrac.a", "PrimFrac.a"}, //MUX_PRIMLODFRAC,384{"vec3(1.0)", "1.0"}, //MUX_K5,385{"vec3(1.0)", "1.0"}, //MUX_UNK, // Should not be used386};387#endif388389390char oglNewFP[4092];391392char* MuxToOC(uint8 val)393{394// For color channel395if( val&MUX_ALPHAREPLICATE )396return (char*)muxToFP_Maps[val&0x1F][1];397else398return (char*)muxToFP_Maps[val&0x1F][0];399}400401char* MuxToOA(uint8 val)402{403// For alpha channel404return (char*)muxToFP_Maps[val&0x1F][1];405}406407static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1)408{409MuxVar &= 0x1f;410if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA)411bNeedT0 = true;412if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA)413bNeedT1 = true;414}415416void COGL_FragmentProgramCombiner::GenerateProgramStr()417{418DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;419420mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED;421m_pDecodedMux->Reformat(false);422423char tempstr[500], newFPBody[4092];424bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false;425newFPBody[0] = 0;426427for( int cycle=0; cycle<2; cycle++ )428{429for( int channel=0; channel<2; channel++)430{431char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA;432char *dst = channel==0?(char*)"rgb":(char*)"a";433N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel];434switch( mux.splitType[cycle*2+channel] )435{436case CM_FMT_TYPE_NOT_USED:437tempstr[0] = 0;438break;439case CM_FMT_TYPE_D:440sprintf(tempstr, "comb.%s = %s;\n", dst, func(m.d));441CheckFpVars(m.d, bNeedT0, bNeedT1);442break;443case CM_FMT_TYPE_A_MOD_C:444sprintf(tempstr, "comb.%s = %s * %s;\n", dst, func(m.a), func(m.c));445CheckFpVars(m.a, bNeedT0, bNeedT1);446CheckFpVars(m.c, bNeedT0, bNeedT1);447break;448case CM_FMT_TYPE_A_ADD_D:449sprintf(tempstr, "comb.%s = saturate(%s + %s);\n", dst, func(m.a), func(m.d));450CheckFpVars(m.a, bNeedT0, bNeedT1);451CheckFpVars(m.d, bNeedT0, bNeedT1);452break;453case CM_FMT_TYPE_A_SUB_B:454sprintf(tempstr, "comb.%s = %s - %s;\n", dst, func(m.a), func(m.b));455CheckFpVars(m.a, bNeedT0, bNeedT1);456CheckFpVars(m.b, bNeedT0, bNeedT1);457break;458case CM_FMT_TYPE_A_MOD_C_ADD_D:459sprintf(tempstr, "comb.%s = saturate(%s * %s + %s);\n", dst, func(m.a), func(m.c),func(m.d));460CheckFpVars(m.a, bNeedT0, bNeedT1);461CheckFpVars(m.c, bNeedT0, bNeedT1);462CheckFpVars(m.d, bNeedT0, bNeedT1);463break;464case CM_FMT_TYPE_A_LERP_B_C:465//ARB ASM LERP and mix have different parameter ordering.466//sprintf(tempstr, "comb.%s = saturate(mix(%s, %s, %s));\n", dst,func(m.a),func(m.b), func(m.c));467sprintf(tempstr, "comb.%s = (%s - %s) * %s + %s;\n", dst,func(m.a),func(m.b), func(m.c),func(m.b));468CheckFpVars(m.a, bNeedT0, bNeedT1);469CheckFpVars(m.b, bNeedT0, bNeedT1);470CheckFpVars(m.c, bNeedT0, bNeedT1);471//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));472break;473default:474sprintf(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));475CheckFpVars(m.a, bNeedT0, bNeedT1);476CheckFpVars(m.b, bNeedT0, bNeedT1);477CheckFpVars(m.c, bNeedT0, bNeedT1);478CheckFpVars(m.d, bNeedT0, bNeedT1);479bNeedComb2 = true;480break;481}482strcat(newFPBody, tempstr);483}484}485486oglNewFP[0] = 0;487if (bNeedT0)488strcat(oglNewFP, "#define NEED_TEX0\n");489if (bNeedT1)490strcat(oglNewFP, "#define NEED_TEX1\n");491if(gRDP.bFogEnableInBlender && gRSP.bFogEnabled && options.fogMethod > 0)492strcat(oglNewFP,"#define FOG");493strcat(oglNewFP, fragmentHeader);494strcat(oglNewFP, newFPBody);495strcat(oglNewFP, fragmentFooter);496497}498499int COGL_FragmentProgramCombiner::ParseDecodedMux()500{501if( !m_bFragmentProgramIsSupported )502return COGLColorCombiner4::ParseDecodedMux();503504OGLShaderCombinerSaveType res;505GLint success;506507if(vertexProgram == 9999)508{509vertexProgram = res.vertexShaderID = glCreateShader(GL_VERTEX_SHADER);510glShaderSource(res.vertexShaderID, 1, &vertexShader,NULL);511OPENGL_CHECK_ERRORS;512glCompileShader(res.vertexShaderID);513OPENGL_CHECK_ERRORS;514}515else516{517res.vertexShaderID = vertexProgram;518}519520521//Create 2 shaders, with and without alphatest522GenerateProgramStr();523524for(int alphaTest = 0;alphaTest < 2;alphaTest++)525{526res.fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);527528char* tmpShader = (char*)malloc(sizeof(char) * 4096);529strcpy(tmpShader,"#version " GLSL_VERSION "\n");530531if(alphaTest == 1)532{533strcat(tmpShader,"#define ALPHA_TEST\n");534}535536res.alphaTest = alphaTest == 1;537strcat(tmpShader,oglNewFP);538539glShaderSource(res.fragmentShaderID, 1,(const char**) &tmpShader,NULL);540free(tmpShader);541542543OPENGL_CHECK_ERRORS;544glCompileShader(res.fragmentShaderID);545546glGetShaderiv(res.fragmentShaderID, GL_COMPILE_STATUS, &success);547if (!success)548{549char Log[1024];550GLint nLength;551glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);552printf("Error compiling shader!\n %s",oglNewFP);553printf(Log);554}555556res.programID = glCreateProgram();557glAttachShader(res.programID,res.vertexShaderID);558glAttachShader(res.programID,res.fragmentShaderID);559560//Bind Attributes561glBindAttribLocation(res.programID,VS_COLOR,"aColor");562OPENGL_CHECK_ERRORS;563glBindAttribLocation(res.programID,VS_TEXCOORD0,"aTexCoord0");564OPENGL_CHECK_ERRORS;565glBindAttribLocation(res.programID,VS_TEXCOORD1,"aTexCoord1");566OPENGL_CHECK_ERRORS;567glBindAttribLocation(res.programID,VS_POSITION,"aPosition");568OPENGL_CHECK_ERRORS;569570glLinkProgram(res.programID);571OPENGL_CHECK_ERRORS;572573glGetProgramiv(res.programID, GL_LINK_STATUS, &success);574if (!success)575{576char Log[1024];577GLint nLength;578glGetShaderInfoLog(res.fragmentShaderID, 1024, &nLength, Log);579printf("Error linking program!\n");580printf("%s\n",Log);581}582583glUseProgram(res.programID);584OPENGL_CHECK_ERRORS;585586//Bind texture samplers587GLint tex0 = glGetUniformLocation(res.programID,"uTex0");588GLint tex1 = glGetUniformLocation(res.programID,"uTex1");589590if(tex0 != -1)591glUniform1i(tex0,0);592if(tex1 != -1)593glUniform1i(tex1,1);594595//Bind Uniforms596res.PrimColorLocation = glGetUniformLocation(res.programID,"PrimColor");597OPENGL_CHECK_ERRORS;598res.EnvColorLocation = glGetUniformLocation(res.programID,"EnvColor");599OPENGL_CHECK_ERRORS;600res.PrimFracLocation = glGetUniformLocation(res.programID,"PrimFrac");601OPENGL_CHECK_ERRORS;602res.EnvFracLocation = glGetUniformLocation(res.programID,"EnvFrac");603OPENGL_CHECK_ERRORS;604res.AlphaRefLocation = glGetUniformLocation(res.programID,"AlphaRef");605OPENGL_CHECK_ERRORS;606res.FogColorLocation = glGetUniformLocation(res.programID,"FogColor");607OPENGL_CHECK_ERRORS;608res.FogMinMaxLocation = glGetUniformLocation(res.programID,"FogMinMax");609OPENGL_CHECK_ERRORS;610611res.dwMux0 = m_pDecodedMux->m_dwMux0;612res.dwMux1 = m_pDecodedMux->m_dwMux1;613res.fogIsUsed = gRDP.bFogEnableInBlender && gRSP.bFogEnabled;614615m_vCompiledShaders.push_back(res);616}617m_lastIndex = m_vCompiledShaders.size()-2;618619return m_lastIndex;620}621622void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index)623{624GLuint ID = m_vCompiledShaders[index].programID;625626glUseProgram(ID);627glEnableVertexAttribArray(VS_POSITION);628OPENGL_CHECK_ERRORS;629glVertexAttribPointer(VS_POSITION,4,GL_FLOAT,GL_FALSE,sizeof(float)*5,&(g_vtxProjected5[0][0]));630OPENGL_CHECK_ERRORS;631632glEnableVertexAttribArray(VS_TEXCOORD0);633OPENGL_CHECK_ERRORS;634glVertexAttribPointer(VS_TEXCOORD0,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[0].u));635OPENGL_CHECK_ERRORS;636637glEnableVertexAttribArray(VS_TEXCOORD1);638OPENGL_CHECK_ERRORS;639glVertexAttribPointer(VS_TEXCOORD1,2,GL_FLOAT,GL_FALSE, sizeof( TLITVERTEX ), &(g_vtxBuffer[0].tcord[1].u));640OPENGL_CHECK_ERRORS;641642glEnableVertexAttribArray(VS_COLOR);643OPENGL_CHECK_ERRORS;644glVertexAttribPointer(VS_COLOR, 4, GL_UNSIGNED_BYTE,GL_TRUE, sizeof(uint8)*4, &(g_oglVtxColors[0][0]) );645OPENGL_CHECK_ERRORS;646}647648void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index)649{650OGLShaderCombinerSaveType prog = m_vCompiledShaders[index];651652glUseProgram(prog.programID);653float *pf;654if(prog.EnvColorLocation != -1)655{656pf = GetEnvColorfv();657glUniform4fv(prog.EnvColorLocation,1, pf);658OPENGL_CHECK_ERRORS;659}660661if(prog.PrimColorLocation != -1)662{663pf = GetPrimitiveColorfv();664glUniform4fv(prog.PrimColorLocation,1, pf);665OPENGL_CHECK_ERRORS;666}667668if(prog.EnvFracLocation != -1)669{670float frac = gRDP.LODFrac / 255.0f;671float tempf[4] = {frac,frac,frac,frac};672glUniform4fv(prog.EnvFracLocation,1, tempf);673OPENGL_CHECK_ERRORS;674}675676if(prog.PrimFracLocation != -1)677{678float frac2 = gRDP.primLODFrac / 255.0f;679float tempf2[4] = {frac2,frac2,frac2,frac2};680glUniform4fv(prog.PrimFracLocation,1, tempf2);681OPENGL_CHECK_ERRORS;682}683684//if(prog.FogColorLocation != -1 && prog.FogMinMaxLocation != -1)685//{686// //Pass fog colour and distance, use 0 alpha if fog disabled687// glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2],688// gRSP.bFogEnabled ? gRDP.fvFogColor[0] : 0.0f);689// glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);690//}691692if(prog.AlphaRefLocation != -1)693glUniform1f(prog.AlphaRefLocation,m_AlphaRef);694OPENGL_CHECK_ERRORS;695}696697void COGL_FragmentProgramCombiner::UpdateFog(bool bEnable)698{699if(m_lastIndex < 0 || m_lastIndex >= m_vCompiledShaders.size())700return;701OGLShaderCombinerSaveType prog = m_vCompiledShaders[m_lastIndex];702703//if(bEnable)704// DebugMessage(M64MSG_INFO,"Fog Color %x Min %f Max %f",gRDP.fogColor,gRSPfFogMin,gRSPfFogMax);705706if(prog.FogColorLocation != -1 && prog.FogMinMaxLocation != -1)707{708//Pass fog colour and distance, use 0 alpha if fog disabled709glUniform4f(prog.FogColorLocation, gRDP.fvFogColor[0],gRDP.fvFogColor[1],gRDP.fvFogColor[2],710bEnable ? gRDP.fvFogColor[0] : 0.0f);711//glUniform4f(prog.FogColorLocation, 1.0f,0.3f,0.3f,1.0f);712//OPENGL_CHECK_ERRORS;713glUniform2f(prog.FogMinMaxLocation,gRSPfFogMin,gRSPfFogMax);714OPENGL_CHECK_ERRORS;715}716}717718int COGL_FragmentProgramCombiner::FindCompiledMux()719{720#ifdef DEBUGGER721if( debuggerDropCombiners )722{723m_vCompiledShaders.clear();724//m_dwLastMux0 = m_dwLastMux1 = 0;725debuggerDropCombiners = false;726}727#endif728for( uint32 i=0; i<m_vCompiledShaders.size(); i++ )729{730if( m_vCompiledShaders[i].dwMux0 == m_pDecodedMux->m_dwMux0731&& m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1732&& m_vCompiledShaders[i].fogIsUsed == (gRDP.bFogEnableInBlender && gRSP.bFogEnabled)733&& m_vCompiledShaders[i].alphaTest == m_AlphaRef > 0.0f)734{735return (int)i;736}737}738739return -1;740}741742//////////////////////////////////////////////////////////////////////////743void COGL_FragmentProgramCombiner::InitCombinerCycle12(void)744{745if( !m_bFragmentProgramIsSupported )746{747COGLColorCombiner4::InitCombinerCycle12();748return;749}750751#ifdef DEBUGGER752if( debuggerDropCombiners )753{754UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1);755m_vCompiledShaders.clear();756m_dwLastMux0 = m_dwLastMux1 = 0;757debuggerDropCombiners = false;758}759#endif760761m_pOGLRender->EnableMultiTexture();762763bool combinerIsChanged = false;764765if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 )766{767combinerIsChanged = true;768m_lastIndex = FindCompiledMux();769if( m_lastIndex < 0 ) // Can not found770{771m_lastIndex = ParseDecodedMux();772}773774m_dwLastMux0 = m_pDecodedMux->m_dwMux0;775m_dwLastMux1 = m_pDecodedMux->m_dwMux1;776}777778779GenerateCombinerSettingConstants(m_lastIndex);780if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )781{782if( m_bCycleChanged || combinerIsChanged )783{784GenerateCombinerSettingConstants(m_lastIndex);785GenerateCombinerSetting(m_lastIndex);786}787else if( gRDP.colorsAreReloaded )788{789GenerateCombinerSettingConstants(m_lastIndex);790}791792m_pOGLRender->SetAllTexelRepeatFlag();793794gRDP.colorsAreReloaded = false;795gRDP.texturesAreReloaded = false;796}797else798{799m_pOGLRender->SetAllTexelRepeatFlag();800}801}802803#ifdef DEBUGGER804void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void)805{806COGLColorCombiner::DisplaySimpleMuxString();807DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux;808mux.Reformat(false);809GenerateProgramStr();810//sprintf(oglNewFP, oglFP,811// MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0),812// MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0),813// MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1),814// MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1)815// );816817TRACE0("OGL Fragment Program:");818TRACE0(oglNewFP);819}820#endif821822823824