From: Mikko Rasa Date: Thu, 30 Oct 2014 08:21:18 +0000 (+0200) Subject: State management improvements in Renderer X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=d41ec7dfaa635bbaea9e902d5f5c60bd4a887891;p=libs%2Fgl.git State management improvements in Renderer Only update modelview matrix in standard_shdata if it actually changed. Don't re-apply all shader data unless the program changed. React to lighting changes caused by pop_state. --- diff --git a/source/renderer.cpp b/source/renderer.cpp index 54d12051..2f253e2a 100644 --- a/source/renderer.cpp +++ b/source/renderer.cpp @@ -24,6 +24,7 @@ Renderer::Renderer(const Camera *c): mtx_stack(*this), changed(MATRIX), matrices_loaded(false), + shdata_applied(0), camera(c), state_stack(1), element_buffer(0) @@ -85,10 +86,6 @@ void Renderer::set_shader_program(const Program *p, const ProgramData *d) state->shprog = p; if(p && d) add_shader_data(*d); - - /* Even if we have no new shdata, the existing ones need to be re-applied - to the new program */ - shdata_changed = true; } void Renderer::add_shader_data(const ProgramData &d) @@ -130,12 +127,23 @@ void Renderer::pop_state() if(state_stack.size()==1) throw stack_underflow("Renderer::pop_state"); + const Lighting *old_lighting = state->lighting; state_stack.pop_back(); state = &state_stack.back(); if(shdata_stack.size()>state->shdata_count) + { shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end()); + changed |= SHADER_DATA; + } + shdata_applied = min(shdata_applied, shdata_stack.size()); mtx_stack.pop(); - changed |= MATRIX|SHADER_DATA; + changed |= MATRIX; + if(state->lighting!=old_lighting) + { + if(state->lighting) + state->lighting->update_shader_data(standard_shdata, state->lighting_matrix); + changed |= LIGHTING; + } } void Renderer::escape() @@ -233,7 +241,7 @@ void Renderer::apply_state() { MatrixStack::modelview() = state->lighting_matrix; state->lighting->bind(); - changed = (changed&~LIGHTING)|MATRIX; + changed = (changed&~LIGHTING)|LEGACY_MATRIX; } else Lighting::unbind(); @@ -242,28 +250,38 @@ void Renderer::apply_state() if(state->shprog) { + bool shprog_changed = (state->shprog!=Program::current()); state->shprog->bind(); if(!legacy_bindings) { - const Matrix &m = mtx_stack.top(); - standard_shdata.uniform("eye_obj_matrix", mtx_stack.top()); - LinAl::SquareMatrix nm; - for(unsigned i=0; i<3; ++i) - for(unsigned j=0; j<3; ++j) - nm(i, j) = m(i, j); - nm = transpose(invert(nm)); - standard_shdata.uniform_matrix3("eye_obj_normal_matrix", &nm(0, 0)); + if(changed&MODERN_MATRIX) + { + const Matrix &m = mtx_stack.top(); + standard_shdata.uniform("eye_obj_matrix", mtx_stack.top()); + LinAl::SquareMatrix nm; + for(unsigned i=0; i<3; ++i) + for(unsigned j=0; j<3; ++j) + nm(i, j) = m(i, j); + nm = transpose(invert(nm)); + standard_shdata.uniform_matrix3("eye_obj_normal_matrix", &nm(0, 0)); + changed &= ~MODERN_MATRIX; + } + if(state->material) state->material->get_shader_data().apply(); standard_shdata.apply(); } - if(changed&SHADER_DATA) + if((changed&SHADER_DATA) || shprog_changed) { - for(vector::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i) + vector::const_iterator i = shdata_stack.begin(); + if(!shprog_changed) + i += shdata_applied; + for(; i!=shdata_stack.end(); ++i) (*i)->apply(); changed &= ~SHADER_DATA; + shdata_applied = shdata_stack.size(); } } else @@ -305,10 +323,10 @@ void Renderer::apply_state() matrices_loaded = true; } - if(changed&MATRIX) + if(changed&LEGACY_MATRIX) { MatrixStack::modelview() = mtx_stack.top(); - changed &= ~MATRIX; + changed &= ~LEGACY_MATRIX; } } } diff --git a/source/renderer.h b/source/renderer.h index a3ddaa3b..dd946412 100644 --- a/source/renderer.h +++ b/source/renderer.h @@ -91,7 +91,9 @@ private: enum ChangeMask { - MATRIX = 1, + LEGACY_MATRIX = 1, + MODERN_MATRIX = 2, + MATRIX = LEGACY_MATRIX|MODERN_MATRIX, LIGHTING = 4, SHADER_DATA = 8 }; @@ -99,6 +101,7 @@ private: MtxStack mtx_stack; unsigned char changed; bool matrices_loaded; + unsigned shdata_applied; const Camera *camera; std::vector state_stack; State *state;