]> git.tdb.fi Git - libs/gl.git/blob - source/light.cpp
Use uniform blocks in generated shaders if supported
[libs/gl.git] / source / light.cpp
1 #include <stdexcept>
2 #include <msp/strings/format.h>
3 #include "light.h"
4 #include "lightunit.h"
5 #include "matrix.h"
6 #include "misc.h"
7 #include "programdata.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace GL {
13
14 Light::Light():
15         diffuse(1),
16         specular(1),
17         position(0, 0, 1, 0),
18         spot_dir(0, 0, -1),
19         spot_exp(0),
20         spot_cutoff(180)
21 {
22         attenuation[0] = 1;
23         attenuation[1] = 0;
24         attenuation[2] = 0;
25 }
26
27 void Light::update_parameter(int mask, int index) const
28 {
29         if(index<0)
30         {
31                 LightUnit *unit = LightUnit::find_unit(this);
32                 if(!unit)
33                         return;
34
35                 index = unit->get_index();
36         }
37
38         GLenum l = GL_LIGHT0+index;
39         if(mask&DIFFUSE)
40                 glLightfv(l, GL_DIFFUSE, &diffuse.r);
41         if(mask&SPECULAR)
42                 glLightfv(l, GL_SPECULAR, &specular.r);
43         if(mask&POSITION)
44                 glLightfv(l, GL_POSITION, &position.x);
45         if(mask&SPOT_DIR)
46                 glLightfv(l, GL_SPOT_DIRECTION, &spot_dir.x);
47         if(mask&SPOT_EXP)
48                 glLightf(l, GL_SPOT_EXPONENT, spot_exp);
49         if(mask&SPOT_CUTOFF)
50                 glLightf(l, GL_SPOT_CUTOFF, spot_cutoff);
51         if(mask&ATTENUATION)
52         {
53                 glLightf(l, GL_CONSTANT_ATTENUATION, attenuation[0]);
54                 glLightf(l, GL_LINEAR_ATTENUATION, attenuation[1]);
55                 glLightf(l, GL_QUADRATIC_ATTENUATION, attenuation[2]);
56         }
57 }
58
59 void Light::set_diffuse(const Color &c)
60 {
61         diffuse = c;
62         update_parameter(DIFFUSE);
63 }
64
65 void Light::set_specular(const Color &c)
66 {
67         specular = c;
68         update_parameter(SPECULAR);
69 }
70
71 void Light::set_position(const Vector4 &p)
72 {
73         position = p;
74         update_parameter(POSITION);
75 }
76
77 void Light::set_spot_direction(const Vector3 &d)
78 {
79         spot_dir = d;
80         update_parameter(SPOT_DIR);
81 }
82
83 void Light::set_spot_exponent(float e)
84 {
85         spot_exp = e;
86         update_parameter(SPOT_EXP);
87 }
88
89 void Light::set_spot_cutoff(float c)
90 {
91         spot_cutoff = c;
92         update_parameter(SPOT_CUTOFF);
93 }
94
95 void Light::set_attenuation(float c, float l, float q)
96 {
97         attenuation[0] = c;
98         attenuation[1] = l;
99         attenuation[2] = q;
100         update_parameter(ATTENUATION);
101 }
102
103 void Light::update_shader_data(ProgramData &shdata, const Matrix &view_matrix, unsigned i) const
104 {
105         string base = format("light_sources[%d]", i);
106         shdata.uniform(base+".position", view_matrix*position);
107         shdata.uniform(base+".diffuse", diffuse);
108         shdata.uniform(base+".specular", specular);
109 }
110
111 void Light::bind_to(unsigned i) const
112 {
113         LightUnit &unit = LightUnit::get_unit(i);
114         if(unit.set_light(this))
115         {
116                 enable(GL_LIGHT0+unit.get_index());
117                 update_parameter(-1, unit.get_index());
118         }
119 }
120
121 const Light *Light::current(unsigned i)
122 {
123         return LightUnit::get_unit(i).get_light();
124 }
125
126 void Light::unbind_from(unsigned i)
127 {
128         LightUnit &unit = LightUnit::get_unit(i);
129         if(unit.set_light(0))
130                 disable(GL_LIGHT0+unit.get_index());
131 }
132
133 } // namespace GL
134 } // namespace Msp