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