-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaterial.h
183 lines (171 loc) · 5.16 KB
/
material.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#ifndef MATERIAL_H_INCLUDED
#define MATERIAL_H_INCLUDED
#include "image.h"
#include "vector.h"
#include <vector>
#include <functional> // std::hash
using namespace std;
struct Light
{
VectorF direction;
ColorF color;
Light(VectorF direction = VectorF(0), ColorF color = GrayscaleF(1))
: direction(normalizeNoThrow(direction)), color(color)
{
}
ColorF evalLight(VectorF vertexNormal, VectorF /*vertexPosition*/) const
{
float v = dot(direction, vertexNormal);
if(v < 0)
v = 0;
return scaleF(v, color);
}
};
//template <typename ...Args>
//struct LightListLiteral;
struct Material
{
ColorF ambient;
ColorF diffuse;
float opacity;
shared_ptr<Texture> texture;
ColorF evalGlobal(VectorF /*vertexNormal*/, VectorF /*vertexPosition*/) const
{
return ambient;
}
ColorF evalCombine(ColorF retval, ColorF lightVal) const
{
return add(retval, lightVal);
}
ColorF evalFinalize(ColorF retval, ColorF vertexColor) const
{
retval = colorize(vertexColor, setAlphaF(retval, opacity));
retval.r = min(1.0f, retval.r);
retval.g = min(1.0f, retval.g);
retval.b = min(1.0f, retval.b);
return retval;
}
Material(ColorF ambient, ColorF diffuse, float opacity, shared_ptr<Texture> texture = nullptr)
: ambient(ambient), diffuse(diffuse), opacity(opacity), texture(texture)
{
}
Material(ColorF ambient, ColorF diffuse, shared_ptr<Texture> texture = nullptr)
: ambient(ambient), diffuse(diffuse), opacity(diffuse.a), texture(texture)
{
}
// template <typename ...Args>
// ColorF eval(const LightListLiteral<Args...> &lights, ColorF vertexColor, VectorF vertexNormal, VectorF vertexPosition) const
// {
// return evalFinalize(lights.eval(*this, vertexNormal, vertexPosition), vertexColor);
// }
ColorF eval(const vector<Light> &lights, ColorF vertexColor, VectorF vertexNormal, VectorF vertexPosition) const
{
ColorF retval = evalGlobal(vertexNormal, vertexPosition);
for(const Light &light : lights)
{
retval = evalCombine(retval, light.evalLight(vertexNormal, vertexPosition));
}
return evalFinalize(retval, vertexColor);
}
explicit Material(ColorF c, shared_ptr<Texture> texture = nullptr)
: ambient(scaleF(0.35, c)), diffuse(scaleF(0.65, c)), opacity(c.a), texture(texture)
{
}
explicit Material(shared_ptr<Texture> texture = nullptr)
: Material(GrayscaleF(1), texture)
{
}
bool operator ==(const Material &rt) const
{
return ambient == rt.ambient && diffuse == rt.diffuse && opacity == rt.opacity && texture == rt.texture;
}
bool operator !=(const Material &rt) const
{
return !operator ==(rt);
}
};
namespace std
{
template <>
struct hash<Material>
{
private:
hash<float> hash_float;
hash<shared_ptr<Texture>> hash_texture;
public:
size_t operator ()(const Material &m) const
{
size_t retval = hash_float(m.ambient.r);
retval += hash_float(m.ambient.g);
retval += hash_float(m.ambient.b);
retval += hash_float(m.ambient.a);
retval += hash_float(m.diffuse.r);
retval += hash_float(m.diffuse.g);
retval += hash_float(m.diffuse.b);
retval += hash_float(m.diffuse.a);
retval += hash_float(m.opacity);
retval += hash_texture(m.texture);
return retval;
}
};
}
#if 0
template <>
struct LightListLiteral<>
{
constexpr LightListLiteral()
{
}
ColorF eval(const Material &material, VectorF vertexNormal, VectorF vertexPosition) const
{
return material.evalGlobal(vertexNormal, vertexPosition);
}
};
template <typename ...Args>
struct LightListLiteral<Light, Args...>
{
Light first;
LightListLiteral<Args...> rest;
constexpr LightListLiteral(Light first, Args ...rest)
: first(first), rest(rest...)
{
}
ColorF eval(const Material &material, VectorF vertexNormal, VectorF vertexPosition) const
{
return material.evalCombine(rest.eval(material, vertexNormal, vertexPosition), first.evalLight(vertexNormal, vertexPosition));
}
};
#endif
template <typename ...Args>
inline vector<Light> make_light_list(Args ...args)
{
return vector<Light>{args...};
}
template <typename T>
struct LitMaterial
{
Material material;
T lights;
LitMaterial(const Material &material, const T &lights)
: material(material), lights(lights)
{
}
ColorF operator ()(ColorF vertexColor, VectorF vertexNormal, VectorF vertexPosition) const
{
return material.eval(lights, vertexColor, vertexNormal, vertexPosition);
}
void setMaterial(const Material &material)
{
this->material = material;
}
};
template <typename ...Args>
inline LitMaterial<vector<Light>> light_material(const Material &material, Args ...args)
{
return LitMaterial<vector<Light>>(material, make_light_list(args...));
}
inline LitMaterial<vector<Light>> light_material(const Material &material, const vector<Light> &lights)
{
return LitMaterial<vector<Light>>(material, lights);
}
#endif // MATERIAL_H_INCLUDED