diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index b1036c0..1e511bb 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -67,13 +67,6 @@ struct UniformObject RGBAf lightColor[MAX_LIGHTS]; }; -struct GLShaderState -{ - RGBA matColor; - SurfaceProperties surfProps; - float extraSurfProp; -}; - const char *shaderDecl120 = "#version 120\n" "#define GL2\n" @@ -120,16 +113,11 @@ static GLuint whitetex; static UniformState uniformState; static UniformScene uniformScene; static UniformObject uniformObject; -static GLShaderState shaderState; #ifndef RW_GL_USE_UBOS // State int32 u_alphaRef; int32 u_fogData; -//int32 u_fogStart; -//int32 u_fogEnd; -//int32 u_fogRange; -//int32 u_fogDisable; int32 u_fogColor; // Scene @@ -405,6 +393,8 @@ getAlphaBlend(void) return rwStateCache.blendEnable; } +bool32 getAlphaTest(void) { return rwStateCache.alphaTestEnable; } + static void setDepthTest(bool32 enable) { @@ -980,6 +970,7 @@ void setWorldMatrix(Matrix *mat) { convMatrix(&uniformObject.world, mat); + setUniform(u_world, &uniformObject.world); objectDirty = 1; } @@ -1045,6 +1036,12 @@ setLights(WorldLights *lightData) } uniformObject.lightParams[n].type = 0.0f; + + setUniform(u_ambLight, &uniformObject.ambLight); + setUniform(u_lightParams, uniformObject.lightParams); + setUniform(u_lightPosition, uniformObject.lightPosition); + setUniform(u_lightDirection, uniformObject.lightDirection); + setUniform(u_lightColor, uniformObject.lightColor); out: objectDirty = 1; return bits; @@ -1054,6 +1051,7 @@ void setProjectionMatrix(float32 *mat) { memcpy(&uniformScene.proj, mat, 64); + setUniform(u_proj, uniformScene.proj); sceneDirty = 1; } @@ -1061,6 +1059,7 @@ void setViewMatrix(float32 *mat) { memcpy(&uniformScene.view, mat, 64); + setUniform(u_view, uniformScene.view); sceneDirty = 1; } @@ -1071,27 +1070,16 @@ Shader *lastShaderUploaded; void setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp) { - bool force = lastShaderUploaded != currentShader; - if(force || !equal(shaderState.matColor, color)){ - rw::RGBAf col; - convColor(&col, &color); - glUniform4fv(U(u_matColor), 1, (GLfloat*)&col); - shaderState.matColor = color; - } + rw::RGBAf col; + convColor(&col, &color); + setUniform(u_matColor, &col); - if(force || - shaderState.surfProps.ambient != surfaceprops.ambient || - shaderState.surfProps.specular != surfaceprops.specular || - shaderState.surfProps.diffuse != surfaceprops.diffuse || - shaderState.extraSurfProp != extraSurfProp){ - float surfProps[4]; - surfProps[0] = surfaceprops.ambient; - surfProps[1] = surfaceprops.specular; - surfProps[2] = surfaceprops.diffuse; - surfProps[3] = extraSurfProp; - glUniform4fv(U(u_surfProps), 1, surfProps); - shaderState.surfProps = surfaceprops; - } + float surfProps[4]; + surfProps[0] = surfaceprops.ambient; + surfProps[1] = surfaceprops.specular; + surfProps[2] = surfaceprops.diffuse; + surfProps[3] = extraSurfProp; + setUniform(u_surfProps, surfProps); } void @@ -1101,80 +1089,54 @@ flushCache(void) #ifndef RW_GL_USE_UBOS - // TODO: this is probably a stupid way to do it without UBOs - if(lastShaderUploaded != currentShader){ - lastShaderUploaded = currentShader; - objectDirty = 1; - sceneDirty = 1; - stateDirty = 1; + // what's this doing here?? + uniformState.fogDisable = rwStateCache.fogEnable ? 0.0f : 1.0f; + uniformState.fogStart = rwStateCache.fogStart; + uniformState.fogEnd = rwStateCache.fogEnd; + uniformState.fogRange = 1.0f/(rwStateCache.fogStart - rwStateCache.fogEnd); - int i; - for(i = 0; i < RWGL_NUM_STATES; i++) - uniformStateDirty[i] = true; + if(uniformStateDirty[RWGL_ALPHAFUNC] || uniformStateDirty[RWGL_ALPHAREF]){ + float alphaTest[4]; + switch(alphaFunc){ + case ALPHAALWAYS: + default: + alphaTest[0] = -1000.0f; + alphaTest[1] = 1000.0f; + break; + case ALPHAGREATEREQUAL: + alphaTest[0] = alphaRef; + alphaTest[1] = 1000.0f; + break; + case ALPHALESS: + alphaTest[0] = -1000.0f; + alphaTest[1] = alphaRef; + break; + } + setUniform(u_alphaRef, alphaTest); + uniformStateDirty[RWGL_ALPHAFUNC] = false; + uniformStateDirty[RWGL_ALPHAREF] = false; } - if(sceneDirty){ - glUniformMatrix4fv(U(u_proj), 1, 0, uniformScene.proj); - glUniformMatrix4fv(U(u_view), 1, 0, uniformScene.view); - sceneDirty = 0; + if(uniformStateDirty[RWGL_FOG] || + uniformStateDirty[RWGL_FOGSTART] || + uniformStateDirty[RWGL_FOGEND]){ + float fogData[4] = { + uniformState.fogStart, + uniformState.fogEnd, + uniformState.fogRange, + uniformState.fogDisable + }; + setUniform(u_fogData, fogData); + uniformStateDirty[RWGL_FOG] = false; + uniformStateDirty[RWGL_FOGSTART] = false; + uniformStateDirty[RWGL_FOGEND] = false; } - if(objectDirty){ - glUniformMatrix4fv(U(u_world), 1, 0, (float*)&uniformObject.world); - glUniform4fv(U(u_ambLight), 1, (float*)&uniformObject.ambLight); - glUniform4fv(U(u_lightParams), MAX_LIGHTS, (float*)uniformObject.lightParams); - glUniform4fv(U(u_lightPosition), MAX_LIGHTS, (float*)uniformObject.lightPosition); - glUniform4fv(U(u_lightDirection), MAX_LIGHTS, (float*)uniformObject.lightDirection); - glUniform4fv(U(u_lightColor), MAX_LIGHTS, (float*)uniformObject.lightColor); - objectDirty = 0; + if(uniformStateDirty[RWGL_FOGCOLOR]){ + setUniform(u_fogColor, &uniformState.fogColor); + uniformStateDirty[RWGL_FOGCOLOR] = false; } -// if(stateDirty){ - - uniformState.fogDisable = rwStateCache.fogEnable ? 0.0f : 1.0f; - uniformState.fogStart = rwStateCache.fogStart; - uniformState.fogEnd = rwStateCache.fogEnd; - uniformState.fogRange = 1.0f/(rwStateCache.fogStart - rwStateCache.fogEnd); - - if(uniformStateDirty[RWGL_ALPHAFUNC] || uniformStateDirty[RWGL_ALPHAREF]){ - switch(alphaFunc){ - case ALPHAALWAYS: - default: - glUniform2f(U(u_alphaRef), -1000.0f, 1000.0f); - break; - case ALPHAGREATEREQUAL: - glUniform2f(U(u_alphaRef), alphaRef, 1000.0f); - break; - case ALPHALESS: - glUniform2f(U(u_alphaRef), -1000.0f, alphaRef); - break; - } - uniformStateDirty[RWGL_ALPHAFUNC] = false; - uniformStateDirty[RWGL_ALPHAREF] = false; - } - - if(uniformStateDirty[RWGL_FOG] || - uniformStateDirty[RWGL_FOGSTART] || - uniformStateDirty[RWGL_FOGEND]){ - float fogData[4] = { - uniformState.fogStart, - uniformState.fogEnd, - uniformState.fogRange, - uniformState.fogDisable - }; - glUniform4fv(U(u_fogData), 1, fogData); - uniformStateDirty[RWGL_FOG] = false; - uniformStateDirty[RWGL_FOGSTART] = false; - uniformStateDirty[RWGL_FOGEND] = false; - } - - if(uniformStateDirty[RWGL_FOGCOLOR]){ - glUniform4fv(U(u_fogColor), 1, (float*)&uniformState.fogColor); - uniformStateDirty[RWGL_FOGCOLOR] = false; - } - -// stateDirty = 0; -// } #else if(objectDirty){ glBindBuffer(GL_UNIFORM_BUFFER, ubo_object); @@ -1214,6 +1176,7 @@ flushCache(void) stateDirty = 0; } #endif + flushUniforms(); } static void @@ -1796,29 +1759,25 @@ initOpenGL(void) } #ifndef RW_GL_USE_UBOS - u_alphaRef = registerUniform("u_alphaRef"); - u_fogData = registerUniform("u_fogData"); -// u_fogStart = registerUniform("u_fogStart"); -// u_fogEnd = registerUniform("u_fogEnd"); -// u_fogRange = registerUniform("u_fogRange"); -// u_fogDisable = registerUniform("u_fogDisable"); - u_fogColor = registerUniform("u_fogColor"); - u_proj = registerUniform("u_proj"); - u_view = registerUniform("u_view"); - u_world = registerUniform("u_world"); - u_ambLight = registerUniform("u_ambLight"); - u_lightParams = registerUniform("u_lightParams"); - u_lightPosition = registerUniform("u_lightPosition"); - u_lightDirection = registerUniform("u_lightDirection"); - u_lightColor = registerUniform("u_lightColor"); + u_alphaRef = registerUniform("u_alphaRef", UNIFORM_VEC4); + u_fogData = registerUniform("u_fogData", UNIFORM_VEC4); + u_fogColor = registerUniform("u_fogColor", UNIFORM_VEC4); + u_proj = registerUniform("u_proj", UNIFORM_MAT4); + u_view = registerUniform("u_view", UNIFORM_MAT4); + u_world = registerUniform("u_world", UNIFORM_MAT4); + u_ambLight = registerUniform("u_ambLight", UNIFORM_VEC4); + u_lightParams = registerUniform("u_lightParams", UNIFORM_VEC4, MAX_LIGHTS); + u_lightPosition = registerUniform("u_lightPosition", UNIFORM_VEC4, MAX_LIGHTS); + u_lightDirection = registerUniform("u_lightDirection", UNIFORM_VEC4, MAX_LIGHTS); + u_lightColor = registerUniform("u_lightColor", UNIFORM_VEC4, MAX_LIGHTS); lastShaderUploaded = nil; #else registerBlock("Scene"); registerBlock("Object"); registerBlock("State"); #endif - u_matColor = registerUniform("u_matColor"); - u_surfProps = registerUniform("u_surfProps"); + u_matColor = registerUniform("u_matColor", UNIFORM_VEC4); + u_surfProps = registerUniform("u_surfProps", UNIFORM_VEC4); glClearColor(0.25, 0.25, 0.25, 1.0); diff --git a/src/gl/gl3immed.cpp b/src/gl/gl3immed.cpp index 2a5361d..de2cf7f 100644 --- a/src/gl/gl3immed.cpp +++ b/src/gl/gl3immed.cpp @@ -53,7 +53,7 @@ static int primTypeMap[] = { void openIm2D(void) { - u_xform = registerUniform("u_xform"); + u_xform = registerUniform("u_xform", UNIFORM_VEC4); #include "shaders/im2d_gl.inc" #include "shaders/simple_fs_gl.inc" @@ -120,7 +120,8 @@ im2DSetXform(void) xform[1] = -2.0f/cam->frameBuffer->height; xform[2] = -1.0f; xform[3] = 1.0f; - glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform); + setUniform(u_xform, xform); +// glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform); } void diff --git a/src/gl/gl3matfx.cpp b/src/gl/gl3matfx.cpp index df7cb34..7ffa3da 100644 --- a/src/gl/gl3matfx.cpp +++ b/src/gl/gl3matfx.cpp @@ -24,8 +24,6 @@ namespace gl3 { #ifdef RW_OPENGL -#define U(i) currentShader->uniformLocations[i] - static Shader *envShader; static int32 u_texMatrix; static int32 u_fxparams; @@ -77,7 +75,7 @@ uploadEnvMatrix(Frame *frame) invMtx.pos.set(0.0f, 0.0f, 0.0f); RawMatrix::mult(&envMtx, &invMtx, &normal2texcoord); } - glUniformMatrix4fv(U(u_texMatrix), 1, GL_FALSE, (float*)&envMtx); + setUniform(u_texMatrix, &envMtx); } void @@ -99,18 +97,19 @@ matfxEnvRender(InstanceDataHeader *header, InstanceData *inst, uint32 flags, Mat setMaterial(flags, m->color, m->surfaceProps); - float fxparams[2]; + float fxparams[4]; fxparams[0] = env->coefficient; fxparams[1] = env->fbAlpha ? 0.0f : 1.0f; + fxparams[2] = fxparams[3] = 0.0f; - glUniform2fv(U(u_fxparams), 1, fxparams); + setUniform(u_fxparams, fxparams); static float zero[4]; static float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; // This clamps the vertex color below. With it we can achieve both PC and PS2 style matfx if(MatFX::modulateEnvMap) - glUniform4fv(U(u_colorClamp), 1, zero); + setUniform(u_colorClamp, zero); else - glUniform4fv(U(u_colorClamp), 1, one); + setUniform(u_colorClamp, one); rw::SetRenderState(VERTEXALPHA, 1); rw::SetRenderState(SRCBLEND, BLENDONE); @@ -193,9 +192,9 @@ matfxClose(void *o, int32, int32) void initMatFX(void) { - u_texMatrix = registerUniform("u_texMatrix"); - u_fxparams = registerUniform("u_fxparams"); - u_colorClamp = registerUniform("u_colorClamp"); + u_texMatrix = registerUniform("u_texMatrix", UNIFORM_MAT4); + u_fxparams = registerUniform("u_fxparams", UNIFORM_VEC4); + u_colorClamp = registerUniform("u_colorClamp", UNIFORM_VEC4); Driver::registerPlugin(PLATFORM_GL3, 0, ID_MATFX, matfxOpen, matfxClose); diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index 1b20231..7614171 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -22,6 +22,12 @@ namespace gl3 { UniformRegistry uniformRegistry; static char nameBuffer[(MAX_UNIFORMS + MAX_BLOCKS)*32]; // static because memory system isn't up yet when we register static uint32 nameBufPtr; +static float uniformData[512*4]; // seems enough +static uint32 dataPtr; + +static int uniformTypesize[] = { + 0, 4, 4, 16 +}; static char* shader_strdup(const char *name) @@ -35,7 +41,7 @@ shader_strdup(const char *name) } int32 -registerUniform(const char *name) +registerUniform(const char *name, UniformType type, int32 num) { int i; i = findUniform(name); @@ -45,7 +51,21 @@ registerUniform(const char *name) assert(0 && "no space for uniform"); return -1; } - uniformRegistry.uniformNames[uniformRegistry.numUniforms] = shader_strdup(name); + Uniform *u = &uniformRegistry.uniforms[uniformRegistry.numUniforms]; + u->name = shader_strdup(name); + u->type = type; +// u->dirty = false; + u->serialNum = 0; + if(type == UNIFORM_NA){ + u->num = 0; + u->data = nil; + }else{ + u->num = num; + u->data = &uniformData[dataPtr]; + dataPtr += uniformTypesize[type]*num; + assert(dataPtr <= nelem(uniformData)); + } + return uniformRegistry.numUniforms++; } @@ -54,7 +74,7 @@ findUniform(const char *name) { int i; for(i = 0; i < uniformRegistry.numUniforms; i++) - if(strcmp(name, uniformRegistry.uniformNames[i]) == 0) + if(strcmp(name, uniformRegistry.uniforms[i].name) == 0) return i; return -1; } @@ -82,6 +102,47 @@ findBlock(const char *name) return -1; } +void +setUniform(int32 id, void *data) +{ + Uniform *u = &uniformRegistry.uniforms[id]; + assert(u->type != UNIFORM_NA); + if(memcmp(u->data, data, uniformTypesize[u->type]*u->num * sizeof(float)) != 0){ + memcpy(u->data, data, uniformTypesize[u->type]*u->num * sizeof(float)); + //u->dirty = true; + u->serialNum++; + } +} + +void +flushUniforms(void) +{ + for(int i = 0; i < uniformRegistry.numUniforms; i++){ + int32 loc = currentShader->uniformLocations[i]; + if(loc == -1) + continue; + + Uniform *u = &uniformRegistry.uniforms[i]; +// if(force || u->dirty) + if(currentShader->serialNums[i] != u->serialNum) + switch(u->type){ + case UNIFORM_NA: + break; + case UNIFORM_VEC4: + glUniform4fv(loc, u->num, (GLfloat*)u->data); + break; + case UNIFORM_IVEC4: + glUniform4iv(loc, u->num, (GLint*)u->data); + break; + case UNIFORM_MAT4: + glUniformMatrix4fv(loc, u->num, GL_FALSE, (GLfloat*)u->data); + break; + } + currentShader->serialNums[i] = u->serialNum; + //u->dirty = false; + } +} + Shader *currentShader; static void @@ -238,9 +299,12 @@ Shader::create(const char **vsrc, const char **fsrc) // query uniform locations sh->program = program; sh->uniformLocations = rwNewT(GLint, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER); - for(i = 0; i < uniformRegistry.numUniforms; i++) + sh->serialNums = rwNewT(uint32, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER); + for(i = 0; i < uniformRegistry.numUniforms; i++){ sh->uniformLocations[i] = glGetUniformLocation(program, - uniformRegistry.uniformNames[i]); + uniformRegistry.uniforms[i].name); + sh->serialNums[i] = ~0; // let's hope this means dirty + } // set samplers glUseProgram(program); diff --git a/src/gl/gl3skin.cpp b/src/gl/gl3skin.cpp index d97498a..b2b5831 100644 --- a/src/gl/gl3skin.cpp +++ b/src/gl/gl3skin.cpp @@ -24,8 +24,6 @@ namespace gl3 { #ifdef RW_OPENGL -#define U(i) currentShader->uniformLocations[i] - static Shader *skinShader; static int32 u_boneMatrices; @@ -246,8 +244,7 @@ uploadSkinMatrices(Atomic *a) m++; } } - glUniformMatrix4fv(U(u_boneMatrices), 64, GL_FALSE, - (GLfloat*)skinMatrices); + setUniform(u_boneMatrices, skinMatrices); } void @@ -313,7 +310,7 @@ skinClose(void *o, int32, int32) void initSkin(void) { - u_boneMatrices = registerUniform("u_boneMatrices"); + u_boneMatrices = registerUniform("u_boneMatrices", UNIFORM_MAT4, 64); Driver::registerPlugin(PLATFORM_GL3, 0, ID_SKIN, skinOpen, skinClose); diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index ca732bd..4d32330 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -196,6 +196,8 @@ inline void setMaterial(uint32 flags, const RGBA &color, const SurfaceProperties void setAlphaBlend(bool32 enable); bool32 getAlphaBlend(void); +bool32 getAlphaTest(void); + void bindFramebuffer(uint32 fbo); uint32 bindTexture(uint32 texid); diff --git a/src/gl/rwgl3shader.h b/src/gl/rwgl3shader.h index f9bb632..414f1ac 100644 --- a/src/gl/rwgl3shader.h +++ b/src/gl/rwgl3shader.h @@ -9,20 +9,41 @@ enum { MAX_BLOCKS = 20 }; +enum UniformType +{ + UNIFORM_NA, // managed by the user + UNIFORM_VEC4, + UNIFORM_IVEC4, + UNIFORM_MAT4 +}; + +struct Uniform +{ + char *name; + UniformType type; + //bool dirty; + uint32 serialNum; + int32 num; + void *data; +}; + struct UniformRegistry { int32 numUniforms; - char *uniformNames[MAX_UNIFORMS]; + Uniform uniforms[MAX_UNIFORMS]; int32 numBlocks; char *blockNames[MAX_BLOCKS]; }; -int32 registerUniform(const char *name); +int32 registerUniform(const char *name, UniformType type = UNIFORM_NA, int32 num = 1); int32 findUniform(const char *name); int32 registerBlock(const char *name); int32 findBlock(const char *name); +void setUniform(int32 id, void *data); +void flushUniforms(void); + extern UniformRegistry uniformRegistry; struct Shader @@ -30,6 +51,7 @@ struct Shader GLuint program; // same number of elements as UniformRegistry::numUniforms GLint *uniformLocations; + uint32 *serialNums; static Shader *create(const char **vsrc, const char **fsrc); // static Shader *fromFiles(const char *vs, const char *fs); diff --git a/src/gl/shaders/header.frag b/src/gl/shaders/header.frag index ffe26e3..da58bba 100644 --- a/src/gl/shaders/header.frag +++ b/src/gl/shaders/header.frag @@ -6,7 +6,7 @@ layout(std140) uniform State vec4 u_fogColor; }; #else -uniform vec2 u_alphaRef; +uniform vec4 u_alphaRef; uniform vec4 u_fogData; uniform vec4 u_fogColor; diff --git a/src/gl/shaders/header.vert b/src/gl/shaders/header.vert index 81f86bd..025c2c4 100644 --- a/src/gl/shaders/header.vert +++ b/src/gl/shaders/header.vert @@ -28,7 +28,7 @@ layout(std140) uniform State vec4 u_fogColor; }; #else -uniform vec2 u_alphaRef; +uniform vec4 u_alphaRef; uniform vec4 u_fogData; uniform vec4 u_fogColor; #endif diff --git a/src/gl/shaders/header_fs.inc b/src/gl/shaders/header_fs.inc index 62ef8f2..b028498 100644 --- a/src/gl/shaders/header_fs.inc +++ b/src/gl/shaders/header_fs.inc @@ -7,7 +7,7 @@ const char *header_frag_src = " vec4 u_fogColor;\n" "};\n" "#else\n" -"uniform vec2 u_alphaRef;\n" +"uniform vec4 u_alphaRef;\n" "uniform vec4 u_fogData;\n" "uniform vec4 u_fogColor;\n" diff --git a/src/gl/shaders/header_vs.inc b/src/gl/shaders/header_vs.inc index cd37b25..ec9e505 100644 --- a/src/gl/shaders/header_vs.inc +++ b/src/gl/shaders/header_vs.inc @@ -29,7 +29,7 @@ const char *header_vert_src = " vec4 u_fogColor;\n" "};\n" "#else\n" -"uniform vec2 u_alphaRef;\n" +"uniform vec4 u_alphaRef;\n" "uniform vec4 u_fogData;\n" "uniform vec4 u_fogColor;\n" "#endif\n" diff --git a/src/gl/shaders/matfx_env.frag b/src/gl/shaders/matfx_env.frag index 4164ed1..a8952cc 100644 --- a/src/gl/shaders/matfx_env.frag +++ b/src/gl/shaders/matfx_env.frag @@ -1,7 +1,7 @@ uniform sampler2D tex0; uniform sampler2D tex1; -uniform vec2 u_fxparams; +uniform vec4 u_fxparams; uniform vec4 u_colorClamp; #define shininess (u_fxparams.x) diff --git a/src/gl/shaders/matfx_gl.inc b/src/gl/shaders/matfx_gl.inc index f7296a8..f2de3a2 100644 --- a/src/gl/shaders/matfx_gl.inc +++ b/src/gl/shaders/matfx_gl.inc @@ -31,7 +31,7 @@ const char *matfx_env_frag_src = "uniform sampler2D tex0;\n" "uniform sampler2D tex1;\n" -"uniform vec2 u_fxparams;\n" +"uniform vec4 u_fxparams;\n" "uniform vec4 u_colorClamp;\n" "#define shininess (u_fxparams.x)\n"