]> git.tdb.fi Git - libs/gl.git/blob - source/materials/lighting.cpp
1f1c66d9b172aa41e7bf3d23674f0646962829d3
[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         ambient(0.2),
17         zenith_direction(0, 0, 1),
18         horizon_angle(Geometry::Angle<float>::zero()),
19         fog_color(0.0f, 0.0f, 0.0f, 0.0f),
20         fog_density(0.0f)
21 { }
22
23 Lighting::~Lighting()
24 {
25         for(vector<Light *>::iterator i=owned_data.begin(); i!=owned_data.end(); ++i)
26                 delete *i;
27 }
28
29 void Lighting::set_ambient(const Color &a)
30 {
31         ambient = a;
32 }
33
34 void Lighting::set_sky_color(const Color &s)
35 {
36         sky_color = s;
37 }
38
39 void Lighting::set_zenith_direction(const Vector3 &d)
40 {
41         zenith_direction = d;
42 }
43
44 void Lighting::set_horizon_angle(const Geometry::Angle<float> &a)
45 {
46         horizon_angle = a;
47 }
48
49 void Lighting::set_fog_color(const Color &c)
50 {
51         fog_color = c;
52 }
53
54 void Lighting::set_fog_density(float d)
55 {
56         if(d<0)
57                 throw invalid_argument("Lighting::set_fog_density");
58
59         fog_density = d;
60 }
61
62 void Lighting::set_fog_half_distance(float d)
63 {
64         set_fog_density(-log(pow(0.5, 1.0/d)));
65 }
66
67 void Lighting::attach(const Light &l)
68 {
69         if(find(lights, &l)==lights.end())
70                 lights.push_back(&l);
71 }
72
73 void Lighting::detach(const Light &l)
74 {
75         vector<const Light *>::iterator i = find(lights, &l);
76         if(i!=lights.end())
77                 lights.erase(i);
78 }
79
80 void Lighting::detach(unsigned i)
81 {
82         if(i>=lights.size())
83                 return;
84
85         detach(*lights[i]);
86 }
87
88 const Light *Lighting::get_attached_light(unsigned i) const
89 {
90         return i<lights.size() ? lights[i] : 0;
91 }
92
93 void Lighting::update_shader_data(ProgramData &shdata, const Matrix &view_matrix) const
94 {
95         shdata.uniform("ambient_color", ambient);
96         shdata.uniform("sky_color", sky_color);
97         shdata.uniform("eye_zenith_dir", view_matrix.block<3, 3>(0, 0)*zenith_direction);
98         shdata.uniform("horizon_limit", horizon_angle.radians());
99         shdata.uniform("fog_color", fog_color);
100         shdata.uniform("fog_density", fog_density);
101
102         // For backwards compatibility
103         shdata.uniform("eye_sky_dir", view_matrix.block<3, 3>(0, 0)*zenith_direction);
104
105         for(unsigned i=0; i<lights.size(); ++i)
106                 if(lights[i])
107                         lights[i]->update_shader_data(shdata, view_matrix, i);
108 }
109
110
111 DataFile::Loader::ActionMap Lighting::Loader::shared_actions;
112
113 Lighting::Loader::Loader(Lighting &l):
114         CollectionObjectLoader<Lighting>(l, 0)
115 {
116         set_actions(shared_actions);
117 }
118
119 Lighting::Loader::Loader(Lighting &l, Collection &c):
120         CollectionObjectLoader<Lighting>(l, &c)
121 {
122         set_actions(shared_actions);
123 }
124
125 void Lighting::Loader::init_actions()
126 {
127         add("ambient", &Loader::ambient);
128         add("fog_color", &Loader::fog_color);
129         add("fog_density", &Loader::fog_density);
130         add("fog_half_distance", &Loader::fog_half_distance);
131         add("horizon_angle", &Loader::horizon_angle);
132         add("light", &Loader::light);
133         add("light", &Loader::light_inline);
134         add("sky_color", &Loader::sky_color);
135         add("zenith_direction", &Loader::zenith_direction);
136
137         // Deprecated
138         add("light", &Loader::light_inline_index);
139 }
140
141 void Lighting::Loader::ambient(float r, float g, float b)
142 {
143         obj.ambient = Color(r, g, b);
144 }
145
146 void Lighting::Loader::fog_color(float r, float g, float b)
147 {
148         obj.set_fog_color(Color(r, g, b));
149 }
150
151 void Lighting::Loader::fog_density(float d)
152 {
153         obj.set_fog_density(d);
154 }
155
156 void Lighting::Loader::fog_half_distance(float d)
157 {
158         obj.set_fog_half_distance(d);
159 }
160
161 void Lighting::Loader::horizon_angle(float a)
162 {
163         obj.set_horizon_angle(Geometry::Angle<float>::from_degrees(a));
164 }
165
166 void Lighting::Loader::light(const string &name)
167 {
168         obj.attach(get_collection().get<Light>(name));
169 }
170
171 void Lighting::Loader::light_inline()
172 {
173         RefPtr<Light> lgt = new Light;
174         load_sub(*lgt);
175         obj.attach(*lgt);
176         obj.owned_data.push_back(lgt.release());
177 }
178
179 void Lighting::Loader::light_inline_index(unsigned)
180 {
181         light_inline();
182 }
183
184 void Lighting::Loader::sky_color(float r, float g, float b)
185 {
186         obj.set_sky_color(Color(r, g, b));
187 }
188
189 void Lighting::Loader::zenith_direction(float x, float y, float z)
190 {
191         obj.set_zenith_direction(Vector3(x, y, z));
192 }
193
194 } // namespace GL
195 } // namespace Msp