Merge branch 'master' into blender2.8
[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_equirectangular_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_equirectangular_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[3]) * ibuf->x * ibuf->y, __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                                 copy_v3_v3(offset3, offset4);
203                                 offset3 += 3;
204                                 offset4 += 4;
205                         }
206                         sl->equirectangular_radiance_gputexture = GPU_texture_create_2D(
207                                 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(
211                                 ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
212                         GPUTexture *tex = sl->equirectangular_radiance_gputexture;
213                         GPU_texture_bind(tex, 0);
214                         GPU_texture_filter_mode(tex, true);
215                         GPU_texture_wrap_mode(tex, true);
216                         GPU_texture_unbind(tex);
217                 }
218         }
219         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE;
220 }
221
222 static void studiolight_create_equirectangular_irradiance_gputexture(StudioLight *sl)
223 {
224         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
225                 char error[256];
226                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED);
227                 ImBuf *ibuf = sl->equirectangular_irradiance_buffer;
228                 sl->equirectangular_irradiance_gputexture = GPU_texture_create_2D(
229                         ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
230                 GPUTexture *tex = sl->equirectangular_irradiance_gputexture;
231                 GPU_texture_bind(tex, 0);
232                 GPU_texture_filter_mode(tex, true);
233                 GPU_texture_wrap_mode(tex, true);
234                 GPU_texture_unbind(tex);
235         }
236         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE;
237 }
238
239 static void studiolight_calculate_radiance_cubemap_buffers(StudioLight *sl)
240 {
241         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
242                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
243                 ImBuf *ibuf = sl->equirectangular_radiance_buffer;
244                 if (ibuf) {
245                         float *colbuf = MEM_mallocN(SQUARE(STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * sizeof(float[4]), __func__);
246                         const float add = 1.0f / (STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE + 1);
247                         const float start = ((1.0f / STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) * 0.5f) - 0.5f;
248
249                         /* front */
250                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, 0.5f, 0, 2, 1);
251                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer(
252                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
253
254                         /* back */
255                         studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, -0.5f, 0, 2, 1);
256                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer(
257                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
258
259                         /* left */
260                         studiolight_calculate_radiance_buffer(ibuf, colbuf, -start, -add, start, add, 0.5f, 1, 2, 0);
261                         sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer(
262                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
263
264                         /* right */
265                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 1, 2, 0);
266                         sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer(
267                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
268
269                         /* top */
270                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, start, add, -0.5f, 0, 1, 2);
271                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer(
272                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
273
274                         /* bottom */
275                         studiolight_calculate_radiance_buffer(ibuf, colbuf, start, add, -start, -add, 0.5f, 0, 1, 2);
276                         sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer(
277                                 NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
278
279 #if 0
280                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], "/tmp/studiolight_radiance_left.png", IB_rectfloat);
281                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], "/tmp/studiolight_radiance_right.png", IB_rectfloat);
282                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], "/tmp/studiolight_radiance_front.png", IB_rectfloat);
283                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], "/tmp/studiolight_radiance_back.png", IB_rectfloat);
284                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], "/tmp/studiolight_radiance_bottom.png", IB_rectfloat);
285                         IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], "/tmp/studiolight_radiance_top.png", IB_rectfloat);
286 #endif
287                         MEM_freeN(colbuf);
288                 }
289         }
290         sl->flag |= STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED;
291 }
292
293 BLI_INLINE void studiolight_evaluate_radiance_buffer(
294         ImBuf *radiance_buffer, const float normal[3], float color[3], int *hits,
295         int xoffset, int yoffset, int zoffset, float zvalue)
296 {
297         if (radiance_buffer == NULL) {
298                 return;
299         }
300         float angle;
301         float *radiance_color = radiance_buffer->rect_float;
302         float direction[3];
303         for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y ++) {
304                 for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x ++) {
305                         // calculate light direction;
306                         direction[zoffset] = zvalue;
307                         direction[xoffset] = (x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
308                         direction[yoffset] = (y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
309                         normalize_v3(direction);
310                         angle = fmax(0.0f, dot_v3v3(direction, normal));
311                         madd_v3_v3fl(color, radiance_color, angle);
312                         (*hits) ++;
313                         radiance_color += 4;
314                 }
315         }
316
317 }
318
319 static void studiolight_calculate_irradiance(StudioLight *sl, float color[3], const float normal[3])
320 {
321         int hits = 0;
322         copy_v3_fl(color, 0.0f);
323
324         /* back */
325         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, &hits, 0, 2, 1, 0.5);
326         /* front */
327         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, &hits, 0, 2, 1, -0.5);
328
329         /* left */
330         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, &hits, 1, 2, 0, 0.5);
331         /* right */
332         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, &hits, 1, 2, 0, -0.5);
333
334         /* top */
335         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, &hits, 0, 1, 2, 0.5);
336         /* bottom */
337         studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, &hits, 0, 1, 2, -0.5);
338
339         if (hits) {
340                 mul_v3_fl(color, 3.0 / hits);
341         }
342         else {
343                 copy_v3_fl3(color, 1.0, 0.0, 1.0);
344         }
345 }
346
347
348 static void studiolight_calculate_diffuse_light(StudioLight *sl)
349 {
350         /* init light to black */
351         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 0.0f);
352         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f);
353         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.0f);
354         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.0f);
355         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.0f);
356         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.0f);
357
358         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
359                 const float normal_x_neg[3] = {-1.0f,  0.0f,  0.0f};
360                 const float normal_x_pos[3] = { 1.0f,  0.0f,  0.0f};
361                 const float normal_y_neg[3] = { 0.0f,  1.0f,  0.0f};
362                 const float normal_y_pos[3] = { 0.0f, -1.0f,  0.0f};
363                 const float normal_z_neg[3] = { 0.0f,  0.0f, -1.0f};
364                 const float normal_z_pos[3] = { 0.0f,  0.0f,  1.0f};
365
366                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED);
367
368                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_X_POS], normal_x_pos);
369                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_X_NEG], normal_x_neg);
370                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Y_POS], normal_y_pos);
371                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Y_NEG], normal_y_neg);
372                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Z_POS], normal_z_pos);
373                 studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Z_NEG], normal_z_neg);
374         }
375         sl->flag |= STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED;
376 }
377
378 static float area_element(float x, float y )
379 {
380         return atan2f(x * y, sqrt(x * x + y * y + 1));
381 }
382
383 static float texel_coord_solid_angle(float a_U, float a_V, int a_Size)
384 {
385         //scale up to [-1, 1] range (inclusive), offset by 0.5 to point to texel center.
386         float u = (2.0f * ((float)a_U + 0.5f) / (float)a_Size ) - 1.0f;
387         float v = (2.0f * ((float)a_V + 0.5f) / (float)a_Size ) - 1.0f;
388
389         float resolution_inv = 1.0f / a_Size;
390
391         // U and V are the -1..1 texture coordinate on the current face.
392         // Get projected area for this texel
393         float x0 = u - resolution_inv;
394         float y0 = v - resolution_inv;
395         float x1 = u + resolution_inv;
396         float y1 = v + resolution_inv;
397         return area_element(x0, y0) - area_element(x0, y1) - area_element(x1, y0) + area_element(x1, y1);
398 }
399
400 BLI_INLINE void studiolight_evaluate_specular_radiance_buffer(
401         ImBuf *radiance_buffer, const float normal[3], float color[3], 
402         int xoffset, int yoffset, int zoffset, float zvalue)
403 {
404         if (radiance_buffer == NULL) {
405                 return;
406         }
407         float angle;
408         float *radiance_color = radiance_buffer->rect_float;
409         float direction[3];
410         for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y ++) {
411                 for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x ++) {
412                         // calculate light direction;
413                         float u = (x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
414                         float v = (y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE) - 0.5f;
415                         direction[zoffset] = zvalue;
416                         direction[xoffset] = u;
417                         direction[yoffset] = v;
418                         normalize_v3(direction);
419                         angle = fmax(0.0f, dot_v3v3(direction, normal)) * texel_coord_solid_angle(x, y, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
420                         madd_v3_v3fl(color, radiance_color, angle);
421                         radiance_color += 4;
422                 }
423         }
424
425 }
426
427 static void studiolight_calculate_specular_irradiance(StudioLight *sl, float color[3], const float normal[3])
428 {
429         copy_v3_fl(color, 0.0f);
430
431         /* back */
432         studiolight_evaluate_specular_radiance_buffer(
433                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, 0, 2, 1, 0.5);
434         /* front */
435         studiolight_evaluate_specular_radiance_buffer(
436                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, 0, 2, 1, -0.5);
437
438         /* left */
439         studiolight_evaluate_specular_radiance_buffer(
440                 sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, 1, 2, 0, 0.5);
441         /* right */
442         studiolight_evaluate_specular_radiance_buffer(
443                 sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, 1, 2, 0, -0.5);
444
445         /* top */
446         studiolight_evaluate_specular_radiance_buffer(
447                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, 0, 1, 2, 0.5);
448         /* bottom */
449         studiolight_evaluate_specular_radiance_buffer(
450                 sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, 0, 1, 2, -0.5);
451
452         mul_v3_fl(color, 1.0 / M_PI);
453 }
454
455 static bool studiolight_load_irradiance_equirectangular_image(StudioLight *sl)
456 {
457 #if 1
458         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
459                 ImBuf *ibuf = NULL;
460                 ibuf = IMB_loadiffname(sl->path_irr, 0, NULL);
461                 if (ibuf) {
462                         IMB_float_from_rect(ibuf);
463                         sl->equirectangular_irradiance_buffer = ibuf;
464                         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED;
465                         return true;
466                 }
467         }
468 #endif
469         return false;
470 }
471
472 static void studiolight_calculate_irradiance_equirectangular_image(StudioLight *sl)
473 {
474         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
475                 /* check for cached irr file */
476                 
477                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED);
478
479                 float *colbuf = MEM_mallocN(STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH * STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT * sizeof(float[4]), __func__);
480                 float *color = colbuf;
481                 for (int y = 0; y < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT ; y ++) {
482                         float yf = y / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT;
483
484                         for (int x = 0; x < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH ; x ++) {
485                                 float xf = x / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH;
486                                 float dir[3];
487                                 equirectangular_to_direction(dir, xf, yf);
488                                 studiolight_calculate_specular_irradiance(sl, color, dir);
489                                 color[3] = 1.0f;
490                                 color += 4;
491                         }
492                 }
493                 sl->equirectangular_irradiance_buffer = IMB_allocFromBuffer(
494                         NULL, colbuf,
495                         STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH,
496                         STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT);
497                 MEM_freeN(colbuf);
498
499                 if (sl->flag | STUDIOLIGHT_USER_DEFINED) {
500                         IMB_saveiff(sl->equirectangular_irradiance_buffer, sl->path_irr, IB_rectfloat);
501                 }
502         }
503         sl->flag |= STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED;
504 }
505
506 static void studiolight_calculate_light_direction(StudioLight *sl)
507 {
508         float best_light = 0.0;
509         sl->light_direction[0] = 0.0f;
510         sl->light_direction[1] = 0.0f;
511         sl->light_direction[2] = -1.0f;
512
513         if ((sl->flag & STUDIOLIGHT_EXTERNAL_FILE) && (sl->flag & STUDIOLIGHT_ORIENTATION_WORLD)) {
514                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED);
515                 ImBuf *ibuf = sl->equirectangular_irradiance_buffer;
516                 if (ibuf) {
517                         /* go over every pixel, determine light, if higher calc direction off the light */
518                         float new_light;
519                         float *color = ibuf->rect_float;
520                         for (int y = 0; y < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT; y ++) {
521                                 for (int x = 0; x < STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH; x ++) {
522                                         new_light = color[0] + color[1] + color[2];
523                                         if (new_light > best_light) {
524                                                 float u = x / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH;
525                                                 float v = y / (float)STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT;
526                                                 equirectangular_to_direction(sl->light_direction, u, v);
527                                                 SWAP(float, sl->light_direction[0], sl->light_direction[1]);
528                                                 normalize_v3(sl->light_direction);
529                                                 negate_v3(sl->light_direction);
530                                                 best_light = new_light;
531                                         }
532                                         color += 4;
533                                 }
534                         }
535                 }
536         }
537         sl->flag |= STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED;
538 }
539
540 static void studiolight_add_files_from_datafolder(const int folder_id, const char *subfolder, int flag)
541 {
542         StudioLight *sl;
543         struct direntry *dir;
544         const char *folder = BKE_appdir_folder_id(folder_id, subfolder);
545         if (folder) {
546                 uint totfile = BLI_filelist_dir_contents(folder, &dir);
547                 int i;
548                 for (i = 0; i < totfile; i++) {
549                         if ((dir[i].type & S_IFREG)) {
550                                 const char *filename = dir[i].relname;
551                                 const char *path = dir[i].path;
552                                 if (BLI_path_extension_check_array(filename, imb_ext_image)) {
553                                         sl = studiolight_create(STUDIOLIGHT_EXTERNAL_FILE | flag);
554                                         BLI_strncpy(sl->name, filename, FILE_MAXFILE);
555                                         BLI_strncpy(sl->path, path, FILE_MAXFILE);
556                                         sl->path_irr = BLI_string_joinN(path, ".irr");
557                                         BLI_addtail(&studiolights, sl);
558                                 }
559                         }
560                 }
561                 BLI_filelist_free(dir, totfile);
562                 dir = NULL;
563         }
564
565 }
566
567 static int studiolight_flag_cmp_order(const StudioLight *sl)
568 {
569         /* Internal studiolights before external studio lights */
570         if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
571                 return 1;
572         }
573         return 0;
574 }
575
576 static int studiolight_cmp(const void *a, const void *b)
577 {
578         const StudioLight *sl1 = a;
579         const StudioLight *sl2 = b;
580
581         const int flagorder1 = studiolight_flag_cmp_order(sl1);
582         const int flagorder2 = studiolight_flag_cmp_order(sl2);
583
584         if (flagorder1 < flagorder2) {
585                 return -1;
586         }
587         else if (flagorder1 > flagorder2) {
588                 return 1;
589         }
590         else {
591                 return BLI_strcasecmp(sl1->name, sl2->name);
592         }
593 }
594
595 /* icons */
596
597 /* Takes normalized uvs as parameter (range from 0 to 1).
598  * inner_edge and outer_edge are distances (from the center)
599  * in uv space for the alpha mask falloff. */
600 static uint alpha_circle_mask(float u, float v, float inner_edge, float outer_edge)
601 {
602         /* Coords from center. */
603         float co[2] = {u - 0.5f, v - 0.5f};
604         float dist = len_v2(co);
605         float alpha = 1.0f + (inner_edge - dist) / (outer_edge - inner_edge);
606         uint mask = (uint)floorf(255.0f * min_ff(max_ff(alpha, 0.0f), 1.0f));
607         return mask << 24;
608 }
609
610 #define STUDIOLIGHT_DIAMETER 0.95f
611
612 static uint *studiolight_radiance_preview(StudioLight *sl, int icon_size)
613 {
614         BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
615
616         uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
617         float pixel_size = 1.0f / (float)icon_size;
618
619         int offset = 0;
620         for (int y = 0; y < icon_size; y++) {
621                 float dy = (y + 0.5f) / (float)icon_size;
622                 dy = dy / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
623                 for (int x = 0; x < icon_size; x++) {
624                         float dx = (x + 0.5f) / (float)icon_size;
625                         dx = dx / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
626
627                         uint pixelresult = 0x0;
628                         uint alphamask = alpha_circle_mask(dx, dy, 0.5f - pixel_size, 0.5f);
629                         if (alphamask != 0) {
630                                 float incoming[3] = {0.0f, 0.0f, -1.0f};
631
632                                 float normal[3];
633                                 normal[0] = dx * 2.0f - 1.0f;
634                                 normal[1] = dy * 2.0f - 1.0f;
635                                 float dist = len_v2(normal);
636                                 normal[2] = sqrtf(1.0f - SQUARE(dist));
637
638                                 float direction[3];
639                                 reflect_v3_v3v3(direction, incoming, normal);
640
641                                 /* We want to see horizon not poles. */
642                                 SWAP(float, direction[1], direction[2]);
643                                 direction[1] = -direction[1];
644
645                                 float color[4];
646                                 studiolight_calculate_radiance(sl->equirectangular_radiance_buffer, color, direction);
647
648                                 pixelresult = rgb_to_cpack(
649                                         linearrgb_to_srgb(color[0]),
650                                         linearrgb_to_srgb(color[1]),
651                                         linearrgb_to_srgb(color[2])) | alphamask;
652                         }
653                         rect[offset++] = pixelresult;
654                 }
655         }
656         return rect;
657 }
658
659 static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size, bool flipped)
660 {
661         BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
662
663         uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
664         float color[4];
665         float fx, fy;
666         float pixel_size = 1.0f / (float)icon_size;
667         int offset = 0;
668         ImBuf *ibuf = sl->equirectangular_radiance_buffer;
669
670         for (int y = 0; y < icon_size; y++) {
671                 fy = (y + 0.5f) / (float)icon_size;
672                 fy = fy / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
673                 for (int x = 0; x < icon_size; x++) {
674                         fx = (x + 0.5f) / (float)icon_size;
675                         fx = fx / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
676                         if (flipped) {
677                                 fx = 1.0f - fx;
678                         }
679                         nearest_interpolation_color(ibuf, NULL, color, fx * ibuf->x, fy * ibuf->y);
680
681                         uint alphamask = alpha_circle_mask(fx, fy, 0.5f - pixel_size, 0.5f);
682
683                         rect[offset++] = rgb_to_cpack(
684                                 linearrgb_to_srgb(color[0]),
685                                 linearrgb_to_srgb(color[1]),
686                                 linearrgb_to_srgb(color[2])) | alphamask;
687                 }
688         }
689         return rect;
690 }
691
692 static uint *studiolight_irradiance_preview(StudioLight *sl, int icon_size)
693 {
694 #if 0
695         if (!(sl->flag & STUDIOLIGHT_EXTERNAL_FILE))
696 #endif
697         {
698
699                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED);
700
701                 uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
702                 float pixel_size = 1.0f / (float)icon_size;
703
704                 int offset = 0;
705                 for (int y = 0; y < icon_size; y++) {
706                         float dy = (y + 0.5f) / (float)icon_size;
707                         dy = dy / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
708                         for (int x = 0; x < icon_size; x++) {
709                                 float dx = (x + 0.5f) / (float)icon_size;
710                                 dx = dx / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
711
712                                 uint pixelresult = 0x0;
713                                 uint alphamask = alpha_circle_mask(dx, dy, 0.5f - pixel_size, 0.5f);
714                                 if (alphamask != 0) {
715                                         /* calculate normal */
716                                         float normal[3];
717                                         normal[0] = dx * 2.0f - 1.0f;
718                                         normal[1] = dy * 2.0f - 1.0f;
719                                         float dist = len_v2(normal);
720                                         normal[2] = sqrtf(1.0f - SQUARE(dist));
721
722                                         float color[3];
723                                         mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0));
724                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0));
725                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[1], 0.0, 1.0));
726                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_NEG], clamp_f(-normal[1], 0.0, 1.0));
727                                         interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[2], 0.0, 1.0));
728
729                                         pixelresult = rgb_to_cpack(
730                                                 linearrgb_to_srgb(color[0]),
731                                                 linearrgb_to_srgb(color[1]),
732                                                 linearrgb_to_srgb(color[2])) | alphamask;
733                                 }
734                                 rect[offset++] = pixelresult;
735                         }
736                 }
737                 return rect;
738         }
739 #if 0
740         else {
741                 BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED);
742
743                 uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
744                 int icon_center = icon_size / 2;
745                 float sphere_radius = icon_center * 0.9;
746
747                 int offset = 0;
748                 for (int y = 0; y < icon_size; y++) {
749                         float dy = y - icon_center;
750                         for (int x = 0; x < icon_size; x++) {
751                                 float dx = x - icon_center;
752                                 /* calculate aliasing */
753                                 float alias = 0;
754                                 const float alias_step = 0.333;
755                                 for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) {
756                                         for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) {
757                                                 if (sqrt(ay * ay + ax * ax) < sphere_radius) {
758                                                         alias += alias_step * alias_step;
759                                                 }
760                                         }
761                                 }
762                                 uint pixelresult = 0x0;
763                                 uint alias_i = clamp_i(alias * 256, 0, 255);
764                                 if (alias_i != 0) {
765                                         /* calculate normal */
766                                         uint alias_mask = alias_i << 24;
767                                         float incoming[3];
768                                         copy_v3_fl3(incoming, 0.0, 1.0, 0.0);
769
770                                         float normal[3];
771                                         normal[0] = dx / sphere_radius;
772                                         normal[2] = dy / sphere_radius;
773                                         normal[1] = -sqrt(-(normal[0] * normal[0]) - (normal[2] * normal[2]) + 1);
774                                         normalize_v3(normal);
775
776                                         float direction[3];
777                                         reflect_v3_v3v3(direction, incoming, normal);
778
779                                         float color[4];
780                                         studiolight_calculate_radiance(sl->equirectangular_irradiance_buffer, color, direction);
781
782                                         pixelresult = rgb_to_cpack(
783                                                 linearrgb_to_srgb(color[0]),
784                                                 linearrgb_to_srgb(color[1]),
785                                                 linearrgb_to_srgb(color[2])) | alias_mask;
786                                 }
787                                 rect[offset++] = pixelresult;
788                         }
789                 }
790                 return rect;
791         }
792 #endif
793 }
794
795 /* API */
796 void BKE_studiolight_init(void)
797 {
798         StudioLight *sl;
799         /* go over the preset folder and add a studiolight for every image with its path */
800         /* order studio lights by name */
801         /* Also reserve icon space for it. */
802         /* Add default studio light */
803         sl = studiolight_create(STUDIOLIGHT_INTERNAL | STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED | STUDIOLIGHT_ORIENTATION_CAMERA);
804         BLI_strncpy(sl->name, "INTERNAL_01", FILE_MAXFILE);
805         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 1.5f);
806         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f);
807         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.8f);
808         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.05f);
809         copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.2f);
810         copy_v3_fl3(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.1f, 0.0f, 0.0f);
811         BLI_addtail(&studiolights, sl);
812
813         studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_CAMERA_FOLDER, STUDIOLIGHT_ORIENTATION_CAMERA);
814         studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,   STUDIOLIGHT_CAMERA_FOLDER, STUDIOLIGHT_ORIENTATION_CAMERA | STUDIOLIGHT_USER_DEFINED);
815         studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_WORLD_FOLDER,  STUDIOLIGHT_ORIENTATION_WORLD);
816         studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,   STUDIOLIGHT_WORLD_FOLDER,  STUDIOLIGHT_ORIENTATION_WORLD | STUDIOLIGHT_USER_DEFINED);
817         studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_MATCAP_FOLDER, STUDIOLIGHT_ORIENTATION_VIEWNORMAL);
818         studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,   STUDIOLIGHT_MATCAP_FOLDER, STUDIOLIGHT_ORIENTATION_VIEWNORMAL | STUDIOLIGHT_USER_DEFINED);
819
820         /* sort studio lights on filename. */
821         BLI_listbase_sort(&studiolights, studiolight_cmp);
822 }
823
824 void BKE_studiolight_free(void)
825 {
826         struct StudioLight *sl;
827         while ((sl = BLI_pophead(&studiolights))) {
828                 studiolight_free(sl);
829         }
830 }
831
832 struct StudioLight *BKE_studiolight_find_first(int flag)
833 {
834         LISTBASE_FOREACH(StudioLight *, sl, &studiolights) {
835                 if ((sl->flag & flag)) {
836                         return sl;
837                 }
838         }
839         return NULL;
840 }
841
842 struct StudioLight *BKE_studiolight_find(const char *name, int flag)
843 {
844         LISTBASE_FOREACH(StudioLight *, sl, &studiolights) {
845                 if (STREQLEN(sl->name, name, FILE_MAXFILE)) {
846                         if ((sl->flag & flag)) {
847                                 return sl;
848                         }
849                         else {
850                                 /* flags do not match, so use default */
851                                 return BKE_studiolight_find_first(flag);
852                         }
853                 }
854         }
855         /* When not found, use the default studio light */
856         return BKE_studiolight_find_first(flag);
857 }
858
859 struct StudioLight *BKE_studiolight_findindex(int index, int flag)
860 {
861         LISTBASE_FOREACH(StudioLight *, sl, &studiolights) {
862                 if (sl->index == index) {
863                         return sl;
864                 }
865         }
866         /* When not found, use the default studio light */
867         return BKE_studiolight_find_first(flag);
868 }
869
870 struct ListBase *BKE_studiolight_listbase(void)
871 {
872         return &studiolights;
873 }
874
875 uint *BKE_studiolight_preview(StudioLight *sl, int icon_size, int icon_id_type)
876 {
877         switch (icon_id_type) {
878                 case STUDIOLIGHT_ICON_ID_TYPE_RADIANCE:
879                 default:
880                         return studiolight_radiance_preview(sl, icon_size);
881                 case STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE:
882                         return studiolight_irradiance_preview(sl, icon_size);
883                 case STUDIOLIGHT_ICON_ID_TYPE_MATCAP:
884                         return studiolight_matcap_preview(sl, icon_size, false);
885                 case STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED:
886                         return studiolight_matcap_preview(sl, icon_size, true);
887         }
888 }
889
890 void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
891 {
892         if ((sl->flag & flag) == flag) {
893                 return;
894         }
895
896         if ((flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED)) {
897                 studiolight_load_equirectangular_image(sl);
898         }
899         if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) {
900                 studiolight_calculate_radiance_cubemap_buffers(sl);
901         }
902         if ((flag & STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED)) {
903                 studiolight_calculate_diffuse_light(sl);
904         }
905         if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_RADIANCE_GPUTEXTURE)) {
906                 studiolight_create_equirectangular_radiance_gputexture(sl);
907         }
908         if ((flag & STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED)) {
909                 studiolight_calculate_light_direction(sl);
910         }
911         if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_GPUTEXTURE)) {
912                 studiolight_create_equirectangular_irradiance_gputexture(sl);
913         }
914         if ((flag & STUDIOLIGHT_EQUIRECTANGULAR_IRRADIANCE_IMAGE_CALCULATED)) {
915                 if (!studiolight_load_irradiance_equirectangular_image(sl)) {
916                         studiolight_calculate_irradiance_equirectangular_image(sl);
917                 }
918         }
919 }
920
921 void BKE_studiolight_refresh(void)
922 {
923         BKE_studiolight_free();
924         BKE_studiolight_init();
925 }