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