From d3c4248946f65d287f18b3d6488cd450dfb6d81d Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 11 May 2018 16:55:14 +0200 Subject: Workbench: StudioLight HDRI's The Studio lights are now loaded from disk. The location is `datafiles/studiolights` they need to be JPG for now. JPG cannot store HDRI color range but they are clamped inside the Workbench engine for speed reason. I didn't select JP2K as it might not be enabled. Users can add upto 20 HDRI files. This limitation is inside the RNA_space.c Currently the icons are calculated when you first open the selection box for the HDRI's. We could add them to a background rendering later. I added 2 test files a sky texture rendered in Cycles and an HDRI from cloud.blender.org. --- source/blender/blenkernel/BKE_icons.h | 4 + source/blender/blenkernel/BKE_studiolight.h | 73 +++++ source/blender/blenkernel/CMakeLists.txt | 2 + source/blender/blenkernel/intern/icons.c | 11 + source/blender/blenkernel/intern/studiolight.c | 297 +++++++++++++++++++++ source/blender/draw/DRW_engine.h | 1 - .../draw/engines/workbench/workbench_materials.c | 5 +- .../draw/engines/workbench/workbench_private.h | 5 +- .../draw/engines/workbench/workbench_studiolight.c | 117 +------- source/blender/editors/include/UI_icons.h | 7 - source/blender/editors/interface/interface_icons.c | 34 +-- source/blender/makesdna/DNA_view3d_types.h | 3 +- source/blender/makesrna/intern/rna_space.c | 75 +++++- source/blender/windowmanager/intern/wm_init_exit.c | 4 +- source/creator/CMakeLists.txt | 8 + 15 files changed, 496 insertions(+), 150 deletions(-) create mode 100644 source/blender/blenkernel/BKE_studiolight.h create mode 100644 source/blender/blenkernel/intern/studiolight.c (limited to 'source') diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 766704b8f9c..e54531bdb0e 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -43,6 +43,7 @@ enum { ICON_DATA_PREVIEW, /** 2D triangles: obj is #Icon_Geom */ ICON_DATA_GEOM, + ICON_DATA_STUDIOLIGHT, }; struct Icon { @@ -77,6 +78,7 @@ typedef struct Icon Icon; struct ImBuf; struct PreviewImage; struct ID; +struct StudioLight; enum eIconSizes; @@ -158,6 +160,8 @@ struct ImBuf *BKE_icon_geom_rasterize( const struct Icon_Geom *geom, const unsigned int size_x, const unsigned int size_y); +int BKE_icon_ensure_studio_light(struct StudioLight *sl); + #define ICON_RENDER_DEFAULT_HEIGHT 32 #endif /* __BKE_ICONS_H__ */ diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h new file mode 100644 index 00000000000..c65e9050157 --- /dev/null +++ b/source/blender/blenkernel/BKE_studiolight.h @@ -0,0 +1,73 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006-2007 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_STUDIOLIGHT_H__ +#define __BKE_STUDIOLIGHT_H__ + +/** \file BKE_studiolight.h + * \ingroup bke + * + * Studio lighting for the 3dview + */ + +#include "BLI_sys_types.h" + +#include "DNA_space_types.h" + +#define STUDIOLIGHT_X_POS 0 +#define STUDIOLIGHT_X_NEG 1 +#define STUDIOLIGHT_Y_POS 2 +#define STUDIOLIGHT_Y_NEG 3 +#define STUDIOLIGHT_Z_POS 4 +#define STUDIOLIGHT_Z_NEG 5 + +enum StudioLightFlag +{ + STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED = (1 << 0), + STUDIOLIGHT_EXTERNAL_FILE = (1 << 1), +} StudioLightFlag; + +typedef struct StudioLight +{ + struct StudioLight *next, *prev; + int flag; + char name[FILE_MAXFILE]; + char path[FILE_MAX]; + int icon_id; + int index; + float diffuse_light[6][3]; +} StudioLight; + +void BKE_studiolight_init(void); +void BKE_studiolight_free(void); +struct StudioLight *BKE_studiolight_find(const char* name); +struct StudioLight *BKE_studiolight_findindex(int index); +unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size); +const struct ListBase *BKE_studiolight_listbase(void); +void BKE_studiolight_ensure_flag(StudioLight *sl, int flag); + +#endif /* __BKE_STUDIOLIGHT_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 37e08cedb10..d5ce6f2f94d 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -185,6 +185,7 @@ set(SRC intern/softbody.c intern/sound.c intern/speaker.c + intern/studiolight.c intern/subsurf_ccg.c intern/suggestions.c intern/text.c @@ -303,6 +304,7 @@ set(SRC BKE_softbody.h BKE_sound.h BKE_speaker.h + BKE_studiolight.h BKE_subsurf.h BKE_suggestions.h BKE_text.h diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index f1f343faac8..61c05c2500d 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -56,6 +56,7 @@ #include "BKE_icons.h" #include "BKE_global.h" /* only for G.background test */ +#include "BKE_studiolight.h" #include "BLI_sys_types.h" // for intptr_t support @@ -802,3 +803,13 @@ struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) } /** \} */ + +/** \name Studio Light Icon + * \{ */ +int BKE_icon_ensure_studio_light(struct StudioLight *sl) { + int icon_id = get_next_free_id(); + icon_create(icon_id, ICON_DATA_STUDIOLIGHT, sl); + return icon_id; +} +/** \} */ + diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c new file mode 100644 index 00000000000..9bc678a1820 --- /dev/null +++ b/source/blender/blenkernel/intern/studiolight.c @@ -0,0 +1,297 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006-2007 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file blender/blenkernel/intern/studiolight.c + * \ingroup bke + */ + +#include "BKE_studiolight.h" + +#include "BKE_appdir.h" +#include "BKE_icons.h" + +#include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "DNA_listBase.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "MEM_guardedalloc.h" + + +/* Statics */ +static ListBase studiolights; +static const char *STUDIO_LIGHT_FOLDER = "studiolights/"; + +/* FUNCTIONS */ +static void studiolight_free(struct StudioLight *sl) +{ + MEM_freeN(sl); +} + +static struct StudioLight *studiolight_create(void) +{ + struct StudioLight *sl = MEM_callocN(sizeof(*sl), __func__); + sl->path[0] = 0x00; + sl->name[0] = 0x00; + sl->flag = 0; + sl->index = BLI_listbase_count(&studiolights); + sl->icon_id = BKE_icon_ensure_studio_light(sl); + return sl; +} + +static void direction_to_equirectangular(float r[2], const float dir[3]) +{ + r[0] = (atan2f(dir[1], dir[0]) - M_PI) / -(M_PI * 2); + r[1] = (acosf(dir[2] / 1.0) - M_PI) / -M_PI; +} + +static void studiolight_calculate_directional_diffuse_light(ImBuf *ibuf, float color[4], const float start[3], const float v1[3], const float v2[3], int steps) +{ + float uv[2]; + float dir[3]; + float col[4]; + float v11[3]; + float v12[3]; + float totcol[4]; + + zero_v4(totcol); + for (int x = 0; x < steps ; x++) { + float xf = (float)x / (float)steps; + mul_v3_v3fl(v11, v1, xf); + for (int y = 0; y < steps; y++) { + float yf = (float)y / (float)steps; + /* start + x/steps*v1 + y/steps*v2 */ + mul_v3_v3fl(v12, v2, yf); + add_v3_v3v3(dir, start, v11); + add_v3_v3(dir, v12); + /* normalize */ + normalize_v3(dir); + + /* sample */ + direction_to_equirectangular(uv, dir); + nearest_interpolation_color_wrap(ibuf, NULL, col, uv[0] * ibuf->x, uv[1] * ibuf->y); + add_v3_v3(totcol, col); + } + } + mul_v3_v3fl(color, totcol, 1.0/(steps*steps)); +} + +static void studiolight_calculate_diffuse_light(StudioLight *sl) +{ + const int steps = 16; + float start[3]; + float v1[3]; + float v2[3]; + + /* init light to black */ + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.0f); + + if (sl->flag &= STUDIOLIGHT_EXTERNAL_FILE) { + ImBuf* ibuf = NULL; + ibuf = IMB_loadiffname(sl->path, 0, NULL); + if (ibuf) { + IMB_float_from_rect(ibuf); + + copy_v3_fl3(start, -1.0f, -1.0f, -1.0f); + copy_v3_fl3(v1, 0.0f, 2.0f, 0.0f); + copy_v3_fl3(v2, 0.0f, 0.0f, 2.0f); + studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Z_NEG], start, v1, v2, steps); + copy_v3_fl3(start, 1.0f, -1.0f, -1.0f); + studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Z_POS], start, v1, v2, steps); + + copy_v3_fl3(start, -1.0f, -1.0f, -1.0f); + copy_v3_fl3(v1, 2.0f, 0.0f, 0.0f); + copy_v3_fl3(v2, 0.0f, 0.0f, 2.0f); + studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_X_POS], start, v1, v2, steps); + copy_v3_fl3(start, -1.0f, 1.0f, -1.0f); + studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_X_NEG], start, v1, v2, steps); + + copy_v3_fl3(start, -1.0f, -1.0f, -1.0f); + copy_v3_fl3(v1, 2.0f, 0.0f, 0.0f); + copy_v3_fl3(v2, 0.0f, 2.0f, 0.0f); + studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Y_NEG], start, v1, v2, steps); + copy_v3_fl3(start, -1.0f, -1.0f, 1.0f); + studiolight_calculate_directional_diffuse_light(ibuf, sl->diffuse_light[STUDIOLIGHT_Y_POS], start, v1, v2, steps); + + IMB_freeImBuf(ibuf); + } + } + sl->flag |= STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED; +} + + +/* API */ +void BKE_studiolight_init(void) +{ + StudioLight *sl; + /* go over the preset folder and add a studiolight for every image with its path */ + /* order studio lights by name */ + /* Also reserve icon space for it. */ + /* Add default studio light */ + sl = studiolight_create(); + BLI_strncpy(sl->name, "INTERNAL_01\0", FILE_MAXFILE); + sl->flag = STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED; + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 1.0f); + copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.0f); + BLI_addtail(&studiolights, sl); + + struct direntry *dir; + const char *folder = BKE_appdir_folder_id(BLENDER_DATAFILES, STUDIO_LIGHT_FOLDER); + unsigned int totfile = BLI_filelist_dir_contents(folder, &dir); + int i; + for (i = 0; i < totfile; i++) { + if ((dir[i].type & S_IFREG)) { + const char *filename = dir[i].relname; + const char *path = dir[i].path; + if (BLI_testextensie(filename, ".jpg")) { + sl = studiolight_create(); + sl->flag = STUDIOLIGHT_EXTERNAL_FILE; + BLI_strncpy(sl->name, filename, FILE_MAXFILE); + BLI_strncpy(sl->path, path, FILE_MAXFILE); + BLI_addtail(&studiolights, sl); + } + } + } + BLI_filelist_free(dir, totfile); + dir = NULL; +} + +void BKE_studiolight_free(void) +{ + struct StudioLight *sl; + while((sl = (StudioLight*)BLI_pophead(&studiolights))) + { + studiolight_free(sl); + } +} + +struct StudioLight *BKE_studiolight_find(const char* name) +{ + LISTBASE_FOREACH(StudioLight *, sl, &studiolights) { + if (STREQLEN(sl->name, name, FILE_MAXFILE)) { + return sl; + } + } + /* When not found, use the default studio light */ + return (StudioLight*)studiolights.first; +} + +struct StudioLight *BKE_studiolight_findindex(int index) +{ + LISTBASE_FOREACH(StudioLight *, sl, &studiolights) { + if (sl->index == index) { + return sl; + } + } + /* When not found, use the default studio light */ + return (StudioLight*)studiolights.first; +} + +const struct ListBase *BKE_studiolight_listbase(void) +{ + return &studiolights; +} + +unsigned int *BKE_studiolight_preview(StudioLight *sl, int icon_size) +{ + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); + + uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); + int icon_center = icon_size / 2; + float sphere_radius = icon_center * 0.9; + + int offset = 0; + for (int y = 0; y < icon_size; y++) { + float dy = y - icon_center; + for (int x = 0; x < icon_size; x++) { + float dx = x - icon_center; + /* calculate aliasing */ + float alias = 0; + const float alias_step = 0.333; + for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { + for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { + if (sqrt(ay * ay + ax * ax) < sphere_radius) { + alias += alias_step * alias_step; + } + } + } + uint pixelresult = 0x0; + uint alias_i = clamp_i(alias * 256, 0, 255); + if (alias_i != 0) { + /* calculate normal */ + uint alias_mask = alias_i << 24; + float normal[3]; + normal[0] = dx / sphere_radius; + normal[1] = dy / sphere_radius; + normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1); + normalize_v3(normal); + + float color[3]; + mul_v3_v3fl(color, sl->diffuse_light[STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_POS], clamp_f(normal[1], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Y_NEG], clamp_f(-normal[1], 0.0, 1.0)); + interp_v3_v3v3(color, color, sl->diffuse_light[STUDIOLIGHT_Z_POS], clamp_f(normal[2], 0.0, 1.0)); + + pixelresult = rgb_to_cpack( + linearrgb_to_srgb(color[0]), + linearrgb_to_srgb(color[1]), + linearrgb_to_srgb(color[2])) | alias_mask; + } + rect[offset++] = pixelresult; + } + } + return rect; +} + +void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) +{ + if (sl->flag & flag){ + return; + } + + if ((flag & STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED)) { + studiolight_calculate_diffuse_light(sl); + } +} diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index a1a2a36e75a..524a94e5886 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -135,5 +135,4 @@ void DRW_opengl_context_disable(void); void DRW_deferred_shader_remove(struct GPUMaterial *mat); -uint *WORKBENCH_generate_studiolight_preview(int studiolight_id, int icon_size); #endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 0fee42619c3..680ac264233 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -338,6 +338,7 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata) if (v3d) { wpd->shading = v3d->shading; wpd->drawtype = v3d->drawtype; + wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light); } else { /* XXX: We should get the default shading from the view layer, after we implemented the render callback */ @@ -346,7 +347,9 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata) wpd->shading.shadow_intensity = 0.5; copy_v3_fl(wpd->shading.single_color, 0.8f); wpd->drawtype = OB_SOLID; + wpd->studio_light = BKE_studiolight_findindex(0); } + BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED); select_deferred_shaders(wpd); /* Deferred Mix Pass */ @@ -360,7 +363,7 @@ void workbench_materials_cache_init(WORKBENCH_Data *vedata) srgb_to_linearrgb_v3_v3(wd->background_color_high, wd->background_color_high); srgb_to_linearrgb_v3_v3(wd->background_color_low, wd->background_color_low); - studiolight_update_world(wpd->shading.studio_light, wd); + studiolight_update_world(wpd->studio_light, wd); wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), NULL); DRW_uniformbuffer_update(wpd->world_ubo, &wpd->world_data); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 7a646d056b5..dde62302f62 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -27,6 +27,8 @@ #define __WORKBENCH_PRIVATE_H__ +#include "BKE_studiolight.h" + #include "DNA_image_types.h" #include "DNA_view3d_types.h" @@ -81,6 +83,7 @@ typedef struct WORKBENCH_PrivateData { struct GPUShader *prepass_texture_sh; struct GPUShader *composite_sh; View3DShading shading; + StudioLight *studio_light; int drawtype; struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; @@ -127,6 +130,6 @@ void workbench_materials_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob void workbench_materials_cache_finish(WORKBENCH_Data *vedata); /* workbench_studiolight.c */ -void studiolight_update_world(int studio_light, WORKBENCH_UBO_World *wd); +void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd); #endif diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c index 5b1d4432ca7..f7d107ea403 100644 --- a/source/blender/draw/engines/workbench/workbench_studiolight.c +++ b/source/blender/draw/engines/workbench/workbench_studiolight.c @@ -22,118 +22,19 @@ /** \file workbench_studiolight.c * \ingroup draw_engine */ +#include "BKE_studiolight.h" + #include "DRW_engine.h" #include "workbench_private.h" #include "BLI_math.h" - -#define STUDIOLIGHT_X_POS 0 -#define STUDIOLIGHT_X_NEG 1 -#define STUDIOLIGHT_Y_POS 2 -#define STUDIOLIGHT_Y_NEG 3 -#define STUDIOLIGHT_Z_POS 4 -#define STUDIOLIGHT_Z_NEG 5 - -const float studiolights[][6][3] = { - { - {1.0, 0.8, 0.6}, - {1.0, 0.6, 0.6}, - {0.9, 0.9, 1.0}, - {0.05, 0.025, 0.025}, - {0.8, 0.8, 0.75}, - {1.0, 0.95, 0.8}, - }, - { - {0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0}, - {0.0, 0.0, 0.0}, - {0.8, 0.8, 1.0}, - {0.0, 0.0, 0.0}, - }, - { - {0.4, 0.3, 0.8}, - {0.4, 0.3, 0.8}, - {0.8, 0.8, 0.2}, - {0.0, 0.0, 0.0}, - {0.4, 0.4, 0.8}, - {0.0, 0.0, 0.0}, - }, - { - {0.2, 0.2, 0.0}, - {0.8, 0.2, 0.0}, - {0.8, 0.2, 0.0}, - {0.2, 0.2, 0.0}, - {0.8, 0.6, 0.4}, - {0.0, 0.0, 0.0}, - }, - { - {0.8, 0.2, 0.0}, - {0.8, 0.2, 0.0}, - {0.8, 0.6, 0.0}, - {0.2, 0.2, 0.0}, - {1.0, 0.5, 0.0}, - {0.0, 0.0, 0.0}, - }, -}; - -void studiolight_update_world(int studio_light, WORKBENCH_UBO_World *wd) -{ - copy_v3_v3(wd->diffuse_light_x_pos, studiolights[studio_light][STUDIOLIGHT_X_POS]); - copy_v3_v3(wd->diffuse_light_x_neg, studiolights[studio_light][STUDIOLIGHT_X_NEG]); - copy_v3_v3(wd->diffuse_light_y_pos, studiolights[studio_light][STUDIOLIGHT_Y_POS]); - copy_v3_v3(wd->diffuse_light_y_neg, studiolights[studio_light][STUDIOLIGHT_Y_NEG]); - copy_v3_v3(wd->diffuse_light_z_pos, studiolights[studio_light][STUDIOLIGHT_Z_POS]); - copy_v3_v3(wd->diffuse_light_z_neg, studiolights[studio_light][STUDIOLIGHT_Z_NEG]); -} - -uint *WORKBENCH_generate_studiolight_preview(int studiolight_id, int icon_size) +void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd) { - uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__); - int icon_center = icon_size / 2; - float sphere_radius = icon_center * 0.9; - - int offset = 0; - for (int y = 0; y < icon_size; y++) { - float dy = y - icon_center; - for (int x = 0; x < icon_size; x++) { - float dx = x - icon_center; - /* calculate aliasing */ - float alias = 0; - const float alias_step = 0.2; - for (float ay = dy - 0.5; ay < dy + 0.5; ay += alias_step) { - for (float ax = dx - 0.5; ax < dx + 0.5; ax += alias_step) { - if (sqrt(ay * ay + ax * ax) < sphere_radius) { - alias += alias_step * alias_step; - } - } - } - uint pixelresult = 0x0; - uint alias_i = clamp_i(alias * 256, 0, 255); - if (alias_i != 0) { - /* calculate normal */ - uint alias_mask = alias_i << 24; - float normal[3]; - normal[0] = dx / sphere_radius; - normal[1] = dy / sphere_radius; - normal[2] = sqrt(-(normal[0] * normal[0]) - (normal[1] * normal[1]) + 1); - normalize_v3(normal); - - float color[3]; - mul_v3_v3fl(color, studiolights[studiolight_id][STUDIOLIGHT_X_POS], clamp_f(normal[0], 0.0, 1.0)); - interp_v3_v3v3(color, color, studiolights[studiolight_id][STUDIOLIGHT_X_NEG], clamp_f(-normal[0], 0.0, 1.0)); - interp_v3_v3v3(color, color, studiolights[studiolight_id][STUDIOLIGHT_Y_POS], clamp_f(normal[1], 0.0, 1.0)); - interp_v3_v3v3(color, color, studiolights[studiolight_id][STUDIOLIGHT_Y_NEG], clamp_f(-normal[1], 0.0, 1.0)); - interp_v3_v3v3(color, color, studiolights[studiolight_id][STUDIOLIGHT_Z_POS], clamp_f(normal[2], 0.0, 1.0)); - - pixelresult = rgb_to_cpack( - linearrgb_to_srgb(color[0]), - linearrgb_to_srgb(color[1]), - linearrgb_to_srgb(color[2])) | alias_mask; - } - rect[offset++] = pixelresult; - } - } - return rect; + copy_v3_v3(wd->diffuse_light_x_pos, sl->diffuse_light[STUDIOLIGHT_X_POS]); + copy_v3_v3(wd->diffuse_light_x_neg, sl->diffuse_light[STUDIOLIGHT_X_NEG]); + copy_v3_v3(wd->diffuse_light_y_pos, sl->diffuse_light[STUDIOLIGHT_Y_POS]); + copy_v3_v3(wd->diffuse_light_y_neg, sl->diffuse_light[STUDIOLIGHT_Y_NEG]); + copy_v3_v3(wd->diffuse_light_z_pos, sl->diffuse_light[STUDIOLIGHT_Z_POS]); + copy_v3_v3(wd->diffuse_light_z_neg, sl->diffuse_light[STUDIOLIGHT_Z_NEG]); } diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index b0ee6773e7a..6a9067ef95d 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -1031,10 +1031,3 @@ DEF_VICO(COLORSET_17_VEC) DEF_VICO(COLORSET_18_VEC) DEF_VICO(COLORSET_19_VEC) DEF_VICO(COLORSET_20_VEC) - - /* Studio lighting presets */ -DEF_ICON(STUDIOLIGHT_01) -DEF_ICON(STUDIOLIGHT_02) -DEF_ICON(STUDIOLIGHT_03) -DEF_ICON(STUDIOLIGHT_04) -DEF_ICON(STUDIOLIGHT_05) diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index afd57fdcd05..9f5c2005878 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -58,6 +58,7 @@ #include "BKE_global.h" #include "BKE_icons.h" #include "BKE_appdir.h" +#include "BKE_studiolight.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -493,23 +494,6 @@ static void init_matcap_icons(void) } -static void init_studio_light_icons(void) -{ - /* dynamic allocation now, tucking datatoc pointers in DrawInfo */ -#define INIT_STUDIOLIGHT_ICON(icon_id, studiolight_id) \ - { \ - DrawInfo *di; \ - di = def_internal_icon(NULL, icon_id, 0, 0, 96, ICON_TYPE_BUFFER); \ - di->data.buffer.image->rect = WORKBENCH_generate_studiolight_preview(studiolight_id, 96); \ - } (void)0 - - INIT_STUDIOLIGHT_ICON(ICON_STUDIOLIGHT_01, 0); - INIT_STUDIOLIGHT_ICON(ICON_STUDIOLIGHT_02, 1); - INIT_STUDIOLIGHT_ICON(ICON_STUDIOLIGHT_03, 2); - INIT_STUDIOLIGHT_ICON(ICON_STUDIOLIGHT_04, 3); - INIT_STUDIOLIGHT_ICON(ICON_STUDIOLIGHT_05, 4); - -} static void init_internal_icons(void) { // bTheme *btheme = UI_GetTheme(); @@ -779,8 +763,9 @@ void UI_icons_free_drawinfo(void *drawinfo) /** * #Icon.data_type and #Icon.obj */ -static DrawInfo *icon_create_drawinfo(int icon_data_type) +static DrawInfo *icon_create_drawinfo(Icon *icon) { + int icon_data_type = icon->obj_type; DrawInfo *di = NULL; di = MEM_callocN(sizeof(DrawInfo), "di_icon"); @@ -791,6 +776,16 @@ static DrawInfo *icon_create_drawinfo(int icon_data_type) else if (icon_data_type == ICON_DATA_GEOM) { di->type = ICON_TYPE_GEOM; } + else if (icon_data_type == ICON_DATA_STUDIOLIGHT) { + const int STUDIOLIGHT_SIZE = 96; + StudioLight *sl = icon->obj; + di->type = ICON_TYPE_BUFFER; + IconImage *img = MEM_mallocN(sizeof(IconImage), __func__); + img->w = STUDIOLIGHT_SIZE; + img->h = STUDIOLIGHT_SIZE; + img->rect = BKE_studiolight_preview(sl, STUDIOLIGHT_SIZE); + di->data.buffer.image = img; + } else { BLI_assert(0); } @@ -803,7 +798,7 @@ static DrawInfo *icon_ensure_drawinfo(Icon *icon) if (icon->drawinfo) { return icon->drawinfo; } - DrawInfo *di = icon_create_drawinfo(icon->obj_type); + DrawInfo *di = icon_create_drawinfo(icon); icon->drawinfo = di; icon->drawinfo_free = UI_icons_free_drawinfo; return di; @@ -856,7 +851,6 @@ void UI_icons_init(int first_dyn_id) init_internal_icons(); init_brush_icons(); init_matcap_icons(); - init_studio_light_icons(); #endif } diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index cf078bc203d..8a92ad25c92 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -138,7 +138,8 @@ typedef struct View3DShading { short color_type; short light; - short studio_light; + char pad[2]; + char studio_light[256]; /* FILE_MAXFILE */ float shadow_intensity; float single_color[3]; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 124a0477f4c..d8c3fdd7a64 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -35,6 +35,7 @@ #include "BKE_key.h" #include "BKE_movieclip.h" #include "BKE_node.h" +#include "BKE_studiolight.h" #include "DNA_action_types.h" #include "DNA_key_types.h" @@ -191,6 +192,31 @@ const EnumPropertyItem rna_enum_viewport_lighting_items[] = { {0, NULL, 0, NULL, NULL} }; +static const EnumPropertyItem rna_enum_studio_light_items[] = { + {0, "STUDIOLIGHT_01", 0, "", ""}, + {1, "STUDIOLIGHT_02", 0, "", ""}, + {2, "STUDIOLIGHT_03", 0, "", ""}, + {3, "STUDIOLIGHT_04", 0, "", ""}, + {4, "STUDIOLIGHT_05", 0, "", ""}, + {5, "STUDIOLIGHT_06", 0, "", ""}, + {6, "STUDIOLIGHT_07", 0, "", ""}, + {7, "STUDIOLIGHT_08", 0, "", ""}, + {8, "STUDIOLIGHT_09", 0, "", ""}, + {9, "STUDIOLIGHT_10", 0, "", ""}, + {10, "STUDIOLIGHT_11", 0, "", ""}, + {11, "STUDIOLIGHT_12", 0, "", ""}, + {12, "STUDIOLIGHT_13", 0, "", ""}, + {13, "STUDIOLIGHT_14", 0, "", ""}, + {14, "STUDIOLIGHT_15", 0, "", ""}, + {15, "STUDIOLIGHT_16", 0, "", ""}, + {16, "STUDIOLIGHT_17", 0, "", ""}, + {17, "STUDIOLIGHT_18", 0, "", ""}, + {18, "STUDIOLIGHT_19", 0, "", ""}, + {19, "STUDIOLIGHT_20", 0, "", ""}, + {0, NULL, 0, NULL, NULL} +}; +#define NUM_STUDIO_LIGHT_ITEMS 20 + const EnumPropertyItem rna_enum_clip_editor_mode_items[] = { {SC_MODE_TRACKING, "TRACKING", ICON_ANIM_DATA, "Tracking", "Show tracking and solving tools"}, {SC_MODE_MASKEDIT, "MASK", ICON_MOD_MASK, "Mask", "Show mask editing tools"}, @@ -705,6 +731,42 @@ static const EnumPropertyItem *rna_3DViewShading_type_itemf( return item; } +static int rna_View3DShading_studio_light_get(PointerRNA *ptr) +{ + /* XXX: should be stored as string */ + View3D *v3d = (View3D *)ptr->data; + StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light); + return sl->index; +} + +static void rna_View3DShading_studio_light_set(PointerRNA *ptr, int value) +{ + /* XXX: should be stored as string */ + View3D *v3d = (View3D *)ptr->data; + StudioLight *sl = BKE_studiolight_findindex(value); + BLI_strncpy(v3d->shading.studio_light, sl->name, FILE_MAXFILE); +} + +static const EnumPropertyItem *rna_View3DShading_studio_light_itemf( + bContext *UNUSED(C), PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), bool *r_free) +{ + EnumPropertyItem *item = NULL; + int totitem = 0; + + /* XXX: add studio lights */ + LISTBASE_FOREACH(StudioLight*, sl, BKE_studiolight_listbase()) { + if (totitem < NUM_STUDIO_LIGHT_ITEMS) { + RNA_enum_items_add_value(&item, &totitem, rna_enum_studio_light_items, totitem); + item[totitem-1].icon = sl->icon_id; + } + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + return item; +} + static const EnumPropertyItem *rna_SpaceView3D_stereo3d_camera_itemf( bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *UNUSED(r_free)) @@ -2156,14 +2218,6 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) {V3D_SHADING_RANDOM_COLOR, "RANDOM", 0, "Random", "Show random object color"}, {0, NULL, 0, NULL, NULL} }; - static const EnumPropertyItem studio_lighting_items[] = { - {0, "01", ICON_STUDIOLIGHT_01, "", ""}, - {1, "02", ICON_STUDIOLIGHT_02, "", ""}, - {2, "03", ICON_STUDIOLIGHT_03, "", ""}, - {3, "04", ICON_STUDIOLIGHT_04, "", ""}, - {4, "05", ICON_STUDIOLIGHT_05, "", ""}, - {0, NULL, 0, NULL, NULL} - }; srna = RNA_def_struct(brna, "View3DShading", NULL); RNA_def_struct_sdna(srna, "View3D"); @@ -2192,8 +2246,9 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "studio_light", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "shading.studio_light"); - RNA_def_property_enum_items(prop, studio_lighting_items); + RNA_def_property_enum_items(prop, rna_enum_studio_light_items); + RNA_def_property_enum_default(prop, 0); + RNA_def_property_enum_funcs(prop, "rna_View3DShading_studio_light_get", "rna_View3DShading_studio_light_set", "rna_View3DShading_studio_light_itemf"); RNA_def_property_ui_text(prop, "Studiolight", "Studio lighting setup"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 5813fc95e13..1dd2185b982 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -75,6 +75,7 @@ #include "BKE_addon.h" #include "BKE_appdir.h" #include "BKE_sequencer.h" /* free seq clipboard */ +#include "BKE_studiolight.h" #include "BKE_material.h" /* clear_matcopybuf */ #include "BKE_tracking.h" /* free tracking clipboard */ #include "BKE_mask.h" /* free mask clipboard */ @@ -250,6 +251,7 @@ void WM_init(bContext *C, int argc, const char **argv) WM_init_opengl(); UI_init(); + BKE_studiolight_init(); } else { /* Note: Currently only inits icons, which we now want in background mode too @@ -259,7 +261,6 @@ void WM_init(bContext *C, int argc, const char **argv) BKE_icons_init(1); } - ED_spacemacros_init(); /* note: there is a bug where python needs initializing before loading the @@ -513,6 +514,7 @@ void WM_exit_ext(bContext *C, const bool do_python) GPU_pass_cache_free(); DRW_opengl_context_destroy(); } + BKE_studiolight_free(); #ifdef WITH_INTERNATIONAL BLF_free_unifont(); diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 585a2f58204..8240b27f2cf 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -413,6 +413,7 @@ install( DESTINATION ${TARGETDIR_VER}/datafiles ) + # helpful tip when using make if("${CMAKE_GENERATOR}" MATCHES ".*Makefiles.*") # message after building. @@ -979,6 +980,13 @@ unset(_icon_names) unset(_icon_files) unset(_f) +# ----------------------------------------------------------------------------- +# Studio Lights +install( + DIRECTORY + ${CMAKE_SOURCE_DIR}/release/datafiles/studiolights + DESTINATION ${TARGETDIR_VER}/datafiles +) # ----------------------------------------------------------------------------- # Setup link libs -- cgit v1.2.3