]> git.tdb.fi Git - libs/gl.git/blob - source/materials/lighting.cpp
Split the Light class into subclasses by light type
[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 "light.h"
8 #include "lighting.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GL {
14
15 Lighting::Lighting()
16 {
17         set_ambient(0.2f);
18         set_fog_color(Color(0.0f, 0.0f, 0.0f, 0.0f));
19         set_fog_density(0.0f);
20
21         for(unsigned i=0; i<8; ++i)
22         {
23                 string base = format("light_sources[%d]", i);
24                 shdata.uniform(base+".position", Vector4(0, 0, 1, 0));
25                 shdata.uniform(base+".color", 0.0f, 0.0f, 0.0f);
26                 shdata.uniform(base+".type", 0);
27         }
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_fog_color(const Color &c)
37 {
38         fog_color = c;
39         shdata.uniform("fog_color", fog_color);
40 }
41
42 void Lighting::set_fog_density(float d)
43 {
44         if(d<0)
45                 throw invalid_argument("Lighting::set_fog_density");
46
47         fog_density = d;
48         shdata.uniform("fog_density", fog_density);
49 }
50
51 void Lighting::set_fog_half_distance(float d)
52 {
53         set_fog_density(-log(pow(0.5, 1.0/d)));
54 }
55
56 void Lighting::attach(const Light &l)
57 {
58         if(find_member(lights, &l, &AttachedLight::light)==lights.end())
59                 lights.push_back(&l);
60 }
61
62 void Lighting::detach(const Light &l)
63 {
64         auto i = find_member(lights, &l, &AttachedLight::light);
65         if(i!=lights.end())
66         {
67                 lights.erase(i);
68                 shdata.uniform(format("light_sources[%d].enabled", lights.size()), 0);
69         }
70 }
71
72 int Lighting::find_light_index(const Light &l) const
73 {
74         auto i = find_member(lights, &l, &AttachedLight::light);
75         return (i!=lights.end() ? i-lights.begin() : -1);
76 }
77
78 const ProgramData &Lighting::get_shader_data() const
79 {
80         for(unsigned i=0; i<lights.size(); ++i)
81                 if(lights[i].light->get_generation()!=lights[i].generation)
82                 {
83                         lights[i].light->update_shader_data(shdata, i);
84                         lights[i].generation = lights[i].light->get_generation();
85                 }
86
87         return shdata;
88 }
89
90 void Lighting::set_debug_name(const string &name)
91 {
92 #ifdef DEBUG
93         shdata.set_debug_name(name+" [UBO]");
94 #else
95         (void)name;
96 #endif
97 }
98
99
100 DataFile::Loader::ActionMap Lighting::Loader::shared_actions;
101
102 Lighting::Loader::Loader(Lighting &l, Collection &c):
103         CollectionObjectLoader<Lighting>(l, &c)
104 {
105         set_actions(shared_actions);
106 }
107
108 void Lighting::Loader::init_actions()
109 {
110         add("ambient", &Loader::ambient);
111         add("fog_color", &Loader::fog_color);
112         add("fog_density", &Loader::fog_density);
113         add("fog_half_distance", &Loader::fog_half_distance);
114         add("light", &Loader::light);
115         add("light", &Loader::light_inline);
116 }
117
118 void Lighting::Loader::ambient(float r, float g, float b)
119 {
120         obj.set_ambient(Color(r, g, b));
121 }
122
123 void Lighting::Loader::fog_color(float r, float g, float b)
124 {
125         obj.set_fog_color(Color(r, g, b));
126 }
127
128 void Lighting::Loader::fog_density(float d)
129 {
130         obj.set_fog_density(d);
131 }
132
133 void Lighting::Loader::fog_half_distance(float d)
134 {
135         obj.set_fog_half_distance(d);
136 }
137
138 void Lighting::Loader::light(const string &name)
139 {
140         obj.attach(get_collection().get<Light>(name));
141 }
142
143 void Lighting::Loader::light_inline()
144 {
145         Light::GenericLoader ldr(get_collection());
146         load_sub_with(ldr);
147         RefPtr<Light> lgt = ldr.get_object();
148         get_collection().add(format("%s/%d.light", FS::basename(get_source()), obj.lights.size()), lgt.get());
149         obj.attach(*lgt.release());
150 }
151
152 } // namespace GL
153 } // namespace Msp