Performance optimizations, caching uniforms and bound textures and avoiding uploding them if they're already set.
This commit is contained in:
parent
2cac6e1766
commit
b4e66809cb
|
@ -153,6 +153,7 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader, vector<NodeDistSh
|
||||||
};
|
};
|
||||||
static Light lights[N_LIGHTS];
|
static Light lights[N_LIGHTS];
|
||||||
static Gloom::Shader* s = nullptr; // The currently active shader
|
static Gloom::Shader* s = nullptr; // The currently active shader
|
||||||
|
static Gloom::Shader* prev_s = nullptr; // The last shader to glDrawElements
|
||||||
|
|
||||||
// activate the correct shader
|
// activate the correct shader
|
||||||
Gloom::Shader* node_shader = (node->shader != nullptr)
|
Gloom::Shader* node_shader = (node->shader != nullptr)
|
||||||
|
@ -164,39 +165,49 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader, vector<NodeDistSh
|
||||||
uint i = 0; for (Light l : lights) l.push_to_shader(s, i++);
|
uint i = 0; for (Light l : lights) l.push_to_shader(s, i++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool shader_changed = s == prev_s;
|
||||||
|
#define cache(x) static decltype(node->x) cached_ ## x; if (shader_changed && cached_ ## x != node->x) { cached_ ## x = node->x;
|
||||||
|
#define um4fv(x) cache(x) glUniformMatrix4fv(s->location(#x), 1, GL_FALSE, glm::value_ptr(node->x)); }
|
||||||
|
#define u2fv(x) cache(x) glUniform2fv( s->location(#x), 1, glm::value_ptr(node->x)); }
|
||||||
|
#define u3fv(x) cache(x) glUniform3fv( s->location(#x), 1, glm::value_ptr(node->x)); }
|
||||||
|
#define u1f(x) cache(x) glUniform1f( s->location(#x), node->x); }
|
||||||
|
#define u1ui(x) cache(x) glUniform1ui( s->location(#x), node->x); }
|
||||||
|
#define ubtu(n,i,x) if(node->i) { cache(x) glBindTextureUnit(n, node->x); } }
|
||||||
|
|
||||||
switch(node->nodeType) {
|
switch(node->nodeType) {
|
||||||
case GEOMETRY:
|
case GEOMETRY:
|
||||||
if (transparent_nodes!=nullptr && node->has_transparancy()) {
|
if (transparent_nodes!=nullptr && node->has_transparancy()) {
|
||||||
// defer to sorted pass later on
|
// defer to sorted pass later on
|
||||||
transparent_nodes->emplace_back(node, node_shader, (float)glm::length(vec3(node->MVP*vec4(0,0,0,1))));
|
//transparent_nodes->emplace_back(node, node_shader, glm::length(vec3(node->MVP[3])));
|
||||||
|
//transparent_nodes->push_back({node, node_shader, glm::length(vec3(node->MVP[3]))});
|
||||||
|
transparent_nodes->emplace_back(node, node_shader, glm::length(vec3(node->MVP*vec4(0,0,0,1))));
|
||||||
|
//transparent_nodes->push_back({node, node_shader, glm::length(vec3(node->MVP*vec4(0,0,0,1)))});
|
||||||
}
|
}
|
||||||
else if(node->vertexArrayObjectID != -1) {
|
else if(node->vertexArrayObjectID != -1) {
|
||||||
// load uniforms
|
// load uniforms
|
||||||
glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP));
|
um4fv(MVP); um4fv(MV); um4fv(MVnormal);
|
||||||
glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV));
|
u2fv (uvOffset);
|
||||||
glUniformMatrix4fv(s->location("MVnormal"), 1, GL_FALSE, glm::value_ptr(node->MVnormal));
|
u3fv (diffuse_color);
|
||||||
glUniform2fv(s->location("uvOffset") , 1, glm::value_ptr(node->uvOffset));
|
u3fv (emissive_color);
|
||||||
glUniform3fv(s->location("diffuse_color") , 1, glm::value_ptr(node->diffuse_color));
|
u3fv (specular_color);
|
||||||
glUniform3fv(s->location("emissive_color"), 1, glm::value_ptr(node->emissive_color));
|
u1f (opacity);
|
||||||
glUniform3fv(s->location("specular_color"), 1, glm::value_ptr(node->specular_color));
|
u1f (shininess);
|
||||||
glUniform1f( s->location("opacity"), node->opacity);
|
u1f (reflexiveness);
|
||||||
glUniform1f( s->location("shininess"), node->shininess);
|
u1f (displacementCoefficient);
|
||||||
glUniform1f( s->location("reflexiveness"), node->reflexiveness);
|
u1ui (isTextured);
|
||||||
glUniform1f( s->location("displacementCoefficient"), node->displacementCoefficient);
|
u1ui (isVertexColored);
|
||||||
glUniform1ui(s->location("isTextured"), node->isTextured);
|
u1ui (isNormalMapped);
|
||||||
glUniform1ui(s->location("isVertexColored"), node->isVertexColored);
|
u1ui (isDisplacementMapped);
|
||||||
glUniform1ui(s->location("isNormalMapped"), node->isNormalMapped);
|
u1ui (isReflectionMapped);
|
||||||
glUniform1ui(s->location("isDisplacementMapped"), node->isDisplacementMapped);
|
u1ui (isIlluminated);
|
||||||
glUniform1ui(s->location("isReflectionMapped"), node->isReflectionMapped);
|
u1ui (isInverted);
|
||||||
glUniform1ui(s->location("isIlluminated"), node->isIlluminated);
|
ubtu(0, isTextured , diffuseTextureID);
|
||||||
glUniform1ui(s->location("isInverted"), node->isInverted);
|
ubtu(1, isNormalMapped , normalTextureID);
|
||||||
|
ubtu(2, isDisplacementMapped, displacementTextureID);
|
||||||
if (node->isTextured) glBindTextureUnit(0, node->diffuseTextureID);
|
ubtu(3, isReflectionMapped , reflectionTextureID);
|
||||||
if (node->isNormalMapped) glBindTextureUnit(1, node->normalTextureID);
|
|
||||||
if (node->isDisplacementMapped) glBindTextureUnit(2, node->displacementTextureID);
|
|
||||||
if (node->isReflectionMapped) glBindTextureUnit(3, node->reflectionTextureID);
|
|
||||||
glBindVertexArray(node->vertexArrayObjectID);
|
glBindVertexArray(node->vertexArrayObjectID);
|
||||||
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
|
glDrawElements(GL_TRIANGLES, node->VAOIndexCount, GL_UNSIGNED_INT, nullptr);
|
||||||
|
prev_s = s;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPOT_LIGHT:
|
case SPOT_LIGHT:
|
||||||
|
@ -215,6 +226,14 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader, vector<NodeDistSh
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef um4fv
|
||||||
|
#undef u2fv
|
||||||
|
#undef u3fv
|
||||||
|
#undef u1f
|
||||||
|
#undef u1ui
|
||||||
|
#undef ubtu
|
||||||
|
#undef cache
|
||||||
|
|
||||||
if (do_recursive)
|
if (do_recursive)
|
||||||
for(SceneNode* child : node->children) {
|
for(SceneNode* child : node->children) {
|
||||||
renderNode(child, node_shader, transparent_nodes, true);
|
renderNode(child, node_shader, transparent_nodes, true);
|
||||||
|
@ -238,12 +257,12 @@ void renderFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
||||||
[](NodeDistShader a, NodeDistShader b) {
|
[](NodeDistShader a, NodeDistShader b) {
|
||||||
return a.dist > b.dist;
|
return a.dist > b.dist;
|
||||||
});
|
});
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE); // read only
|
||||||
//glDisable(GL_DEPTH_TEST);
|
//glDisable(GL_DEPTH_TEST);
|
||||||
for (NodeDistShader a : transparent_nodes)
|
for (NodeDistShader a : transparent_nodes)
|
||||||
renderNode(a.node, a.s, nullptr, false);
|
renderNode(a.node, a.s, nullptr, false);
|
||||||
std::cout << transparent_nodes.size() << std::endl;
|
std::cout << transparent_nodes.size() << std::endl;
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE); // read write
|
||||||
//glEnable(GL_DEPTH_TEST);
|
//glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
namespace Gloom
|
namespace Gloom
|
||||||
|
@ -19,17 +20,21 @@ namespace Gloom
|
||||||
public:
|
public:
|
||||||
Shader() { mProgram = glCreateProgram(); }
|
Shader() { mProgram = glCreateProgram(); }
|
||||||
|
|
||||||
// hack?:
|
|
||||||
GLint location(std::string const& name) {
|
|
||||||
return glGetUniformLocation(mProgram, name.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public member functions
|
// Public member functions
|
||||||
void activate() { glUseProgram(mProgram); }
|
void activate() { glUseProgram(mProgram); }
|
||||||
void deactivate() { glUseProgram(0); }
|
void deactivate() { glUseProgram(0); }
|
||||||
GLuint get() { return mProgram; }
|
GLuint get() { return mProgram; }
|
||||||
void destroy() { glDeleteProgram(mProgram); }
|
void destroy() { glDeleteProgram(mProgram); }
|
||||||
|
|
||||||
|
GLint inline location(std::string const& name) {
|
||||||
|
static std::map<std::string, GLint> cache {};
|
||||||
|
auto it = cache.find(name);
|
||||||
|
if (it == cache.end())
|
||||||
|
return cache[name] = glGetUniformLocation(mProgram, name.c_str());
|
||||||
|
return it->second;
|
||||||
|
//return glGetUniformLocation(mProgram, name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
/* Attach a shader to the current shader program */
|
/* Attach a shader to the current shader program */
|
||||||
void attach(std::string const &filename)
|
void attach(std::string const &filename)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue