gKit2 light
Loading...
Searching...
No Matches
envmap.h
1
2#ifndef _ENVMAP_H
3#define _ENVMAP_H
4
5#include <array>
6
7#include "vec.h"
8#include "color.h"
9#include "image.h"
10
12struct Envmap
13{
14 Envmap( ) : m_faces(), m_width(0) {}
15
16 Envmap( const int size ) : m_faces(), m_width(size)
17 {
18 for(int i= 0; i < 6; i++)
19 m_faces[i]= Image(size, size);
20 }
21
23 Envmap( const Image& image ) : m_faces(), m_width(0)
24 {
25 int w= image.width() / 4;
26 int h= image.height() / 3;
27 if(w != h)
28 return;
29
30 m_width= w;
31
32 // chaque face de la cubemap est un carre [image.width/4 x image.height/3] dans l'image originale
33 struct { int x, y; } faces[]= {
34 {0, 1}, // X+
35 {2, 1}, // X-
36 {1, 2}, // Y+
37 {1, 0}, // Y-
38 {1, 1}, // Z+
39 {3, 1}, // Z-
40 };
41
42 for(int i= 0; i < 6; i++)
43 m_faces[i]= flipX(flipY(copy(image, faces[i].x*w, faces[i].y*h, w, h)));
44 }
45
47 Envmap( const std::array<Image, 6>& faces ) : m_faces()
48 {
49 for(int i= 0; i < 6; i++)
50 m_faces[i]= flipX(flipY(faces[i]));
51
52 m_width= m_faces[0].width();
53 for(int i= 0; i < 6; i++)
54 if(m_width != m_faces[i].width() || m_width != m_faces[i].height())
55 m_width= 0;
56 }
57
58 int width( ) const { return m_width; }
59 int height( ) const { return m_width; }
60 bool empty() const { return m_width == 0; }
61
63 void linear( const float gamma = 2.2f )
64 {
65 for(int i= 0; i < 6; i++)
66 for(int p= 0; p < int(m_faces[i].size()); p++)
67 {
68 Color pixel= m_faces[i](p);
69 m_faces[i](p)= Color(std::pow(pixel.r, gamma), std::pow(pixel.g, gamma), std::pow(pixel.b, gamma));
70 }
71 }
72
74 void gamma( const float gamma = 2.2f )
75 {
76 for(int i= 0; i < 6; i++)
77 for(int p= 0; p < int(m_faces[i].size()); p++)
78 {
79 Color pixel= m_faces[i](p);
80 m_faces[i](p)= Color(std::pow(pixel.r, 1 / gamma), std::pow(pixel.g, 1 / gamma), std::pow(pixel.b, 1 / gamma));
81 }
82 }
83
85 Image cross( ) const
86 {
87 if(empty())
88 return Image();
89
90 // chaque face de la cubemap est un carre [image.width/4 x image.height/3] dans l'image originale
91 struct { int x, y; } faces[]= {
92 {0, 1}, // X+
93 {2, 1}, // X-
94 {1, 2}, // Y+
95 {1, 0}, // Y-
96 {1, 1}, // Z+
97 {3, 1}, // Z-
98 };
99
100 // 3 lignes de 4 colonnes
101 Image image(4*width(), 3*height());
102 for(int i= 0; i < 6; i++)
103 {
104 Image face= flipY(flipX(m_faces[i]));
105
106 int xmin= faces[i].x*width();
107 int ymin= faces[i].y*height();
108 for(int y= 0; y < height(); y++)
109 for(int x= 0; x < width(); x++)
110 image(xmin+x, ymin+y)= face(x, y);
111 }
112
113 return image;
114 }
115
117 std::array<Image, 6> faces( ) const
118 {
119 if(empty())
120 return std::array<Image, 6>();
121
122 std::array<Image, 6> faces;
123 for(int i= 0; i < 6; i++)
124 faces[i]= flipY(flipX(m_faces[i]));
125
126 return faces;
127 }
128
129 Color& operator() ( const int face, const int x, const int y )
130 {
131 return m_faces[face](x, y);
132 }
133
134 Color operator() ( const int face, const int x, const int y ) const
135 {
136 return m_faces[face](x, y);
137 }
138
140 Color texture( const Vector& d ) const
141 {
142 // reproduit la convention opengl / renderman
143 // cf https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf#section.8.13
144
145 float sm, tm;
146 int face= -1;
147 Vector m= Vector(std::abs(d.x), std::abs(d.y), std::abs(d.z));
148 if(m.x > m.y && m.x > m.z)
149 {
150 // X
151 if(d.x > 0)
152 {
153 face= 0;
154 sm= -d.z / m.x;
155 tm= -d.y / m.x;
156 }
157 else
158 {
159 face= 1;
160 sm= d.z / m.x;
161 tm= -d.y / m.x;
162 }
163 }
164 else if(m.y > m.z)
165 {
166 // Y
167 if(d.y > 0)
168 {
169 face= 2;
170 sm= d.x / m.y;
171 tm= d.z / m.y;
172 }
173 else
174 {
175 face= 3;
176 sm= d.x / m.y;
177 tm= -d.z / m.y;
178 }
179 }
180 else
181 {
182 // Z
183 if(d.z > 0)
184 {
185 face= 4;
186 sm= d.x / m.z;
187 tm= -d.y / m.z;
188 }
189 else
190 {
191 face= 5;
192 sm= -d.x / m.z;
193 tm= -d.y / m.z;
194 }
195 }
196
197 assert(face != -1);
198 float s= (sm +1) / 2;
199 float t= (tm +1) / 2;
200 return m_faces[face].texture(s, t);
201 }
202
203 // mapping direction vers pixel [0 .. w]x[0 .. h]
204 Vector envmap_pixel( const Vector& d ) { Vector texel= envmap_texel(d); return Vector(texel.x, texel.y * m_width, texel.z * m_width); }
205
206 // mapping direction vers texel [0 .. 1]x[0 .. 1]
207 Vector envmap_texel( const Vector& d )
208 {
209 float sm, tm;
210 int face= -1;
211 Vector m= Vector(std::abs(d.x), std::abs(d.y), std::abs(d.z));
212 if(m.x > m.y && m.x > m.z)
213 {
214 // X
215 if(d.x > 0)
216 {
217 face= 0;
218 sm= -d.z / m.x;
219 tm= -d.y / m.x;
220 }
221 else
222 {
223 face= 1;
224 sm= d.z / m.x;
225 tm= -d.y / m.x;
226 }
227 }
228 else if(m.y > m.z)
229 {
230 // Y
231 if(d.y > 0)
232 {
233 face= 2;
234 sm= d.x / m.y;
235 tm= d.z / m.y;
236 }
237 else
238 {
239 face= 3;
240 sm= d.x / m.y;
241 tm= -d.z / m.y;
242 }
243 }
244 else
245 {
246 // Z
247 if(d.z > 0)
248 {
249 face= 4;
250 sm= d.x / m.z;
251 tm= -d.y / m.z;
252 }
253 else
254 {
255 face= 5;
256 sm= -d.x / m.z;
257 tm= -d.y / m.z;
258 }
259 }
260
261 assert(face != -1);
262 float s= (sm +1) / 2;
263 float t= (tm +1) / 2;
264 return Vector(face, s, t);
265 }
266
267 // mapping texel vers direction
268 Vector envmap_pixel_direction( const Vector& d ) { return envmap_texel_direction(int(d.x), d.y / m_width, d.z / m_width); }
269
270 Vector envmap_texel_direction( const Vector& d ) { return envmap_texel_direction(int(d.x), d.y, d.z); }
271
272 Vector envmap_texel_direction( const int face, const float s, const float t )
273 {
274 // retrouve le point sur le cube [-1 .. 1]
275 float sm= 2 * s -1;
276 float tm= 2 * t -1;
277 if(face == 0)
278 {
279 // X+
280 // sm= -d.z / m.x;
281 // tm= -d.y / m.x;
282 return Vector(1, -tm, -sm);
283 }
284 else if(face == 1)
285 {
286 // X-
287 // sm= d.z / m.x;
288 // tm= -d.y / m.x;
289 return Vector(-1, -tm, sm);
290 }
291 else if(face == 2)
292 {
293 // Y+
294 // sm= d.x / m.y;
295 // tm= d.z / m.y;
296 return Vector(sm, 1, tm);
297 }
298 else if(face == 3)
299 {
300 // Y-
301 // sm= d.x / m.y;
302 // tm= -d.z / m.y;
303 return Vector(sm, -1, -tm);
304 }
305 else if(face == 4)
306 {
307 // Z+
308 // sm= d.x / m.z;
309 // tm= -d.y / m.z;
310 return Vector(sm, -tm, 1);
311 }
312 else // if(face == 5)
313 {
314 // Z-
315 // sm= -d.x / m.z;
316 // tm= -d.y / m.z;
317 return Vector(-sm, -tm, -1);
318 }
319 }
320
321protected:
322 std::array<Image, 6> m_faces;
323 unsigned m_width;
324};
325
327Envmap read_cubemap( const char *filename );
329Envmap read_cubemap_faces( const std::array<const char *, 6>& filenames );
331Envmap read_cubemap_faces( const char *prefix );
332
334int write_cubemap( const Envmap& envmap, const char *filename );
336int write_cubemap_faces( const Envmap& envmap, const char *prefix );
337
338
339#endif
340
representation d'une image.
Definition image.h:21
Image flipY(const Image &image)
retourne l'image
Definition image_io.cpp:112
Image flipX(const Image &image)
retourne l'image
Definition image_io.cpp:129
Image copy(const Image &image, const unsigned xmin, const unsigned ymin, const unsigned width, const unsigned height)
renvoie un bloc de l'image
Definition image_io.cpp:145
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14
representation d'une cubemap / envmap.
Definition envmap.h:13
Envmap(const Image &image)
extrait les 6 faces d'une image.
Definition envmap.h:23
int height() const
hauteur d'une face.
Definition envmap.h:59
Color texture(const Vector &d) const
renvoie la couleur de la cubemap dans la direction d, utilise les memes conventions qu'openGL / Rende...
Definition envmap.h:140
Image cross() const
renvoie une image contenant les 6 faces de la cubemap.
Definition envmap.h:85
Envmap(const std::array< Image, 6 > &faces)
utilise les 6 faces.
Definition envmap.h:47
void linear(const float gamma=2.2f)
applique une correction gamma inverse aux donnees de la cubemap.
Definition envmap.h:63
bool empty() const
renvoie vrai si la cubemap est initialisee.
Definition envmap.h:60
int width() const
largeur d'une face.
Definition envmap.h:58
void gamma(const float gamma=2.2f)
applique une correction gamma aux donnees de la cubemap.
Definition envmap.h:74
std::array< Image, 6 > faces() const
renvoie les 6 faces de la cubemap.
Definition envmap.h:117
representation d'un vecteur 3d.
Definition vec.h:67