From 41339bc44d076569c680b2c24c75b30ef1254c1b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sun, 5 Jul 2009 20:32:00 +0000 Subject: [PATCH] Add Vector3 and Vector4 classes Add the rest of Light parameters Make lighting in PipelinePass const Reset viewport after each effect Add load_matrix functions --- source/light.cpp | 47 +++++++++++--- source/light.h | 25 +++++++- source/matrix.cpp | 10 +++ source/matrix.h | 2 + source/pipeline.cpp | 3 + source/pipelinepass.h | 2 +- source/shadowmap.cpp | 138 ++++++++++++++++++++++++++++++++++++++++++ source/shadowmap.h | 45 ++++++++++++++ source/vector.h | 35 +++++++++++ 9 files changed, 294 insertions(+), 13 deletions(-) create mode 100644 source/shadowmap.cpp create mode 100644 source/shadowmap.h create mode 100644 source/vector.h diff --git a/source/light.cpp b/source/light.cpp index 899e22c9..b523fe36 100644 --- a/source/light.cpp +++ b/source/light.cpp @@ -18,11 +18,15 @@ Light::Light(): 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) { @@ -39,12 +43,31 @@ void Light::set_specular(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 @@ -56,7 +79,13 @@ 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; } } diff --git a/source/light.h b/source/light.h index e9b03269..5871ec72 100644 --- a/source/light.h +++ b/source/light.h @@ -10,6 +10,7 @@ Distributed under the LGPL #include #include "color.h" +#include "vector.h" namespace Msp { namespace GL { @@ -20,8 +21,8 @@ private: 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]; @@ -31,13 +32,31 @@ private: 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(); }; diff --git a/source/matrix.cpp b/source/matrix.cpp index 78412180..9af850d2 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -20,6 +20,16 @@ void load_identity() 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); diff --git a/source/matrix.h b/source/matrix.h index 13de6c8f..79d330a3 100644 --- a/source/matrix.h +++ b/source/matrix.h @@ -22,6 +22,8 @@ enum MatrixMode 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(); diff --git a/source/pipeline.cpp b/source/pipeline.cpp index fcfead76..6a9556a6 100644 --- a/source/pipeline.cpp +++ b/source/pipeline.cpp @@ -118,7 +118,10 @@ void Pipeline::render_all() const glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); } for(vector::const_iterator i=effects.begin(); i!=effects.end(); ++i) + { (*i)->prepare(); + glViewport(0, 0, width, height); + } for(vector::const_iterator i=pass_order.begin(); i!=pass_order.end(); ++i) render(*i); for(vector::const_iterator i=effects.end(); i--!=effects.begin();) diff --git a/source/pipelinepass.h b/source/pipelinepass.h index 9f797729..0189c928 100644 --- a/source/pipelinepass.h +++ b/source/pipelinepass.h @@ -19,7 +19,7 @@ class Lighting; struct PipelinePass { std::vector effects; - Lighting *lighting; + const Lighting *lighting; PipelinePass(); }; diff --git a/source/shadowmap.cpp b/source/shadowmap.cpp new file mode 100644 index 00000000..9b27ba08 --- /dev/null +++ b/source/shadowmap.cpp @@ -0,0 +1,138 @@ +/* $Id$ + +This file is part of libmspgl +Copyright © 2009 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include +#include +#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 diff --git a/source/shadowmap.h b/source/shadowmap.h new file mode 100644 index 00000000..17e17ca9 --- /dev/null +++ b/source/shadowmap.h @@ -0,0 +1,45 @@ +/* $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 diff --git a/source/vector.h b/source/vector.h new file mode 100644 index 00000000..d1693af1 --- /dev/null +++ b/source/vector.h @@ -0,0 +1,35 @@ +/* $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 -- 2.45.2