]> git.tdb.fi Git - libs/gl.git/blob - source/materials/lighting.cpp
3bbc01a3fa8e4bd4d51fd0fafc924b95651b492d
[libs/gl.git] / source / materials / lighting.cpp
1 #include <stdexcept>
2 #include <cmath>
3 #include <msp/core/algorithm.h>
4 #include "error.h"
5 #include "light.h"
6 #include "lighting.h"
7 #include "matrix.h"
8 #include "misc.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GL {
14
15 Lighting::Lighting():
16         zenith_direction(0, 0, 1),
17         horizon_angle(Geometry::Angle<float>::zero())
18 {
19         set_ambient(0.2f);
20         set_fog_color(Color(0.0f, 0.0f, 0.0f, 0.0f));
21         set_fog_density(0.0f);
22 }
23
24 Lighting::~Lighting()
25 {
26         for(vector<Light *>::iterator i=owned_data.begin(); i!=owned_data.end(); ++i)
27                 delete *i;
28 }
29
30 void Lighting::set_ambient(const Color &a)
31 {
32         ambient = a;
33         shdata.uniform("ambient_color", ambient);
34 }
35
36 void Lighting::set_sky_color(const Color &s)
37 {
38         sky_color = s;
39         shdata.uniform("sky_color", sky_color);
40 }
41
42 void Lighting::set_zenith_direction(const Vector3 &d)
43 {
44         zenith_direction = d;
45         shdata.uniform("world_zenith_dir", zenith_direction);
46 }
47
48 void Lighting::set_horizon_angle(const Geometry::Angle<float> &a)
49 {
50         horizon_angle = a;
51         shdata.uniform("horizon_limit", horizon_angle.radians());
52 }
53
54 void Lighting::set_fog_color(const Color &c)
55 {
56         fog_color = c;
57         shdata.uniform("fog_color", fog_color);
58 }
59
60 void Lighting::set_fog_density(float d)
61 {
62         if(d<0)
63                 throw invalid_argument("Lighting::set_fog_density");
64
65         fog_density = d;
66         shdata.uniform("fog_density", fog_density);
67 }
68
69 void Lighting::set_fog_half_distance(float d)
70 {
71         set_fog_density(-log(pow(0.5, 1.0/d)));
72 }
73
74 void Lighting::attach(const Light &l)
75 {
76         if(find_member(lights, &l, &AttachedLight::light)==lights.end())
77                 lights.push_back(&l);
78 }
79
80 void Lighting::detach(const Light &l)
81 {
82         vector<AttachedLight>::iterator i = find_member(lights, &l, &AttachedLight::light);
83         if(i!=lights.end())
84                 lights.erase(i);
85 }
86
87 void Lighting::detach(unsigned i)
88 {
89         if(i>=lights.size())
90                 return;
91
92         detach(*lights[i].light);
93 }
94
95 const Light *Lighting::get_attached_light(unsigned i) const
96 {
97         return i<lights.size() ? lights[i].light : 0;
98 }
99
100 void Lighting::update_shader_data(ProgramData &sd, const Matrix &) const
101 {
102         sd.uniform("ambient_color", ambient);
103         sd.uniform("sky_color", sky_color);
104         sd.uniform("world_zenith_dir", zenith_direction);
105         sd.uniform("horizon_limit", horizon_angle.radians());
106         sd.uniform("fog_color", fog_color);
107         sd.uniform("fog_density", fog_density);
108
109         for(unsigned i=0; i<lights.size(); ++i)
110                 if(lights[i].light)
111                         lights[i].light->update_shader_data(sd, i);
112 }
113
114 const ProgramData &Lighting::get_shader_data() const
115 {
116         for(unsigned i=0; i<lights.size(); ++i)
117                 if(lights[i].light->get_generation()!=lights[i].generation)
118                 {
119                         lights[i].light->update_shader_data(shdata, i);
120                         lights[i].generation = lights[i].light->get_generation();
121                 }
122
123         return shdata;
124 }
125
126 void Lighting::set_debug_name(const string &name)
127 {
128 #ifdef DEBUG
129         shdata.set_debug_name(name+" [UBO]");
130 #else
131         (void)name;
132 #endif
133 }
134
135
136 DataFile::Loader::ActionMap Lighting::Loader::shared_actions;
137
138 Lighting::Loader::Loader(Lighting &l):
139         CollectionObjectLoader<Lighting>(l, 0)
140 {
141         set_actions(shared_actions);
142 }
143
144 Lighting::Loader::Loader(Lighting &l, Collection &c):
145         CollectionObjectLoader<Lighting>(l, &c)
146 {
147         set_actions(shared_actions);
148 }
149
150 void Lighting::Loader::init_actions()
151 {
152         add("ambient", &Loader::ambient);
153         add("fog_color", &Loader::fog_color);
154         add("fog_density", &Loader::fog_density);
155         add("fog_half_distance", &Loader::fog_half_distance);
156         add("light", &Loader::light);
157         add("light", &Loader::light_inline);
158
159         // Deprecated
160         add("horizon_angle", &Loader::horizon_angle);
161         add("light", &Loader::light_inline_index);
162         add("sky_color", &Loader::sky_color);
163         add("zenith_direction", &Loader::zenith_direction);
164 }
165
166 void Lighting::Loader::ambient(float r, float g, float b)
167 {
168         obj.set_ambient(Color(r, g, b));
169 }
170
171 void Lighting::Loader::fog_color(float r, float g, float b)
172 {
173         obj.set_fog_color(Color(r, g, b));
174 }
175
176 void Lighting::Loader::fog_density(float d)
177 {
178         obj.set_fog_density(d);
179 }
180
181 void Lighting::Loader::fog_half_distance(float d)
182 {
183         obj.set_fog_half_distance(d);
184 }
185
186 #pragma GCC diagnostic push
187 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
188 void Lighting::Loader::horizon_angle(float a)
189 {
190         obj.set_horizon_angle(Geometry::Angle<float>::from_degrees(a));
191 }
192 #pragma GCC diagnostic pop
193
194 void Lighting::Loader::light(const string &name)
195 {
196         obj.attach(get_collection().get<Light>(name));
197 }
198
199 void Lighting::Loader::light_inline()
200 {
201         RefPtr<Light> lgt = new Light;
202         load_sub(*lgt);
203         obj.attach(*lgt);
204         obj.owned_data.push_back(lgt.release());
205 }
206
207 void Lighting::Loader::light_inline_index(unsigned)
208 {
209         light_inline();
210 }
211
212 #pragma GCC diagnostic push
213 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
214 void Lighting::Loader::sky_color(float r, float g, float b)
215 {
216         obj.set_sky_color(Color(r, g, b));
217 }
218
219 void Lighting::Loader::zenith_direction(float x, float y, float z)
220 {
221         obj.set_zenith_direction(Vector3(x, y, z));
222 }
223 #pragma GCC diagnostic pop
224
225 } // namespace GL
226 } // namespace Msp