Yes, they do allow custom uniforms, but they will also fill out a few standard ones. For example, I'm using Horde3D for a project, and one of the shaders contains the following:
[[VS_GENERAL]]
#include "shaders/shaderSettings.shader"
#include "shaders/utilityLib/vertCommon.glsl"
#ifdef _F01_Skinning
#include "shaders/utilityLib/vertSkinning.glsl"
#endif
uniform mat4 viewProjMat;
uniform vec3 viewerPos;
attribute vec3 vertPos;
attribute vec2 texCoords0;
attribute vec3 normal;
#ifdef _F02_NormalMapping
attribute vec4 tangent;
#endif
varying vec4 pos, vsPos;
varying vec2 texCoords;
#ifdef _F02_NormalMapping
varying mat3 tsbMat;
#else
varying vec3 tsbNormal;
#endif
varying vec4 projCoords;
// texture matrix
uniform vec4 textureMatrixRow0;
uniform vec4 textureMatrixRow1;
uniform vec4 textureMatrixRow2;
uniform vec4 textureMatrixRow3;
And the material:
<Material>
<Shader source="shaders/water.shader" />
<ShaderFlag name="_F01_Skinning" />
<ShaderFlag name="_F02_NormalMapping" />
<ShaderFlag name="_F02_Character" />
<Sampler name="albedoMap" map="/textures/dolphin/dolphin_diffuse_V02.dds" />
<Sampler name="causticMap" map="/textures/caustics/001.dds" />
<Sampler name="normalMap" map="/textures/dolphin/dolphin_normal_V02.dds" />
<Uniform name="textureMatrixRow0" a="0.0" b="0.0" c="0.0" d="0.0" />
<Uniform name="textureMatrixRow1" a="0.0" b="0.0" c="0.0" d="0.0" />
<Uniform name="textureMatrixRow2" a="0.0" b="0.0" c="0.0" d="0.0" />
<Uniform name="textureMatrixRow3" a="0.0" b="0.0" c="0.0" d="0.0" />
<Uniform name="fogColor" a="0.0" b="0.0" c="0.0" d="0.0" />
<Uniform name="texScale" a="1.0" b="0.0" c="0.0" d="0.0" />
</Material>
Here, the viewProjMat
and viewerPos
uniforms are filled by the engine, while the others are defined by the user. It seems like a pretty good solution to me.
Note that you can check which GLSL uniform variables are actually used in a shader program:
// uniforms
GLint max_name_length;
GLint active_count;
GLchar* name;
GLsizei length = 100;
GLenum type;
GLint size;
glGetProgramiv(m_Program, GL_ACTIVE_UNIFORMS, &active_count);
glGetProgramiv(m_Program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_name_length);
name = new GLchar[max_name_length];
for (GLint u = 0; u < active_count; u++)
{
glGetActiveUniform(m_Program, u, max_name_length, &length, &size, &type, name);
GLint handle = glGetUniformLocation(m_Program, name);
LOG_INFO("Uniform - %s (%i)", name, handle);
if (!strncmp(name, "gl_", 3))
{
LOG_TRACE("Using deprecated GLSL: %s", name);
}
else
{
// do something with standard uniforms
}
}
delete [] name;
EDIT:
As a user, you see the following:
// set the fog color uniform
h3dSetResParamF(res, H3DMatRes::UniformElem, 4, H3DMatRes::UnifValueF4, 0, m_FogColor.x);
h3dSetResParamF(res, H3DMatRes::UniformElem, 4, H3DMatRes::UnifValueF4, 1, m_FogColor.y);
h3dSetResParamF(res, H3DMatRes::UniformElem, 4, H3DMatRes::UnifValueF4, 2, m_FogColor.z);
Can't say I agree with the C-style interface, but it works.