Allow auto-add usable uniforms to shader

This commit is contained in:
Benau 2018-01-26 16:02:31 +08:00
parent 9e2d649b55
commit 97fd634ed8
16 changed files with 70 additions and 156 deletions

View File

@ -100,18 +100,11 @@
<shadow-pass use-function="" unuse-function=""
vertex-shader="sp_shadow.vert" fragment-shader="white.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<!--
uniforms: Define the uniforms in shader with the name of the
type (int, float, mat4, vec4, vec3, vec2).
-->
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<!--
uniform-assigners: List of uniform assigners functions to be auto-run
when "use" the shader which set the above uniforms,
currently there are:
when "use" the shader which set the uniform
variables in shader, currently there are:
shadowCascadeUniformAssigner will set the current shadow
cascade being drawn.
@ -127,6 +120,9 @@
You have to specify the uniform name in shader together with the
bundled uniform-assigners.
Currently you can automatically assign to uniform type int, float,
mat4, vec4, vec3 and vec2 only.
-->
<uniform-assigners>
<uniform-assigner name="layer"

View File

@ -7,9 +7,6 @@
<shadow-pass vertex-shader="sp_shadow.vert"
fragment-shader="white.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"

View File

@ -7,9 +7,6 @@
<shadow-pass vertex-shader="sp_shadow.vert"
fragment-shader="sp_shadow_alpha_test.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"

View File

@ -5,9 +5,6 @@
</first-pass>
<shadow-pass vertex-shader="sp_shadow.vert" fragment-shader="white.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"

View File

@ -2,16 +2,9 @@
<shader-info name="grass" use-alpha-channel="Y"/>
<first-pass vertex-shader="sp_grass_pass.vert"
fragment-shader="sp_grass.frag">
<uniforms>
<uniform name="wind_direction" type="vec3"/>
</uniforms>
</first-pass>
<shadow-pass vertex-shader="sp_grass_shadow.vert"
fragment-shader="sp_shadow_alpha_test.frag">
<uniforms>
<uniform name="wind_direction" type="vec3"/>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"

View File

@ -6,9 +6,6 @@
<shadow-pass vertex-shader="sp_shadow.vert"
fragment-shader="sp_shadow_alpha_test.frag"
skinned-mesh-shader="sp_skinning_shadow.vert">
<uniforms>
<uniform name="layer" type="int"/>
</uniforms>
</shadow-pass>
<uniform-assigners>
<uniform-assigner name="layer"

View File

@ -3,10 +3,6 @@
<first-pass use-function="alphaBlendUse" vertex-shader="sp_pass.vert"
fragment-shader="sp_transparent.frag"
skinned-mesh-shader="sp_skinning.vert">
<uniforms>
<uniform name="fog_enabled" type="int"/>
<uniform name="custom_alpha" type="float"/>
</uniforms>
</first-pass>
<uniform-assigners>
<uniform-assigner name="fog_enabled"

View File

@ -3,10 +3,6 @@
<first-pass use-function="additiveUse" vertex-shader="sp_pass.vert"
fragment-shader="sp_transparent.frag"
skinned-mesh-shader="sp_skinning.vert">
<uniforms>
<uniform name="fog_enabled" type="int"/>
<uniform name="custom_alpha" type="float"/>
</uniforms>
</first-pass>
<uniform-assigners>
<uniform-assigner name="fog_enabled"

View File

@ -3,9 +3,6 @@
<first-pass use-function="ghostUse" vertex-shader="sp_pass.vert"
fragment-shader="sp_ghost.frag"
skinned-mesh-shader="sp_skinning.vert">
<uniforms>
<uniform name="custom_alpha" type="float"/>
</uniforms>
</first-pass>
<uniform-assigners>
<uniform-assigner name="custom_alpha"

View File

@ -1134,7 +1134,8 @@ void PostProcessing::renderGodRays(scene::ICameraSceneNode * const camnode,
SP::SPUniformAssigner* glow_color_assigner = glow_shader
->getUniformAssigner("col");
assert(glow_color_assigner != NULL);
glow_color_assigner->setValue(video::SColorf(track->getGodRaysColor()));
video::SColorf cf(track->getGodRaysColor());
glow_color_assigner->setValue(core::vector3df(cf.r, cf.g, cf.b));
sun->draw();
glow_shader->unuse();
glDisable(GL_DEPTH_TEST);

View File

@ -83,7 +83,7 @@ std::vector<std::pair<SPShader*, std::vector<std::pair<std::array<GLuint, 6>,
std::vector<std::pair<SPMeshBuffer*, int/*material_id*/> > > > > >
g_final_draw_calls[DCT_FOR_VAO];
// ----------------------------------------------------------------------------
std::unordered_map<unsigned, std::pair<video::SColorf,
std::unordered_map<unsigned, std::pair<core::vector3df,
std::unordered_set<SPMeshBuffer*> > > g_glow_meshes;
// ----------------------------------------------------------------------------
std::unordered_set<SPMeshBuffer*> g_instances;
@ -186,7 +186,7 @@ void displaceShaderInit(SPShader* shader)
shader->linkShaderFiles(RP_RESERVED);
shader->use(RP_RESERVED);
shader->addBasicUniforms(RP_RESERVED);
shader->addUniform("direction", typeid(std::array<float, 4>), RP_RESERVED);
shader->addAllUniforms(RP_RESERVED);
shader->setUseFunction([]()->void
{
glEnable(GL_DEPTH_TEST);
@ -357,7 +357,7 @@ void loadShaders()
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
shader->addUniform("col", typeid(irr::video::SColorf), RP_1ST);
shader->addAllUniforms(RP_1ST);
});
SPShaderManager::get()->addSPShader(sps->getName(), sps);
g_glow_shader = sps.get();
@ -928,7 +928,8 @@ void addObject(SPMeshNode* node)
auto ret = g_glow_meshes.find(key);
if (ret == g_glow_meshes.end())
{
g_glow_meshes[key] = std::make_pair(gc,
g_glow_meshes[key] = std::make_pair(
core::vector3df(gc.r, gc.g, gc.b),
std::unordered_set<SPMeshBuffer*>());
}
g_glow_meshes.at(key).second.insert(mb);

View File

@ -24,9 +24,11 @@
#include "guiengine/message_queue.hpp"
#include "utils/string_utils.hpp"
#include <map>
namespace SP
{
std::unordered_map<std::string, std::pair<unsigned, SamplerType> >
const std::map<std::string, std::pair<unsigned, SamplerType> >
g_prefilled_names =
{
#ifdef USE_GLES2
@ -203,20 +205,49 @@ void SPShader::bindTextures(const std::array<GLuint, 6>& tex,
} // bindTextures
// ----------------------------------------------------------------------------
void SPShader::addUniform(const std::string& name, const std::type_index& ti,
RenderPass rp)
void SPShader::addAllUniforms(RenderPass rp)
{
#ifndef SERVER_ONLY
const char* s = name.c_str();
GLuint location = glGetUniformLocation(m_program[rp], s);
if (location == GL_INVALID_INDEX)
GLint total_uniforms;
glGetProgramiv(m_program[rp], GL_ACTIVE_UNIFORMS, &total_uniforms);
static const std::map<GLenum, std::type_index> supported_types =
{
{ GL_INT, std::type_index(typeid(int)) },
{ GL_FLOAT, std::type_index(typeid(float)) },
{ GL_FLOAT_MAT4, std::type_index(typeid(irr::core::matrix4)) },
{ GL_FLOAT_VEC4, std::type_index(typeid(std::array<float, 4>)) },
{ GL_FLOAT_VEC3, std::type_index(typeid(irr::core::vector3df)) },
{ GL_FLOAT_VEC2, std::type_index(typeid(irr::core::vector2df)) }
};
for (int i = 0; i < total_uniforms; i++)
{
Log::warn("SPShader", "Missing uniform %s in shader files.", s);
return;
GLint size;
GLenum type;
char name[100] = {};
glGetActiveUniform(m_program[rp], i, 99, NULL, &size, &type, name);
if (size != 1)
{
Log::debug("SPShader", "Array of uniforms is not supported in"
" shader %s for %s.", m_name.c_str(), name);
continue;
}
auto ret = supported_types.find(type);
if (ret == supported_types.end())
{
Log::debug("SPShader", "%d type not supported", (unsigned)type);
continue;
}
GLuint location = glGetUniformLocation(m_program[rp], name);
if (location == GL_INVALID_INDEX)
{
Log::debug("SPShader", "%s uniform not found", name);
continue;
}
m_uniforms[rp][name] = new SPUniformAssigner(ret->second, location);
}
m_uniforms[rp][name] = new SPUniformAssigner(ti, location);
#endif
} // addUniform
} // addAllUniforms
// ----------------------------------------------------------------------------
void SPShader::setUniformsPerObject(SPPerObjectUniform* sppou,

View File

@ -161,6 +161,8 @@ public:
// ------------------------------------------------------------------------
void addAllTextures(RenderPass rp = RP_1ST);
// ------------------------------------------------------------------------
void addAllUniforms(RenderPass rp = RP_1ST);
// ------------------------------------------------------------------------
void addCustomPrefilledTextures(SamplerType st, GLuint texture_type,
const std::string& name,
std::function<GLuint()> func,
@ -190,9 +192,6 @@ public:
SPUniformAssigner* getUniformAssigner(const std::string& name,
RenderPass rp = RP_1ST) const;
// ------------------------------------------------------------------------
void addUniform(const std::string& name, const std::type_index& ti,
RenderPass rp = RP_1ST);
// ------------------------------------------------------------------------
void setUniformsPerObject(SPPerObjectUniform* sppou,
std::vector<SPUniformAssigner*>* ua_used,
RenderPass rp = RP_1ST);

View File

@ -37,16 +37,6 @@ SPShaderManager* SPShaderManager::m_spsm = NULL;
SPShaderManager::SPShaderManager()
{
#ifndef SERVER_ONLY
m_official_types =
{
{ "int", std::type_index(typeid(int)) },
{ "float", std::type_index(typeid(float)) },
{ "mat4", std::type_index(typeid(irr::core::matrix4)) },
{ "vec4", std::type_index(typeid(std::array<float, 4>)) },
{ "vec3", std::type_index(typeid(irr::core::vector3df)) },
{ "vec2", std::type_index(typeid(irr::core::vector2df)) }
};
m_official_sampler_types =
{
{ "nearest", ST_NEAREST },
@ -313,32 +303,6 @@ void SPShaderManager::loadPassInfo(const XMLNode* pass, PassInfo& pi)
pass->get("skinned-mesh-shader", &pi.m_skinned_mesh_shader);
pi.m_skinned_mesh_shader = getShaderFullPath(pi.m_skinned_mesh_shader);
const XMLNode* uniforms = pass->getNode("uniforms");
if (uniforms)
{
for (unsigned i = 0; i < uniforms->getNumNodes(); i++)
{
const XMLNode* uniform = uniforms->getNode(i);
if (uniform->getName() == "uniform")
{
std::string name, type;
uniform->get("name", &name);
uniform->get("type", &type);
if (!name.empty() && !type.empty() &&
m_official_types.find(type) != m_official_types.end())
{
pi.m_uniforms.emplace_back(name,
m_official_types.at(type));
}
else
{
Log::error("SPShaderManager", "Invalid uniform type %s",
type.c_str());
}
}
}
}
const XMLNode* prefilled_textures = pass->getNode("prefilled-textures");
if (prefilled_textures)
{
@ -431,7 +395,7 @@ std::shared_ptr<SPShader> SPShaderManager::buildSPShader(const ShaderInfo& si,
shader->linkShaderFiles(RP_1ST);
shader->use(RP_1ST);
shader->addBasicUniforms(RP_1ST);
addUniformsToShader(shader, pi[0].m_uniforms, RP_1ST);
shader->addAllUniforms(RP_1ST);
if (pi[0].m_use_function)
{
shader->setUseFunction(pi[0].m_use_function, RP_1ST);
@ -466,7 +430,7 @@ std::shared_ptr<SPShader> SPShaderManager::buildSPShader(const ShaderInfo& si,
shader->linkShaderFiles(RP_SHADOW);
shader->use(RP_SHADOW);
shader->addBasicUniforms(RP_SHADOW);
addUniformsToShader(shader, pi[1].m_uniforms, RP_SHADOW);
shader->addAllUniforms(RP_SHADOW);
if (pi[1].m_use_function)
{
shader->setUseFunction(pi[1].m_use_function, RP_SHADOW);
@ -484,17 +448,6 @@ std::shared_ptr<SPShader> SPShaderManager::buildSPShader(const ShaderInfo& si,
return sps;
} // buildSPShader
// ----------------------------------------------------------------------------
void SPShaderManager::addUniformsToShader(SPShader* s,
const std::vector<std::pair<std::string, std::type_index> >& u,
RenderPass rp)
{
for (auto& p : u)
{
s->addUniform(p.first, p.second, rp);
}
} // addUniformsToShader
// ----------------------------------------------------------------------------
void SPShaderManager::addPrefilledTexturesToShader(SPShader* s,
const std::vector<std::tuple<std::string, std::string, bool, SamplerType> >

View File

@ -41,7 +41,6 @@ enum RenderPass: unsigned int;
class SPShaderManager : public NoCopy
{
public:
struct PassInfo
{
std::function<void()> m_use_function;
@ -54,8 +53,6 @@ public:
std::string m_skinned_mesh_shader;
std::vector<std::pair<std::string, std::type_index> > m_uniforms;
std::vector<std::tuple<std::string, std::string, bool, SamplerType> >
m_prefilled_textures;
};
@ -87,8 +84,6 @@ private:
std::vector<std::shared_ptr<SPShader> > m_official_shaders;
std::unordered_map<std::string, std::type_index> m_official_types;
std::unordered_map<std::string, SamplerType> m_official_sampler_types;
std::unordered_map<std::string, std::function<void(SPUniformAssigner*)> >
@ -114,10 +109,6 @@ private:
const UniformAssigners& ua,
bool skinned);
// ------------------------------------------------------------------------
static void addUniformsToShader(SPShader* s,
const std::vector<std::pair<std::string, std::type_index> >& u,
RenderPass rp);
// ------------------------------------------------------------------------
static void addPrefilledTexturesToShader(SPShader* s,
const std::vector<std::tuple<std::string, std::string, bool,
SamplerType> >& t, RenderPass rp);

View File

@ -84,17 +84,6 @@ public:
#ifndef SERVER_ONLY
glUniform4f(m_location, v[0], v[1], v[2], v[3]);
m_assigned = true;
#endif
}
}
// ------------------------------------------------------------------------
void setValue(const irr::video::SColorf& col) const
{
if (rumtimeChecking(typeid(col)))
{
#ifndef SERVER_ONLY
glUniform3f(m_location, col.r, col.g, col.b);
m_assigned = true;
#endif
}
}
@ -117,17 +106,6 @@ public:
#ifndef SERVER_ONLY
glUniform2f(m_location, v.X, v.Y);
m_assigned = true;
#endif
}
}
// ------------------------------------------------------------------------
void setValue(const irr::core::dimension2df& v) const
{
if (rumtimeChecking(typeid(v)))
{
#ifndef SERVER_ONLY
glUniform2f(m_location, v.Width, v.Height);
m_assigned = true;
#endif
}
}
@ -160,37 +138,31 @@ public:
{
m_assigned = false;
#ifndef SERVER_ONLY
if (m_type == typeid(irr::core::matrix4))
if (m_type == typeid(int))
{
static const char zeroes[64] = {};
glUniformMatrix4fv(m_location, 1, GL_FALSE, (float*)zeroes);
}
else if (m_type == typeid(irr::video::SColor))
{
glUniform4i(m_location, 0, 0, 0, 0);
}
else if (m_type == typeid(irr::video::SColorf) ||
m_type == typeid(irr::core::vector3df))
{
glUniform3f(m_location, 0.0f, 0.0f, 0.0f);
}
else if (m_type == typeid(irr::core::vector2df) ||
m_type == typeid(irr::core::dimension2df))
{
glUniform2f(m_location, 0.0f, 0.0f);
glUniform1i(m_location, 0);
}
else if (m_type == typeid(float))
{
glUniform1f(m_location, 0.0f);
}
else if (m_type == typeid(int))
else if (m_type == typeid(irr::core::matrix4))
{
glUniform1i(m_location, 0);
static const char zeroes[64] = {};
glUniformMatrix4fv(m_location, 1, GL_FALSE, (float*)zeroes);
}
else if (m_type == typeid(std::array<float, 4>))
{
glUniform4f(m_location, 0.0f, 0.0f, 0.0f,0.0f);
}
else if (m_type == typeid(irr::core::vector3df))
{
glUniform3f(m_location, 0.0f, 0.0f, 0.0f);
}
else if (m_type == typeid(irr::core::vector2df))
{
glUniform2f(m_location, 0.0f, 0.0f);
}
#endif
}
}