]> git.tdb.fi Git - libs/gl.git/blob - source/lighting.cpp
Some fixes to lighting management
[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         sky_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_sky_direction(const Vector3 &d)
35 {
36         sky_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_sky_dir", view_matrix.block<3, 3>(0, 0)*sky_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(unsigned i=0; i<lights.size(); ++i)
97                 if(lights[i])
98                         lights[i]->update_shader_data(shdata, view_matrix, i);
99 }
100
101 void Lighting::bind() const
102 {
103         static Require _req(MSP_legacy_features);
104         if(lights.size()>LightUnit::get_n_units())
105                 throw invalid_operation("Lighting::bind");
106
107         const Lighting *old = current();
108         if(!set_current(this))
109                 return;
110
111         enable(GL_LIGHTING);
112         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &ambient.r);
113         for(unsigned i=0; i<lights.size(); ++i)
114         {
115                 if(lights[i])
116                         lights[i]->bind_to(i);
117                 else
118                         Light::unbind_from(i);
119         }
120
121         if(old)
122         {
123                 for(unsigned i=lights.size(); i<old->lights.size(); ++i)
124                         Light::unbind_from(i);
125         }
126
127         if(fog_density)
128         {
129                 enable(GL_FOG);
130                 glFogi(GL_FOG_MODE, GL_EXP);
131                 glFogf(GL_FOG_DENSITY, fog_density);
132                 glFogfv(GL_FOG_COLOR, &fog_color.r);
133         }
134 }
135
136 void Lighting::unbind()
137 {
138         const Lighting *old = current();
139         if(!set_current(0))
140                 return;
141
142         for(unsigned i=0; i<old->lights.size(); ++i)
143                 if(old->lights[i])
144                         Light::unbind_from(i);
145
146         disable(GL_LIGHTING);
147         if(old->fog_density)
148                 disable(GL_FOG);
149 }
150
151 } // namespace GL
152 } // namespace Msp