ambient(0),
diffuse(1),
specular(1),
- x(0), y(0), z(1), w(0),
- sdx(0), sdy(0), sdz(-1),
+ position(0, 0, 1, 0),
+ spot_dir(0, 0, -1),
spot_exp(0),
spot_cutoff(180)
-{ }
+{
+ attenuation[0]=1;
+ attenuation[1]=0;
+ attenuation[2]=0;
+}
void Light::set_ambient(const Color &c)
{
specular=c;
}
-void Light::set_position(float x_, float y_, float z_, float w_)
+void Light::set_position(const Vector4 &p)
+{
+ position=p;
+}
+
+void Light::set_spot_direction(const Vector3 &d)
+{
+ spot_dir=d;
+}
+
+void Light::set_spot_exponent(float e)
+{
+ spot_exp=e;
+}
+
+void Light::set_spot_cutoff(float c)
+{
+ spot_cutoff=c;
+}
+
+void Light::set_attenuation(float c, float l, float q)
{
- x=x_;
- y=y_;
- z=z_;
- w=w_;
+ attenuation[0]=c;
+ attenuation[1]=l;
+ attenuation[2]=q;
}
void Light::bind() const
glLightfv(l, GL_AMBIENT, &ambient.r);
glLightfv(l, GL_DIFFUSE, &diffuse.r);
glLightfv(l, GL_SPECULAR, &specular.r);
- glLightfv(l, GL_POSITION, &x);
+ 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;
}
}
#include <vector>
#include "color.h"
+#include "vector.h"
namespace Msp {
namespace GL {
Color ambient;
Color diffuse;
Color specular;
- float x, y, z, w;
- float sdx, sdy, sdz;
+ Vector4 position;
+ Vector3 spot_dir;
float spot_exp;
float spot_cutoff;
float attenuation[3];
public:
Light();
+
void set_ambient(const Color &c);
void set_diffuse(const Color &c);
void set_specular(const Color &c);
- void set_position(float, float, float, float);
+ const Color &get_ambient() const { return ambient; }
+ const Color &get_diffuse() const { return diffuse; }
+ const Color &get_specular() const { return specular; }
+
+ void set_position(const Vector4 &);
+ const Vector4 &get_position() const { return position; }
+ void set_spot_direction(const Vector3 &);
+ void set_spot_exponent(float);
+ void set_spot_cutoff(float);
+ const Vector3 &get_spot_direction() const { return spot_dir; }
+ float get_spot_exponent() const { return spot_exp; }
+ float get_spot_cutoff() const { return spot_cutoff; }
+ void set_attenuation(float, float, float);
+ const float *get_attenuation() const { return attenuation; }
+
void bind() const;
void bind_to(unsigned) const;
+ // Deprecated
+ void set_position(float x, float y, float z, float w) { set_position(Vector4(x, y, z, w)); }
+
static void activate(unsigned);
static void unbind();
};
glLoadIdentity();
}
+void load_matrix(const float *matrix)
+{
+ glLoadMatrixf(matrix);
+}
+
+void load_matrix(const double *matrix)
+{
+ glLoadMatrixd(matrix);
+}
+
void mult_matrix(const float *matrix)
{
glMultMatrixf(matrix);
void matrix_mode(MatrixMode);
void load_identity();
+void load_matrix(const float *);
+void load_matrix(const double *);
void mult_matrix(const float *);
void mult_matrix(const double *);
void push_matrix();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
}
for(vector<Effect *>::const_iterator i=effects.begin(); i!=effects.end(); ++i)
+ {
(*i)->prepare();
+ glViewport(0, 0, width, height);
+ }
for(vector<Tag>::const_iterator i=pass_order.begin(); i!=pass_order.end(); ++i)
render(*i);
for(vector<Effect *>::const_iterator i=effects.end(); i--!=effects.begin();)
struct PipelinePass
{
std::vector<Effect *> effects;
- Lighting *lighting;
+ const Lighting *lighting;
PipelinePass();
};
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <cmath>
+#include <cstdlib>
+#include "light.h"
+#include "matrix.h"
+#include "misc.h"
+#include "projection.h"
+#include "scene.h"
+#include "shadowmap.h"
+#include "texunit.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+ShadowMap::ShadowMap(unsigned s, const Scene &c, const Light &l):
+ size(s),
+ scene(c),
+ light(l),
+ radius(1)
+{
+ depth_buf.set_min_filter(LINEAR);
+ depth_buf.storage(DEPTH_COMPONENT, size, size, 0);
+ depth_buf.image(0, DEPTH_COMPONENT, UNSIGNED_BYTE, 0);
+ depth_buf.parameter(GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
+ depth_buf.parameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ depth_buf.parameter(GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ depth_buf.parameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ depth_buf.parameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ fbo.attach(DEPTH_ATTACHMENT, depth_buf, 0);
+ glDrawBuffer(GL_NONE);
+ Framebuffer::unbind();
+ Texture::unbind();
+}
+
+void ShadowMap::set_target(const Vector3 &t, float r)
+{
+ target=t;
+ radius=r;
+}
+
+void ShadowMap::prepare()
+{
+ const Vector4 &lpos=light.get_position();
+ if(lpos.w)
+ throw Exception("Non-directional lights not supported at the moment");
+
+ float matrix[16];
+ if(abs(lpos.z)>=abs(lpos.x) && abs(lpos.z)>=abs(lpos.y))
+ {
+ float d=sqrt(lpos.x*lpos.x+lpos.z*lpos.z);
+ matrix[0]=lpos.z/d;
+ matrix[4]=0;
+ matrix[8]=-lpos.x/d;
+ matrix[1]=-lpos.x*lpos.y/d;
+ matrix[5]=d;
+ matrix[9]=-lpos.z*lpos.y/d;
+ }
+ else
+ {
+ float d=sqrt(lpos.x*lpos.x+lpos.y*lpos.y);
+ matrix[0]=-lpos.y/d;
+ matrix[4]=lpos.x/d;
+ matrix[8]=0;
+ matrix[1]=-lpos.x*lpos.z/d;
+ matrix[5]=-lpos.y*lpos.z/d;
+ matrix[9]=d;
+ }
+
+ matrix[2]=lpos.x;
+ matrix[6]=lpos.y;
+ matrix[10]=lpos.z;
+
+ matrix[12]=-(target.x*matrix[0]+target.y*matrix[4]+target.z*matrix[8]);
+ matrix[13]=-(target.x*matrix[1]+target.y*matrix[5]+target.z*matrix[9]);
+ matrix[14]=-(target.x*matrix[2]+target.y*matrix[6]+target.z*matrix[10]);
+ matrix[3]=0;
+ matrix[7]=0;
+ matrix[11]=0;
+ matrix[15]=1;
+
+ {
+ matrix_mode(PROJECTION);
+ push_matrix();
+ load_identity();
+ ortho(-radius, radius, -radius, radius, -radius, radius);
+ matrix_mode(MODELVIEW);
+ push_matrix();
+ load_matrix(matrix);
+
+ Bind _bind_fbo(fbo);
+ glViewport(0, 0, size, size);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ scene.render();
+
+ matrix_mode(PROJECTION);
+ pop_matrix();
+ matrix_mode(MODELVIEW);
+ pop_matrix();
+ }
+
+ depth_buf.bind_to(3);
+ float diam=radius*2;
+ float s_eq[4]={ matrix[0]/diam, matrix[4]/diam, matrix[8]/diam, matrix[12]/diam+0.5 };
+ float t_eq[4]={ matrix[1]/diam, matrix[5]/diam, matrix[9]/diam, matrix[13]/diam+0.5 };
+ float r_eq[4]={ -matrix[2]/diam, -matrix[6]/diam, -matrix[10]/diam, 0.5-matrix[14]/diam-4.0/size };
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ glTexGenfv(GL_S, GL_EYE_PLANE, s_eq);
+ enable(GL_TEXTURE_GEN_S);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ glTexGenfv(GL_T, GL_EYE_PLANE, t_eq);
+ enable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+ glTexGenfv(GL_R, GL_EYE_PLANE, r_eq);
+ enable(GL_TEXTURE_GEN_R);
+
+ TexUnit::activate(0);
+}
+
+void ShadowMap::cleanup()
+{
+ TexUnit::activate(3);
+ Texture::unbind();
+ disable(GL_TEXTURE_GEN_S);
+ disable(GL_TEXTURE_GEN_T);
+ disable(GL_TEXTURE_GEN_R);
+ TexUnit::activate(0);
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef SHADOWMAP_H_
+#define SHADOWMAP_H_
+
+#include "effect.h"
+#include "framebuffer.h"
+#include "texture2d.h"
+#include "vector.h"
+
+namespace Msp {
+namespace GL {
+
+class Light;
+class Scene;
+
+class ShadowMap: public Effect
+{
+private:
+ unsigned size;
+ const Scene &scene;
+ const Light &light;
+ Framebuffer fbo;
+public:
+ Texture2D depth_buf;
+private:
+ Vector3 target;
+ float radius;
+
+public:
+ ShadowMap(unsigned, const Scene &, const Light &);
+ void set_target(const Vector3 &, float);
+ virtual void prepare();
+ virtual void cleanup();
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_VECTOR_H_
+#define MSP_GL_VECTOR_H_
+
+namespace Msp {
+namespace GL {
+
+struct Vector3
+{
+ float x, y, z;
+
+ Vector3(): x(0), y(0), z(0) { }
+ Vector3(float x_, float y_, float z_): x(x_), y(y_), z(z_) { }
+};
+
+struct Vector4
+{
+ float x, y, z, w;
+
+ Vector4(): x(0), y(0), z(0), w(1) { }
+ Vector4(float x_, float y_, float z_): x(x_), y(y_), z(z_), w(1) { }
+ Vector4(float x_, float y_, float z_, float w_): x(x_), y(y_), z(z_), w(w_) { }
+ Vector4(const Vector3 &v): x(v.x), y(v.y), z(v.z), w(1) { }
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif