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.
mtx_stack(*this),
changed(MATRIX),
matrices_loaded(false),
mtx_stack(*this),
changed(MATRIX),
matrices_loaded(false),
camera(c),
state_stack(1),
element_buffer(0)
camera(c),
state_stack(1),
element_buffer(0)
state->shprog = p;
if(p && d)
add_shader_data(*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)
}
void Renderer::add_shader_data(const ProgramData &d)
if(state_stack.size()==1)
throw stack_underflow("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)
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());
shdata_stack.erase(shdata_stack.begin()+state->shdata_count, shdata_stack.end());
+ changed |= SHADER_DATA;
+ }
+ shdata_applied = min<unsigned>(shdata_applied, shdata_stack.size());
- 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()
}
void Renderer::escape()
{
MatrixStack::modelview() = state->lighting_matrix;
state->lighting->bind();
{
MatrixStack::modelview() = state->lighting_matrix;
state->lighting->bind();
- changed = (changed&~LIGHTING)|MATRIX;
+ changed = (changed&~LIGHTING)|LEGACY_MATRIX;
}
else
Lighting::unbind();
}
else
Lighting::unbind();
+ bool shprog_changed = (state->shprog!=Program::current());
state->shprog->bind();
if(!legacy_bindings)
{
state->shprog->bind();
if(!legacy_bindings)
{
- const Matrix &m = mtx_stack.top();
- standard_shdata.uniform("eye_obj_matrix", mtx_stack.top());
- LinAl::SquareMatrix<float, 3> 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<float, 3> 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(state->material)
state->material->get_shader_data().apply();
standard_shdata.apply();
}
- if(changed&SHADER_DATA)
+ if((changed&SHADER_DATA) || shprog_changed)
- for(vector<const ProgramData *>::const_iterator i=shdata_stack.begin(); i!=shdata_stack.end(); ++i)
+ vector<const ProgramData *>::const_iterator i = shdata_stack.begin();
+ if(!shprog_changed)
+ i += shdata_applied;
+ for(; i!=shdata_stack.end(); ++i)
(*i)->apply();
changed &= ~SHADER_DATA;
(*i)->apply();
changed &= ~SHADER_DATA;
+ shdata_applied = shdata_stack.size();
matrices_loaded = true;
}
matrices_loaded = true;
}
+ if(changed&LEGACY_MATRIX)
{
MatrixStack::modelview() = mtx_stack.top();
{
MatrixStack::modelview() = mtx_stack.top();
+ changed &= ~LEGACY_MATRIX;
+ LEGACY_MATRIX = 1,
+ MODERN_MATRIX = 2,
+ MATRIX = LEGACY_MATRIX|MODERN_MATRIX,
LIGHTING = 4,
SHADER_DATA = 8
};
LIGHTING = 4,
SHADER_DATA = 8
};
MtxStack mtx_stack;
unsigned char changed;
bool matrices_loaded;
MtxStack mtx_stack;
unsigned char changed;
bool matrices_loaded;
+ unsigned shdata_applied;
const Camera *camera;
std::vector<State> state_stack;
State *state;
const Camera *camera;
std::vector<State> state_stack;
State *state;