implement new gl uniform system

This commit is contained in:
aap 2021-02-19 23:32:15 +01:00
parent 8b2caf8f86
commit 276ac82ddf
13 changed files with 190 additions and 146 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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"