X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flight.cpp;h=a3b3d014c0a51a16762c7a82285f4a6a8960247c;hb=4fe225bf15048fcb7a678370f87d09f2de37031a;hp=39693c4091a6b1579885bf79104ef60e38ca0426;hpb=f14435e58bfa0fa697a06ba9a454bb30cd37d9d8;p=libs%2Fgl.git diff --git a/source/light.cpp b/source/light.cpp index 39693c40..a3b3d014 100644 --- a/source/light.cpp +++ b/source/light.cpp @@ -1,6 +1,11 @@ -#include "except.h" +#include +#include +#include #include "light.h" +#include "lightunit.h" +#include "matrix.h" #include "misc.h" +#include "programdata.h" using namespace std; @@ -8,7 +13,6 @@ namespace Msp { namespace GL { Light::Light(): - ambient(0), diffuse(1), specular(1), position(0, 0, 1, 0), @@ -21,39 +25,78 @@ Light::Light(): attenuation[2] = 0; } -void Light::set_ambient(const Color &c) +Light::~Light() { - ambient = c; + while(LightUnit *unit = LightUnit::find_unit(this)) + unbind_from(unit->get_index()); +} + +void Light::update_parameter(int mask, int index) const +{ + if(index<0) + { + LightUnit *unit = LightUnit::find_unit(this); + if(!unit) + return; + + index = unit->get_index(); + } + + GLenum l = GL_LIGHT0+index; + if(mask&DIFFUSE) + glLightfv(l, GL_DIFFUSE, &diffuse.r); + if(mask&SPECULAR) + glLightfv(l, GL_SPECULAR, &specular.r); + if(mask&POSITION) + glLightfv(l, GL_POSITION, &position.x); + if(mask&SPOT_DIR) + glLightfv(l, GL_SPOT_DIRECTION, &spot_dir.x); + if(mask&SPOT_EXP) + glLightf(l, GL_SPOT_EXPONENT, spot_exp); + if(mask&SPOT_CUTOFF) + glLightf(l, GL_SPOT_CUTOFF, spot_cutoff); + if(mask&ATTENUATION) + { + glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]); + glLightf(l, GL_LINEAR_ATTENUATION, attenuation[1]); + glLightf(l, GL_QUADRATIC_ATTENUATION, attenuation[2]); + } } void Light::set_diffuse(const Color &c) { diffuse = c; + update_parameter(DIFFUSE); } void Light::set_specular(const Color &c) { specular = c; + update_parameter(SPECULAR); } void Light::set_position(const Vector4 &p) { position = p; + update_parameter(POSITION); } void Light::set_spot_direction(const Vector3 &d) { spot_dir = d; + update_parameter(SPOT_DIR); } void Light::set_spot_exponent(float e) { spot_exp = e; + update_parameter(SPOT_EXP); } void Light::set_spot_cutoff(float c) { spot_cutoff = c; + update_parameter(SPOT_CUTOFF); } void Light::set_attenuation(float c, float l, float q) @@ -61,64 +104,40 @@ void Light::set_attenuation(float c, float l, float q) attenuation[0] = c; attenuation[1] = l; attenuation[2] = q; + update_parameter(ATTENUATION); } -void Light::bind() const +void Light::update_shader_data(ProgramData &shdata, const Matrix &view_matrix, unsigned i) const { - if(current_lights[current_unit]!=this) - { - GLenum l = GL_LIGHT0+current_unit; - enable(l); - glLightfv(l, GL_AMBIENT, &ambient.r); - glLightfv(l, GL_DIFFUSE, &diffuse.r); - glLightfv(l, GL_SPECULAR, &specular.r); - glLightfv(l, GL_POSITION, &position.x); - glLightfv(l, GL_SPOT_DIRECTION, &spot_dir.x); - glLightf(l, GL_SPOT_EXPONENT, spot_exp); - glLightf(l, GL_SPOT_CUTOFF, spot_cutoff); - glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]); - glLightf(l, GL_LINEAR_ATTENUATION, attenuation[1]); - glLightf(l, GL_QUADRATIC_ATTENUATION, attenuation[2]); - current_lights[current_unit] = this; - } + string base = format("light_sources[%d]", i); + shdata.uniform(base+".position", view_matrix*position); + shdata.uniform(base+".diffuse", diffuse); + shdata.uniform(base+".specular", specular); } void Light::bind_to(unsigned i) const { - activate(i); - bind(); -} + static Require _req(MSP_legacy_features); -void Light::activate(unsigned i) -{ - static unsigned max_lights = get_i(GL_MAX_LIGHTS); - - if(i>=max_lights) - throw InvalidParameterValue("Light unit index out of range"); - - if(i>=current_lights.size()) - current_lights.resize(i+1); - - current_unit = i; + LightUnit &unit = LightUnit::get_unit(i); + if(unit.set_light(this)) + { + enable(GL_LIGHT0+unit.get_index()); + update_parameter(-1, unit.get_index()); + } } -void Light::unbind() +const Light *Light::current(unsigned i) { - if(current_lights[current_unit]) - { - disable(GL_LIGHT0+current_unit); - current_lights[current_unit] = 0; - } + return LightUnit::get_unit(i).get_light(); } void Light::unbind_from(unsigned i) { - activate(i); - unbind(); + LightUnit &unit = LightUnit::get_unit(i); + if(unit.set_light(0)) + disable(GL_LIGHT0+unit.get_index()); } -unsigned Light::current_unit = 0; -vector Light::current_lights(1); - } // namespace GL } // namespace Msp