Performance optimizations, caching uniforms and bound textures and avoiding uploding them if they're already set.

This commit is contained in:
Peder Bergebakken Sundt 2019-03-22 17:04:23 +01:00
parent 2cac6e1766
commit b4e66809cb
2 changed files with 55 additions and 31 deletions

View File

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

View File

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