T55486: use GPU_R11F_G11F_B10F for Matcaps
[blender.git] / source / blender / blenkernel / intern / studiolight.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006-2007 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  *
27  */
28
29 /** \file blender/blenkernel/intern/studiolight.c
30  *  \ingroup bke
31  */
32
33 #include "BKE_studiolight.h"
34
35 #include "BKE_appdir.h"
36 #include "BKE_icons.h"
37
38 #include "BLI_fileops.h"
39 #include "BLI_fileops_types.h"
40 #include "BLI_listbase.h"
41 #include "BLI_math.h"
42 #include "BLI_path_util.h"
43 #include "BLI_rand.h"
44 #include "BLI_string.h"
45 #include "BLI_string_utils.h"
46
47 #include "DNA_listBase.h"
48
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
51
52 #include "GPU_texture.h"
53
54 #include "MEM_guardedalloc.h"
55
56
57 /* Statics */
58 static ListBase studiolights;
59 #define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 16
60 #define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT 64
61 #define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT * 2)
62
63 static const char *STUDIOLIGHT_CAMERA_FOLDER = "studiolights/camera/";
64 static const char *STUDIOLIGHT_WORLD_FOLDER = "studiolights/world/";
65 static const char *STUDIOLIGHT_MATCAP_FOLDER = "studiolights/matcap/";
66
67 /* FUNCTIONS */
68 static void studiolight_free(struct StudioLight *sl)
69 {
70         for (int index = 0 ; index < 6 ; index ++) {
71                 if (sl->radiance_cubemap_buffers[index] != NULL) {
72                         IMB_freeImBuf(sl->radiance_cubemap_buffers[index]);
73                         sl->radiance_cubemap_buffers[index] = NULL;
74                 }
75         }
76         if (sl->equirectangular_radiance_gputexture) {
77                 GPU_texture_free(sl->equirectangular_radiance_gputexture);
78                 sl->equirectangular_radiance_gputexture = NULL;
79         }
80         
81         if (sl->equirectangular_irradiance_gputexture) {
82                 GPU_texture_free(sl->equirectangular_irradiance_gputexture);
83                 sl->equirectangular_irradiance_gputexture = NULL;
84         }
85         
86         if (sl->equirectangular_radiance_buffer) {
87                 IMB_freeImBuf(sl->equirectangular_radiance_buffer);
88                 sl->equirectangular_radiance_buffer = NULL;
89         }
90         
91         if (sl->equirectangular_irradiance_buffer) {
92                 IMB_freeImBuf(sl->equirectangular_irradiance_buffer);
93                 sl->equirectangular_irradiance_buffer = NULL;
94         }
95         if (sl->path_irr) {
96                 MEM_freeN(sl->path_irr);
97                 sl->path_irr = NULL;
98         }
99         if (sl->gpu_matcap_3components) {
100                 MEM_freeN(sl->gpu_matcap_3components);
101                 sl->gpu_matcap_3components = NULL;
102         }
103         MEM_freeN(sl);
104 }
105
106 static struct StudioLight *studiolight_create(int flag)
107 {
108         struct StudioLight *sl = MEM_callocN(sizeof(*sl), __func__);
109         sl->path[0] = 0x00;
110         sl->name[0] = 0x00;
111         sl->path_irr = NULL;
112         sl->flag = flag;
113         sl->index = BLI_listbase_count(&studiolights);
114         if (flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL) {
115                 sl->icon_id_matcap = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_MATCAP);
116                 sl->icon_id_matcap_flipped = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED);
117         }
118         else {
119                 sl->icon_id_radiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_RADIANCE);
120                 sl->icon_id_irradiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE);
121         }
122
123         for (int index = 0 ; index < 6 ; index ++) {
124                 sl->radiance_cubemap_buffers[index] = NULL;
125         }
126         return sl;
127 }
128
129 static void direction_to_equirectangular(float r[2], const float dir[3])
130 {
131         r[0] = (atan2f(dir[1], dir[0]) - M_PI) / -(M_PI * 2);
132         r[1] = (acosf(dir[2] / 1.0) - M_PI) / -M_PI;
133 }
134
135 static void equirectangular_to_direction(float r[3], float u, float v)
136 {
137         float phi = (-(M_PI * 2)) * u + M_PI;
138         float theta = -M_PI * v + M_PI;
139         float sin_theta = sinf(theta);
140         r[0] = sin_theta * cosf(phi);
141         r[1] = sin_theta * sinf(phi);
142         r[2] = cosf(theta);
143 }
144
145 static void studiolight_calculate_radiance(ImBuf *ibuf, float color[4], const float direction[3])
146 {
147         float uv[2];
148         direction_to_equirectangular(uv, direction);
149         nearest_interpolation_color_wrap(ibuf, NULL, color, uv[0] * ibuf->x, uv[1] * ibuf->y);
150 }
151
152 static void studiolight_calculate_radiance_buffer(
153         ImBuf *ibuf, float *colbuf,
154         const float start_x, const float add_x,
155         const float start_y, const float add_y, const float z,
156         const int index_x, const int index_y, const int index_z)
157 {
158         float direction[3];
159         float yf = start_y;
160         float xf;
161         float *color = colbuf;
162
163         for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y ++, yf += add_y) {
164                 xf = start_x;
165                 for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x ++, xf += add_x) {
166                         direction[index_x] = xf;
167                         direction[index_y] = yf;
168                         direction[index_z] = z;
169                         normalize_v3(direction);
170                         studiolight_calculate_radiance(ibuf, color, direction);
171                         color += 4;
172                 }
173         }
174 }
175
176 static void studiolight_load_equierectangular_image(StudioLight *sl)
177 {
178         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
179                 ImBuf *ibuf = NULL;
180                 ibuf = IMB_loadiffname(sl->path, 0, NULL);
181                 if (ibuf) {
182                         IMB_float_from_rect(ibuf);
183                         sl->equirectangular_radiance_buffer = ibuf;
184                 }
185         }
186         sl->flag |= STUDIOLIGHT_EXTERNAL_IMAGE_LOADED;
187 }
188
189 static void studiolight_create_equierectangular_radiance_gputexture(StudioLight *sl)
190 {
191         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
192                 char error[256];
193                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
194                 ImBuf *ibuf = sl->equirectangular_radiance_buffer;
195
196                 if (sl->flag & STUDIOLIGHT_ORIENTATION_VIEWNORMAL) {
197                         sl->gpu_matcap_3components = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y * 3, __func__);
198                         
199                         float* offset4 = ibuf->rect_float;
200                         float* offset3 = sl->gpu_matcap_3components;
201                         for (int i = 0 ; i < ibuf->x * ibuf->y; i ++)
202                         {
203                                 copy_v3_v3(offset3, offset4);
204                                 offset3 += 3;
205                                 offset4 += 4;
206                         }
207                         sl->equirectangular_radiance_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_R11F_G11F_B10F, sl->gpu_matcap_3components, error);
208                 }
209                 else {
210                         sl->equirectangular_radiance_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
211                         GPUTexture *tex = sl->equirectangular_radiance_gputexture;
212                         GPU_texture_bind(tex, 0);
213                         GPU_texture_filter_mode(tex, true);
214                         GPU_texture_wrap_mode(tex, true);
215                         GPU_texture_unbind(tex);
216                 }
217         }
218         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE;
219 }
220
221 static void studiolight_create_equierectangular_irradiance_gputexture(StudioLight *sl)
222 {
223         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
224                 char error[256];
225                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED);
226                 ImBuf *ibuf = sl->equirectangular_irradiance_buffer;
227                 sl->equirectangular_irradiance_gputexture = GPU_texture_create_2D(ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
228                 GPUTexture *tex = sl->equirectangular_irradiance_gputexture;
229                 GPU_texture_bind(tex, 0);
230                 GPU_texture_filter_mode(tex, true);
231                 GPU_texture_wrap_mode(tex, true);
232                 GPU_texture_unbind(tex);
233         }
234         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE;
235 }
236
237 static void studiolight_calculate_radiance_cubemap_buffers(StudioLight *sl)
238 {
239         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
240                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
241                 ImBuf *ibuf = sl->equirectangular_radiance_buffer;
242                 if (ibuf) {
243                         float *colbuf = MEM_mallocN(SQUARE(STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * sizeof(float[4]), __func__);
244                         const float add = 1.0f / (STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE + 1);
245                         const float start = ((1.0f / STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * 0.5f) - 0.5f;
246
247                         /* front */
248                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, 0.5f, 0, 2, 1);
249                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer(
250                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
251
252                         /* back */
253                         studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, -0.5f, 0, 2, 1);
254                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer(
255                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
256
257                         /* left */
258                         studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, 0.5f, 1, 2, 0);
259                         sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer(
260                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
261
262                         /* right */
263                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 1, 2, 0);
264                         sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer(
265                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
266
267                         /* top */
268                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 0, 1, 2);
269                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer(
270                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
271
272                         /* bottom */
273                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, -start, -add, 0.5f, 0, 1, 2);
274                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer(
275                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
276
277 #if 0
278                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], "/tmp/studiolight_radiance_left.png", IB_rectfloat);
279                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], "/tmp/studiolight_radiance_right.png", IB_rectfloat);
280                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], "/tmp/studiolight_radiance_front.png", IB_rectfloat);
281                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], "/tmp/studiolight_radiance_back.png", IB_rectfloat);
282                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], "/tmp/studiolight_radiance_bottom.png", IB_rectfloat);
283                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], "/tmp/studiolight_radiance_top.png", IB_rectfloat);
284 #endif
285                         MEM_freeN(colbuf);
286                 }
287         }
288         sl->flag |= STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED;
289 }
290
291 BLI_INLINE void studiolight_evaluate_radiance_buffer(
292         ImBuf *radiance_buffer, const float normal[3], float color[3], int *hits,
293         int xoffset, int yoffset, int zoffset, float zvalue)
294 {
295         if (radiance_buffer == NULL) {
296                 return;
297         }
298         float angle;
299         float *radiance_color = radiance_buffer->rect_float;
300         float direction[3];
301         for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y ++) {
302                 for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x ++) {
303                         // calculate light direction;
304                         direction[zoffset] = zvalue;
305                         direction[xoffset] = (x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
306                         direction[yoffset] = (y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
307                         normalize_v3(direction);
308                         angle = fmax(0.0f, dot_v3v3(direction, normal));
309                         madd_v3_v3fl(color, radiance_color, angle);
310                         (*hits) ++;
311                         radiance_color += 4;
312                 }
313         }
314
315 }
316
317 static void studiolight_calculate_irradiance(StudioLight *sl, float color[3], const float normal[3])
318 {
319         int hits = 0;
320         copy_v3_fl(color, 0.0f);
321
322         /* back */
323         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, &hits, 0, 2, 1, 0.5);
324         /* front */
325         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, &hits, 0, 2, 1, -0.5);
326
327         /* left */
328         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, &hits, 1, 2, 0, 0.5);
329         /* right */
330         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, &hits, 1, 2, 0, -0.5);
331
332         /* top */
333         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, &hits, 0, 1, 2, 0.5);
334         /* bottom */
335         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, &hits, 0, 1, 2, -0.5);
336
337         if (hits) {
338                 mul_v3_fl(color, 3.0 / hits);
339         }
340         else {
341                 copy_v3_fl3(color, 1.0, 0.0, 1.0);
342         }
343 }
344
345
346 static void studiolight_calculate_diffuse_light(StudioLight *sl)
347 {
348         /* init light to black */
349         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 0.0f);
350         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f);
351         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.0f);
352         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.0f);
353         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.0f);
354         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.0f);
355
356         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
357                 const float normal_x_neg[3] = {-1.0f,  0.0f,  0.0f};
358                 const float normal_x_pos[3] = { 1.0f,  0.0f,  0.0f};
359                 const float normal_y_neg[3] = { 0.0f,  1.0f,  0.0f};
360                 const float normal_y_pos[3] = { 0.0f, -1.0f,  0.0f};
361                 const float normal_z_neg[3] = { 0.0f,  0.0f, -1.0f};
362                 const float normal_z_pos[3] = { 0.0f,  0.0f,  1.0f};
363
364                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED);
365
366                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_X_POS], normal_x_pos);
367                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_X_NEG], normal_x_neg);
368                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Y_POS], normal_y_pos);
369                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Y_NEG], normal_y_neg);
370                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Z_POS], normal_z_pos);
371                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Z_NEG], normal_z_neg);
372         }
373         sl->flag |= STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED;
374 }
375
376 static float area_element(float x, float y )
377 {
378         return atan2f(x * y, sqrt(x * x + y * y + 1));
379 }
380
381 static float texel_coord_solid_angle(float a_U, float a_V, int a_Size)
382 {
383         //scale up to [-1, 1] range (inclusive), offset by 0.5 to point to texel center.
384         float u = (2.0f * ((float)a_U + 0.5f) / (float)a_Size ) - 1.0f;
385         float v = (2.0f * ((float)a_V + 0.5f) / (float)a_Size ) - 1.0f;
386
387         float resolution_inv = 1.0f / a_Size;
388
389         // U and V are the -1..1 texture coordinate on the current face.
390         // Get projected area for this texel
391         float x0 = u - resolution_inv;
392         float y0 = v - resolution_inv;
393         float x1 = u + resolution_inv;
394         float y1 = v + resolution_inv;
395         return area_element(x0, y0) - area_element(x0, y1) - area_element(x1, y0) + area_element(x1, y1);
396 }
397
398 BLI_INLINE void studiolight_evaluate_specular_radiance_buffer(
399         ImBuf *radiance_buffer, const float normal[3], float color[3], 
400         int xoffset, int yoffset, int zoffset, float zvalue)
401 {
402         if (radiance_buffer == NULL) {
403                 return;
404         }
405         float angle;
406         float *radiance_color = radiance_buffer->rect_float;
407         float direction[3];
408         for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y ++) {
409                 for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x ++) {
410                         // calculate light direction;
411                         float u = (x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
412                         float v = (y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
413                         direction[zoffset] = zvalue;
414                         direction[xoffset] = u;
415                         direction[yoffset] = v;
416                         normalize_v3(direction);
417                         angle = fmax(0.0f, dot_v3v3(direction, normal)) * texel_coord_solid_angle(x, y, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
418                         madd_v3_v3fl(color, radiance_color, angle);
419                         radiance_color += 4;
420                 }
421         }
422
423 }
424
425 static void studiolight_calculate_specular_irradiance(StudioLight *sl, float color[3], const float normal[3])
426 {
427         copy_v3_fl(color, 0.0f);
428
429         /* back */
430         studiolight_evaluate_specular_radiance_buffer(
431                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, 0, 2, 1, 0.5);
432         /* front */
433         studiolight_evaluate_specular_radiance_buffer(
434                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, 0, 2, 1, -0.5);
435
436         /* left */
437         studiolight_evaluate_specular_radiance_buffer(
438                 sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, 1, 2, 0, 0.5);
439         /* right */
440         studiolight_evaluate_specular_radiance_buffer(
441                 sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, 1, 2, 0, -0.5);
442
443         /* top */
444         studiolight_evaluate_specular_radiance_buffer(
445                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, 0, 1, 2, 0.5);
446         /* bottom */
447         studiolight_evaluate_specular_radiance_buffer(
448                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, 0, 1, 2, -0.5);
449
450         mul_v3_fl(color, 1.0 / M_PI);
451 }
452
453 static bool studiolight_load_irradiance_equirectangular_image(StudioLight *sl)
454 {
455 #if 1
456         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
457                 ImBuf *ibuf = NULL;
458                 ibuf = IMB_loadiffname(sl->path_irr, 0, NULL);
459                 if (ibuf) {
460                         IMB_float_from_rect(ibuf);
461                         sl->equirectangular_irradiance_buffer = ibuf;
462                         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED;
463                         return true;
464                 }
465         }
466 #endif
467         return false;
468 }
469
470 static void studiolight_calculate_irradiance_equirectangular_image(StudioLight *sl)
471 {
472         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
473                 /* check for cached irr file */
474                 
475                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED);
476
477                 float *colbuf = MEM_mallocN(STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH * STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT * sizeof(float[4]), __func__);
478                 float *color = colbuf;
479                 for (int y = 0; y < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT ; y ++) {
480                         float yf = y / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT;
481
482                         for (int x = 0; x < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH ; x ++) {
483                                 float xf = x / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH;
484                                 float dir[3];
485                                 equirectangular_to_direction(dir, xf, yf);
486                                 studiolight_calculate_specular_irradiance(sl, color, dir);
487                                 color[3] = 1.0f;
488                                 color += 4;
489                         }
490                 }
491                 sl->equirectangular_irradiance_buffer = IMB_allocFromBuffer(
492                         NULL, colbuf,
493                         STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH,
494                         STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT);
495                 MEM_freeN(colbuf);
496
497                 if (sl->flag | STUDIOLIGHT_USER_DEFINED) {
498                         IMB_saveiff(sl->equirectangular_irradiance_buffer, sl->path_irr, IB_rectfloat);
499                 }
500         }
501         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED;
502 }
503
504 static void studiolight_calculate_light_direction(StudioLight *sl)
505 {
506         float best_light = 0.0;
507         sl->light_direction[0] = 0.0f;
508         sl->light_direction[1] = 0.0f;
509         sl->light_direction[2] = -1.0f;
510
511         if ((sl->flag & STUDIOLIGHT_EXTERNAL_FILE) && (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) {
512                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED);
513                 ImBuf *ibuf = sl->equirectangular_irradiance_buffer;
514                 if (ibuf) {
515                         /* go over every pixel, determine light, if higher calc direction off the light */
516                         float new_light;
517                         float *color = ibuf->rect_float;
518                         for (int y = 0; y < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT; y ++) {
519                                 for (int x = 0; x < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH; x ++) {
520                                         new_light = color[0] + color[1] + color[2];
521                                         if (new_light > best_light) {
522                                                 float u = x / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH;
523                                                 float v = y / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT;
524                                                 equirectangular_to_direction(sl->light_direction, u, v);
525                                                 SWAP(float, sl->light_direction[0], sl->light_direction[1]);
526                                                 normalize_v3(sl->light_direction);
527                                                 negate_v3(sl->light_direction);
528                                                 best_light = new_light;
529                                         }
530                                         color += 4;
531                                 }
532                         }
533                 }
534         }
535         sl->flag |= STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED;
536 }
537
538 static void studiolight_add_files_from_datafolder(const int folder_id, const char *subfolder, int flag)
539 {
540         StudioLight *sl;
541         struct direntry *dir;
542         const char *folder = BKE_appdir_folder_id(folder_id, subfolder);
543         if (folder) {
544                 uint totfile = BLI_filelist_dir_contents(folder, &dir);
545                 int i;
546                 for (i = 0; i < totfile; i++) {
547                         if ((dir[i].type & S_IFREG)) {
548                                 const char *filename = dir[i].relname;
549                                 const char *path = dir[i].path;
550                                 if (BLI_testextensie_array(filename, imb_ext_image)) {
551                                         sl = studiolight_create(STUDIOLIGHT_EXTERNAL_FILE | flag);
552                                         BLI_strncpy(sl->name, filename, FILE_MAXFILE);
553                                         BLI_strncpy(sl->path, path, FILE_MAXFILE);
554                                         sl->path_irr = BLI_string_joinN(path, ".irr");
555                                         BLI_addtail(&studiolights, sl);
556                                 }
557                         }
558                 }
559                 BLI_filelist_free(dir, totfile);
560                 dir = NULL;
561         }
562
563 }
564
565 static int studiolight_flag_cmp_order(const StudioLight *sl)
566 {
567         /* Internal studiolights before external studio lights */
568         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
569                 return 1;
570         }
571         return 0;
572 }
573
574 static int studiolight_cmp(const void *a, const void *b)
575 {
576         const StudioLight *sl1 = a;
577         const StudioLight *sl2 = b;
578
579         const int flagorder1 = studiolight_flag_cmp_order(sl1);
580         const int flagorder2 = studiolight_flag_cmp_order(sl2);
581
582         if (flagorder1 < flagorder2) {
583                 return -1;
584         }
585         else if (flagorder1 > flagorder2) {
586                 return 1;
587         }
588         else {
589                 return BLI_strcasecmp(sl1->name, sl2->name);
590         }
591 }
592
593 /* icons */
594 static uint *studiolight_radiance_preview(StudioLight *sl, int icon_size)
595 {
596         BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
597
598         uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
599         int icon_center = icon_size / 2;
600         float sphere_radius = icon_center * 0.9;
601
602         int offset = 0;
603         for (int y = 0; y < icon_size; y++) {
604                 float dy = y - icon_center;
605                 for (int x = 0; x < icon_size; x++) {
606                         float dx = x - icon_center;
607                         /* calculate aliasing */
608                         float alias = 0;
609                         const float alias_step = 0.333;
610                         for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) {
611                                 for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) {
612                                         if (sqrt(ay * ay + ax * ax) < sphere_radius) {
613                                                 alias += alias_step * alias_step;
614                                         }
615                                 }
616                         }
617                         uint pixelresult = 0x0;
618                         uint alias_i = clamp_i(alias * 256, 0, 255);
619                         if (alias_i != 0) {
620                                 /* calculate normal */
621                                 uint alias_mask = alias_i << 24;
622                                 float incoming[3];
623                                 copy_v3_fl3(incoming, 0.0, 1.0, 0.0);
624
625                                 float normal[3];
626                                 normal[0] = dx / sphere_radius;
627                                 normal[2] = dy / sphere_radius;
628                                 normal[1] = -sqrt(-(normal[0] * normal[0]) - (normal[2] * normal[2]) + 1);
629                                 normalize_v3(normal);
630
631                                 float direction[3];
632                                 reflect_v3_v3v3(direction, incoming, normal);
633
634                                 float color[4];
635                                 studiolight_calculate_radiance(sl->equirectangular_radiance_buffer, color, direction);
636
637                                 pixelresult = rgb_to_cpack(
638                                         linearrgb_to_srgb(color[0]),
639                                         linearrgb_to_srgb(color[1]),
640                                         linearrgb_to_srgb(color[2])) | alias_mask;
641                         }
642                         rect[offset++] = pixelresult;
643                 }
644         }
645         return rect;
646 }
647
648 static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size, bool flipped)
649 {
650         BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
651
652         uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
653         const uint alphamask = 0xff000000;
654         float color[4];
655         float fx, fy;
656         int offset = 0;
657         ImBuf *ibuf = sl->equirectangular_radiance_buffer;
658
659         for (int y = 0; y < icon_size; y++) {
660                 fy = y * ibuf->y / icon_size;
661                 for (int x = 0; x < icon_size; x++) {
662                         if (flipped) {
663                                 fx = ibuf->x - (x * ibuf->x / icon_size) - 1;
664                         }
665                         else {
666                                 fx = x * ibuf->x / icon_size;
667                         }
668                         nearest_interpolation_color(ibuf, NULL, color, fx, fy);
669                         rect[offset++] = rgb_to_cpack(
670                                 linearrgb_to_srgb(color[0]),
671                                 linearrgb_to_srgb(color[1]),
672                                 linearrgb_to_srgb(color[2])) | alphamask;
673                 }
674         }
675         return rect;
676 }
677
678 static uint *studiolight_irradiance_preview(StudioLight *sl, int icon_size)
679 {
680 #if 0
681         if (!(sl->flag & STUDIOLIGHT_EXTERNAL_FILE))
682 #endif
683         {
684
685                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED);
686
687                 uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
688                 int icon_center = icon_size / 2;
689                 float sphere_radius = icon_center * 0.9;
690
691                 int offset = 0;
692                 for (int y = 0; y < icon_size; y++) {
693                         float dy = y - icon_center;
694                         for (int x = 0; x < icon_size; x++) {
695                                 float dx = x - icon_center;
696                                 /* calculate aliasing */
697                                 float alias = 0;
698                                 const float alias_step = 0.333;
699                                 for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) {
700                                         for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) {
701                                                 if (sqrt(ay * ay + ax * ax) < sphere_radius) {
702                                                         alias += alias_step * alias_step;
703                                                 }
704                                         }
705                                 }
706                                 uint pixelresult = 0x0;
707                                 uint alias_i = clamp_i(alias * 256, 0, 255);
708                                 if (alias_i != 0) {
709                                         /* calculate normal */
710                                         uint alias_mask = alias_i << 24;
711                                         float normal[3];
712                                         normal[0] = dx / sphere_radius;
713                                         normal[1] = dy / sphere_radius;
714                                         normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1);
715                                         normalize_v3(normal);
716
717                                         float color[3];
718                                         mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0));
719                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0));
720                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[1], 0.0, 1.0));
721                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_NEG], clamp_f(-normal[1], 0.0, 1.0));
722                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[2], 0.0, 1.0));
723
724                                         pixelresult = rgb_to_cpack(
725                                                 linearrgb_to_srgb(color[0]),
726                                                 linearrgb_to_srgb(color[1]),
727                                                 linearrgb_to_srgb(color[2])) | alias_mask;
728                                 }
729                                 rect[offset++] = pixelresult;
730                         }
731                 }
732                 return rect;
733         }
734 #if 0
735         else {
736                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED);
737
738                 uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
739                 int icon_center = icon_size / 2;
740                 float sphere_radius = icon_center * 0.9;
741
742                 int offset = 0;
743                 for (int y = 0; y < icon_size; y++) {
744                         float dy = y - icon_center;
745                         for (int x = 0; x < icon_size; x++) {
746                                 float dx = x - icon_center;
747                                 /* calculate aliasing */
748                                 float alias = 0;
749                                 const float alias_step = 0.333;
750                                 for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) {
751                                         for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) {
752                                                 if (sqrt(ay * ay + ax * ax) < sphere_radius) {
753                                                         alias += alias_step * alias_step;
754                                                 }
755                                         }
756                                 }
757                                 uint pixelresult = 0x0;
758                                 uint alias_i = clamp_i(alias * 256, 0, 255);
759                                 if (alias_i != 0) {
760                                         /* calculate normal */
761                                         uint alias_mask = alias_i << 24;
762                                         float incoming[3];
763                                         copy_v3_fl3(incoming, 0.0, 1.0, 0.0);
764
765                                         float normal[3];
766                                         normal[0] = dx / sphere_radius;
767                                         normal[2] = dy / sphere_radius;
768                                         normal[1] = -sqrt(-(normal[0] * normal[0]) - (normal[2] * normal[2]) + 1);
769                                         normalize_v3(normal);
770
771                                         float direction[3];
772                                         reflect_v3_v3v3(direction, incoming, normal);
773
774                                         float color[4];
775                                         studiolight_calculate_radiance(sl->equirectangular_irradiance_buffer, color, direction);
776
777                                         pixelresult = rgb_to_cpack(
778                                                 linearrgb_to_srgb(color[0]),
779                                                 linearrgb_to_srgb(color[1]),
780                                                 linearrgb_to_srgb(color[2])) | alias_mask;
781                                 }
782                                 rect[offset++] = pixelresult;
783                         }
784                 }
785                 return rect;
786         }
787 #endif
788 }
789
790 /* API */
791 void BKE_studiolight_init(void)
792 {
793         StudioLight *sl;
794         /* go over the preset folder and add a studiolight for every image with its path */
795         /* order studio lights by name */
796         /* Also reserve icon space for it. */
797         /* Add default studio light */
798         sl = studiolight_create(STUDIOLIGHT_INTERNAL | STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED | STUDIOLIGHT_ORIENTATION_CAMERA);
799         BLI_strncpy(sl->name, "INTERNAL_01", FILE_MAXFILE);
800         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 1.5f);
801         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f);
802         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.8f);
803         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.05f);
804         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.2f);
805         copy_v3_fl3(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.1f, 0.0f, 0.0f);
806         BLI_addtail(&studiolights, sl);
807
808         studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_CAMERA_FOLDER, STUDIOLIGHT_ORIENTATION_CAMERA);
809         studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,   STUDIOLIGHT_CAMERA_FOLDER, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_USER_DEFINED);
810         studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_WORLD_FOLDER,  STUDIOLIGHT_ORIENTATION_WORLD);
811         studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,   STUDIOLIGHT_WORLD_FOLDER,  STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_USER_DEFINED);
812         studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_MATCAP_FOLDER, STUDIOLIGHT_ORIENTATION_VIEWNORMAL);
813         studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,   STUDIOLIGHT_MATCAP_FOLDER, STUDIOLIGHT_ORIENTATION_VIEWNORMAL | STUDIOLIGHT_USER_DEFINED);
814
815         /* sort studio lights on filename. */
816         BLI_listbase_sort(&studiolights, studiolight_cmp);
817 }
818
819 void BKE_studiolight_free(void)
820 {
821         struct StudioLight *sl;
822         while ((sl = BLI_pophead(&studiolights))) {
823                 studiolight_free(sl);
824         }
825 }
826
827 struct StudioLight *BKE_studiolight_find_first(int flag)
828 {
829         LISTBASE_FOREACH(StudioLight *, sl, &studiolights) {
830                 if ((sl->flag & flag)) {
831                         return sl;
832                 }
833         }
834         return NULL;
835 }
836
837 struct StudioLight *BKE_studiolight_find(const char *name, int flag)
838 {
839         LISTBASE_FOREACH(StudioLight *, sl, &studiolights) {
840                 if (STREQLEN(sl->name, name, FILE_MAXFILE)) {
841                         if ((sl->flag & flag)) {
842                                 return sl;
843                         }
844                         else {
845                                 /* flags do not match, so use default */
846                                 return BKE_studiolight_find_first(flag);
847                         }
848                 }
849         }
850         /* When not found, use the default studio light */
851         return BKE_studiolight_find_first(flag);
852 }
853
854 struct StudioLight *BKE_studiolight_findindex(int index, int flag)
855 {
856         LISTBASE_FOREACH(StudioLight *, sl, &studiolights) {
857                 if (sl->index == index) {
858                         return sl;
859                 }
860         }
861         /* When not found, use the default studio light */
862         return BKE_studiolight_find_first(flag);
863 }
864
865 struct ListBase *BKE_studiolight_listbase(void)
866 {
867         return &studiolights;
868 }
869
870 uint *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type)
871 {
872         switch (icon_id_type) {
873                 case STUDIOLIGHT_ICON_ID_TYPE_RADIANCE:
874                 default:
875                         return studiolight_radiance_preview(sl, icon_size);
876                 case STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE:
877                         return studiolight_irradiance_preview(sl, icon_size);
878                 case STUDIOLIGHT_ICON_ID_TYPE_MATCAP:
879                         return studiolight_matcap_preview(sl, icon_size, false);
880                 case STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED:
881                         return studiolight_matcap_preview(sl, icon_size, true);
882         }
883 }
884
885 void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
886 {
887         if ((sl->flag & flag) == flag) {
888                 return;
889         }
890
891         if ((flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED)) {
892                 studiolight_load_equierectangular_image(sl);
893         }
894         if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) {
895                 studiolight_calculate_radiance_cubemap_buffers(sl);
896         }
897         if ((flag & STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED)) {
898                 studiolight_calculate_diffuse_light(sl);
899         }
900         if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE)) {
901                 studiolight_create_equierectangular_radiance_gputexture(sl);
902         }
903         if ((flag & STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED)) {
904                 studiolight_calculate_light_direction(sl);
905         }
906         if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE)) {
907                 studiolight_create_equierectangular_irradiance_gputexture(sl);
908         }
909         if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED)) {
910                 if (!studiolight_load_irradiance_equirectangular_image(sl)) {
911                         studiolight_calculate_irradiance_equirectangular_image(sl);
912                 }
913         }
914 }
915
916 void BKE_studiolight_refresh(void)
917 {
918         BKE_studiolight_free();
919         BKE_studiolight_init();
920 }