]> git.tdb.fi Git - libs/gl.git/blob - source/materials/lighting.cpp
Move lighting calculations to world space
[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("world_zenith_dir", 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(unsigned i=0; i<lights.size(); ++i)
103                 if(lights[i])
104                         lights[i]->update_shader_data(shdata, view_matrix, i);
105 }
106
107
108 DataFile::Loader::ActionMap Lighting::Loader::shared_actions;
109
110 Lighting::Loader::Loader(Lighting &l):
111         CollectionObjectLoader<Lighting>(l, 0)
112 {
113         set_actions(shared_actions);
114 }
115
116 Lighting::Loader::Loader(Lighting &l, Collection &c):
117         CollectionObjectLoader<Lighting>(l, &c)
118 {
119         set_actions(shared_actions);
120 }
121
122 void Lighting::Loader::init_actions()
123 {
124         add("ambient", &Loader::ambient);
125         add("fog_color", &Loader::fog_color);
126         add("fog_density", &Loader::fog_density);
127         add("fog_half_distance", &Loader::fog_half_distance);
128         add("horizon_angle", &Loader::horizon_angle);
129         add("light", &Loader::light);
130         add("light", &Loader::light_inline);
131         add("sky_color", &Loader::sky_color);
132         add("zenith_direction", &Loader::zenith_direction);
133
134         // Deprecated
135         add("light", &Loader::light_inline_index);
136 }
137
138 void Lighting::Loader::ambient(float r, float g, float b)
139 {
140         obj.ambient = Color(r, g, b);
141 }
142
143 void Lighting::Loader::fog_color(float r, float g, float b)
144 {
145         obj.set_fog_color(Color(r, g, b));
146 }
147
148 void Lighting::Loader::fog_density(float d)
149 {
150         obj.set_fog_density(d);
151 }
152
153 void Lighting::Loader::fog_half_distance(float d)
154 {
155         obj.set_fog_half_distance(d);
156 }
157
158 void Lighting::Loader::horizon_angle(float a)
159 {
160         obj.set_horizon_angle(Geometry::Angle<float>::from_degrees(a));
161 }
162
163 void Lighting::Loader::light(const string &name)
164 {
165         obj.attach(get_collection().get<Light>(name));
166 }
167
168 void Lighting::Loader::light_inline()
169 {
170         RefPtr<Light> lgt = new Light;
171         load_sub(*lgt);
172         obj.attach(*lgt);
173         obj.owned_data.push_back(lgt.release());
174 }
175
176 void Lighting::Loader::light_inline_index(unsigned)
177 {
178         light_inline();
179 }
180
181 void Lighting::Loader::sky_color(float r, float g, float b)
182 {
183         obj.set_sky_color(Color(r, g, b));
184 }
185
186 void Lighting::Loader::zenith_direction(float x, float y, float z)
187 {
188         obj.set_zenith_direction(Vector3(x, y, z));
189 }
190
191 } // namespace GL
192 } // namespace Msp