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