]> git.tdb.fi Git - libs/gl.git/blob - source/lighting.cpp
ea59a1420945efefcc6c760d28cd9bc13c10a713
[libs/gl.git] / source / lighting.cpp
1 #include <stdexcept>
2 #include <cmath>
3 #include <msp/gl/extensions/msp_legacy_features.h>
4 #include "error.h"
5 #include "light.h"
6 #include "lighting.h"
7 #include "lightunit.h"
8 #include "matrix.h"
9 #include "misc.h"
10
11 using namespace std;
12
13 namespace Msp {
14 namespace GL {
15
16 Lighting::Lighting():
17         ambient(0.2),
18         zenith_direction(0, 0, 1),
19         horizon_angle(Geometry::Angle<float>::zero()),
20         fog_color(0.0f, 0.0f, 0.0f, 0.0f),
21         fog_density(0.0f)
22 { }
23
24 void Lighting::set_ambient(const Color &a)
25 {
26         ambient = a;
27 }
28
29 void Lighting::set_sky_color(const Color &s)
30 {
31         sky_color = s;
32 }
33
34 void Lighting::set_zenith_direction(const Vector3 &d)
35 {
36         zenith_direction = d;
37 }
38
39 void Lighting::set_horizon_angle(const Geometry::Angle<float> &a)
40 {
41         horizon_angle = a;
42 }
43
44 void Lighting::set_fog_color(const Color &c)
45 {
46         fog_color = c;
47 }
48
49 void Lighting::set_fog_density(float d)
50 {
51         if(d<0)
52                 throw invalid_argument("Lighting::set_fog_density");
53
54         fog_density = d;
55 }
56
57 void Lighting::set_fog_half_distance(float d)
58 {
59         set_fog_density(-log(pow(0.5, 1.0/d)));
60 }
61
62 void Lighting::attach(unsigned i, const Light &l)
63 {
64         if(i>=lights.size())
65                 lights.resize(i+1);
66
67         lights[i] = &l;
68         if(current()==this)
69                 l.bind_to(i);
70 }
71
72 void Lighting::detach(unsigned i)
73 {
74         if(i>=lights.size())
75                 return;
76
77         lights[i] = 0;
78         if(current()==this)
79                 Light::unbind_from(i);
80 }
81
82 const Light *Lighting::get_attached_light(unsigned i) const
83 {
84         return i<lights.size() ? lights[i] : 0;
85 }
86
87 void Lighting::update_shader_data(ProgramData &shdata, const Matrix &view_matrix) const
88 {
89         shdata.uniform("ambient_color", ambient);
90         shdata.uniform("sky_color", sky_color);
91         shdata.uniform("eye_zenith_dir", view_matrix.block<3, 3>(0, 0)*zenith_direction);
92         shdata.uniform("horizon_limit", horizon_angle.radians());
93         shdata.uniform("fog_color", fog_color);
94         shdata.uniform("fog_density", fog_density);
95
96         // For backwards compatibility
97         shdata.uniform("eye_sky_dir", view_matrix.block<3, 3>(0, 0)*zenith_direction);
98
99         for(unsigned i=0; i<lights.size(); ++i)
100                 if(lights[i])
101                         lights[i]->update_shader_data(shdata, view_matrix, i);
102 }
103
104 void Lighting::bind() const
105 {
106         static Require _req(MSP_legacy_features);
107         if(lights.size()>LightUnit::get_n_units())
108                 throw invalid_operation("Lighting::bind");
109
110         const Lighting *old = current();
111         if(!set_current(this))
112                 return;
113
114         enable(GL_LIGHTING);
115         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &ambient.r);
116         for(unsigned i=0; i<lights.size(); ++i)
117         {
118                 if(lights[i])
119                         lights[i]->bind_to(i);
120                 else
121                         Light::unbind_from(i);
122         }
123
124         if(old)
125         {
126                 for(unsigned i=lights.size(); i<old->lights.size(); ++i)
127                         Light::unbind_from(i);
128         }
129
130         if(fog_density)
131         {
132                 enable(GL_FOG);
133                 glFogi(GL_FOG_MODE, GL_EXP);
134                 glFogf(GL_FOG_DENSITY, fog_density);
135                 glFogfv(GL_FOG_COLOR, &fog_color.r);
136         }
137 }
138
139 void Lighting::unbind()
140 {
141         const Lighting *old = current();
142         if(!set_current(0))
143                 return;
144
145         for(unsigned i=0; i<old->lights.size(); ++i)
146                 if(old->lights[i])
147                         Light::unbind_from(i);
148
149         disable(GL_LIGHTING);
150         if(old->fog_density)
151                 disable(GL_FOG);
152 }
153
154 } // namespace GL
155 } // namespace Msp