attenuation[2] = 0;
}
+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)
attenuation[0] = c;
attenuation[1] = l;
attenuation[2] = q;
+ update_parameter(ATTENUATION);
}
void Light::bind_to(unsigned i) const
LightUnit &unit = LightUnit::get_unit(i);
if(unit.set_light(this))
{
- GLenum l = GL_LIGHT0+unit.get_index();
- enable(l);
- 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]);
+ enable(GL_LIGHT0+unit.get_index());
+ update_parameter(-1, unit.get_index());
}
}
class Light
{
private:
+ enum ParameterMask
+ {
+ DIFFUSE = 1,
+ SPECULAR = 2,
+ POSITION = 4,
+ SPOT_DIR = 8,
+ SPOT_EXP = 16,
+ SPOT_CUTOFF = 32,
+ ATTENUATION = 64
+ };
+
Color diffuse;
Color specular;
Vector4 position;
public:
Light();
+private:
+ void update_parameter(int, int = -1) const;
+
+public:
void set_diffuse(const Color &c);
void set_specular(const Color &c);
const Color &get_diffuse() const { return diffuse; }
lights.resize(i+1);
lights[i] = &l;
+ if(current()==this)
+ l.bind_to(i);
}
void Lighting::detach(unsigned i)
return;
lights[i] = 0;
+ if(current()==this)
+ Light::unbind_from(i);
}
void Lighting::bind() const
return units[n];
}
+LightUnit *LightUnit::find_unit(const Light *l)
+{
+ for(vector<LightUnit>::iterator i=units.begin(); i!=units.end(); ++i)
+ if(i->light==l)
+ return &*i;
+ return 0;
+}
+
} // namespace GL
} // namespace Msp
static unsigned get_n_units();
static LightUnit &get_unit(unsigned i);
+ static LightUnit *find_unit(const Light *);
};
} // namespace GL
shininess(0)
{ }
+void Material::update_parameter(int mask) const
+{
+ if(cur_obj!=this)
+ return;
+
+ if(mask&AMBIENT)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
+ if(mask&DIFFUSE)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
+ if(mask&SPECULAR)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
+ if(mask&EMISSION)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emission.r);
+ if(mask&SHININESS)
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
+}
+
void Material::set_ambient(const Color &a)
{
ambient = a;
+ update_parameter(AMBIENT);
}
void Material::set_diffuse(const Color &d)
{
diffuse = d;
+ update_parameter(DIFFUSE);
}
void Material::set_specular(const Color &s)
{
specular = s;
+ update_parameter(SPECULAR);
}
void Material::set_emission(const Color &e)
{
emission = e;
+ update_parameter(EMISSION);
}
void Material::set_shininess(float s)
{
shininess = s;
+ update_parameter(SHININESS);
}
void Material::bind() const
{
if(set_current(this))
- {
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
- glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emission.r);
- glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
- }
+ update_parameter(-1);
}
};
private:
+ enum ParameterMask
+ {
+ AMBIENT = 1,
+ DIFFUSE = 2,
+ SPECULAR = 4,
+ EMISSION = 8,
+ SHININESS = 16
+ };
+
Color ambient;
Color diffuse;
Color specular;
public:
Material();
+
+private:
+ void update_parameter(int) const;
+
+public:
void set_ambient(const Color &a);
void set_diffuse(const Color &d);
void set_specular(const Color &s);
return pstore;
}
+void PixelStore::update_parameter(int mask) const
+{
+ if(cur_obj!=this)
+ return;
+
+ if(mask&SIZE)
+ {
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height);
+ }
+ if(mask&ORIGIN)
+ {
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
+ glPixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images);
+ }
+ if(mask&ALIGNMENT)
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
void PixelStore::set_canvas_size(unsigned w, unsigned h)
{
row_length = w;
image_height = h;
+ update_parameter(SIZE);
}
void PixelStore::set_origin(unsigned x, unsigned y, unsigned z)
skip_pixels = x;
skip_rows = y;
skip_images = z;
+ update_parameter(ORIGIN);
}
void PixelStore::set_alignment(unsigned a)
{
alignment = a;
+ update_parameter(ALIGNMENT);
}
void PixelStore::bind() const
{
if(set_current(this))
- {
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
- glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height);
- glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels);
- glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows);
- glPixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images);
- glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
- }
+ update_parameter(-1);
}
} // namespace GL
class PixelStore: public BindableWithDefault<PixelStore>
{
private:
+ enum ParameterMask
+ {
+ SIZE,
+ ORIGIN,
+ ALIGNMENT
+ };
+
unsigned row_length;
unsigned image_height;
unsigned skip_pixels;
static PixelStore from_image(const Graphics::Image &);
+private:
+ void update_parameter(int) const;
+
+public:
void set_canvas_size(unsigned, unsigned);
void set_origin(unsigned, unsigned, unsigned);
void set_alignment(unsigned);
return obj;
}
+void TexEnv::update_parameter(int mask) const
+{
+ if(TexUnit::current().get_texenv()!=this)
+ {
+ TexUnit *unit = TexUnit::find_unit(this);
+ if(!unit)
+ return;
+
+ unit->bind();
+ }
+
+ if(mask&MODE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
+ if(mask&COLOR)
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
+}
+
void TexEnv::set_mode(TexEnvMode m)
{
mode = m;
- if(TexUnit::current().get_texenv()==this)
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
+ update_parameter(MODE);
}
void TexEnv::set_color(const Color &c)
{
color = c;
- if(TexUnit::current().get_texenv()==this)
- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
+ update_parameter(COLOR);
}
void TexEnv::bind_to(unsigned i) const
if(unit.set_texenv(this))
{
unit.bind();
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode);
- glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
+ update_parameter(-1);
}
}
class TexEnv
{
private:
+ enum ParameterMask
+ {
+ MODE = 1,
+ COLOR = 2
+ };
+
TexEnvMode mode;
Color color;
static const TexEnv &default_object();
+private:
+ void update_parameter(int) const;
+
+public:
void set_mode(TexEnvMode);
void set_color(const Color &);
TexEnvMode get_mode() const { return mode; }
void Texture::update_parameter(int mask) const
{
- if(TexUnit::current().get_texture()==this)
+ if(TexUnit::current().get_texture()!=this)
{
- if(mask&MIN_FILTER)
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter);
- if(mask&MAG_FILTER)
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filter);
- if(mask&MAX_ANISOTROPY)
- glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
- if(mask&WRAP_S)
- glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap_s);
- if(mask&WRAP_T)
- glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap_t);
- if(mask&WRAP_R)
- glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap_r);
- if(mask&GENERATE_MIPMAP)
- glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, gen_mipmap);
- if(mask&COMPARE)
- glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
- if(mask&COMPARE_FUNC)
- glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, cmp_func);
+ TexUnit *unit = TexUnit::find_unit(this);
+ if(!unit)
+ {
+ dirty_params |= mask;
+ return;
+ }
+
+ unit->bind();
}
- else
- dirty_params |= mask;
+
+ if(mask&MIN_FILTER)
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter);
+ if(mask&MAG_FILTER)
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filter);
+ if(mask&MAX_ANISOTROPY)
+ glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
+ if(mask&WRAP_S)
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap_s);
+ if(mask&WRAP_T)
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap_t);
+ if(mask&WRAP_R)
+ glTexParameteri(target, GL_TEXTURE_WRAP_R, wrap_r);
+ if(mask&GENERATE_MIPMAP)
+ glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, gen_mipmap);
+ if(mask&COMPARE)
+ glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, (compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE));
+ if(mask&COMPARE_FUNC)
+ glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, cmp_func);
}
void Texture::set_min_filter(TextureFilter f)
return *cur_unit;
}
+TexUnit *TexUnit::find_unit(const Texture *tex)
+{
+ for(vector<TexUnit>::iterator i=units.begin(); i!=units.end(); ++i)
+ if(i->texture==tex)
+ return &*i;
+ return 0;
+}
+
+TexUnit *TexUnit::find_unit(const TexEnv *env)
+{
+ for(vector<TexUnit>::iterator i=units.begin(); i!=units.end(); ++i)
+ if(i->texenv==env)
+ return &*i;
+ return 0;
+}
+
} // namespace GL
} // namespace Msp
static unsigned get_n_units();
static TexUnit &get_unit(unsigned);
static TexUnit ¤t();
+ static TexUnit *find_unit(const Texture *);
+ static TexUnit *find_unit(const TexEnv *);
};
} // namespace GL