]> git.tdb.fi Git - libs/gl.git/blob - source/materials/lighting.cpp
113735040ed22ccfa50ea3f71f2448249a857b16
[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+".enabled", 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):
103         CollectionObjectLoader<Lighting>(l, 0)
104 {
105         set_actions(shared_actions);
106 }
107
108 Lighting::Loader::Loader(Lighting &l, Collection &c):
109         CollectionObjectLoader<Lighting>(l, &c)
110 {
111         set_actions(shared_actions);
112 }
113
114 void Lighting::Loader::init_actions()
115 {
116         add("ambient", &Loader::ambient);
117         add("fog_color", &Loader::fog_color);
118         add("fog_density", &Loader::fog_density);
119         add("fog_half_distance", &Loader::fog_half_distance);
120         add("light", &Loader::light);
121         add("light", &Loader::light_inline);
122 }
123
124 void Lighting::Loader::ambient(float r, float g, float b)
125 {
126         obj.set_ambient(Color(r, g, b));
127 }
128
129 void Lighting::Loader::fog_color(float r, float g, float b)
130 {
131         obj.set_fog_color(Color(r, g, b));
132 }
133
134 void Lighting::Loader::fog_density(float d)
135 {
136         obj.set_fog_density(d);
137 }
138
139 void Lighting::Loader::fog_half_distance(float d)
140 {
141         obj.set_fog_half_distance(d);
142 }
143
144 void Lighting::Loader::light(const string &name)
145 {
146         obj.attach(get_collection().get<Light>(name));
147 }
148
149 void Lighting::Loader::light_inline()
150 {
151         RefPtr<Light> lgt = new Light;
152         load_sub(*lgt);
153         get_collection().add(format("%s/%d.light", FS::basename(get_source()), obj.lights.size()), lgt.get());
154         obj.attach(*lgt.release());
155 }
156
157 } // namespace GL
158 } // namespace Msp