Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-11-29 21:54:23 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-11-29 23:52:36 +0300
commit844788a36cb0e1efdf3a2010ee67abcb7c46474c (patch)
tree202fbd26d4b397dbcf0eaae063e555591233542d /source/blender
parent8f4ab480bfe81f40b59b20780cb452736fe3af1d (diff)
Workbench: Add back studio lighting presets
This changes a bit how the userprefs solid lights works. They are not visible until enabling the "Edit Solid Light" checkbox. Once enabled the current studiolight used for solid mode will be overwritten. Once the lighting settings are tweaked, the user can click the "Save as Studio light" button to save the current settings. This makes it easy to create new lighting without messing the other presets. The studio lights are stored as ASCII files on the disk using a dead simple custom format. The UI/UX is not perfect and will be improved in other commits. Also includes: * Separate LookDev HDRI selection from Solid Lights * Hide LookDev HDRIs from the Solid Lights selection list
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_studiolight.h11
-rw-r--r--source/blender/blenkernel/intern/studiolight.c274
-rw-r--r--source/blender/blenloader/intern/versioning_280.c13
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c2
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c49
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h2
-rw-r--r--source/blender/draw/engines/workbench/workbench_studiolight.c51
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_space.c18
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c27
11 files changed, 359 insertions, 92 deletions
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index 6616af355ac..25931e2bbf5 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -39,6 +39,7 @@
#include "BLI_sys_types.h"
#include "DNA_space_types.h"
+#include "DNA_userdef_types.h"
#include "IMB_imbuf_types.h"
@@ -59,6 +60,8 @@
#define STUDIOLIGHT_ICON_ID_TYPE_MATCAP (1 << 2)
#define STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED (1 << 3)
+#define STUDIOLIGHT_MAX_LIGHT 4
+
#define STUDIOLIGHT_ICON_SIZE 96
/* Only 1 - 5 is supported */
@@ -97,7 +100,7 @@ enum StudioLightFlag {
#define STUDIOLIGHT_FLAG_ALL (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_EXTERNAL_FILE)
#define STUDIOLIGHT_FLAG_ORIENTATIONS (STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_TYPE_WORLD | STUDIOLIGHT_TYPE_MATCAP)
#define STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE (STUDIOLIGHT_TYPE_WORLD)
-#define STUDIOLIGHT_ORIENTATIONS_SOLID (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_TYPE_WORLD)
+#define STUDIOLIGHT_ORIENTATIONS_SOLID (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_TYPE_STUDIO)
typedef void StudioLightFreeFunction(struct StudioLight *, void *data);
@@ -121,6 +124,8 @@ typedef struct StudioLight {
ImBuf *radiance_cubemap_buffers[6];
struct GPUTexture *equirect_radiance_gputexture;
struct GPUTexture *equirect_irradiance_gputexture;
+ SolidLight light[STUDIOLIGHT_MAX_LIGHT];
+ float light_ambient[3];
/*
* Free function to clean up the running icons previews (wmJob) the usage is in
@@ -140,7 +145,9 @@ void BKE_studiolight_preview(uint *icon_buffer, StudioLight *sl, int icon_id_typ
struct ListBase *BKE_studiolight_listbase(void);
void BKE_studiolight_ensure_flag(StudioLight *sl, int flag);
void BKE_studiolight_refresh(void);
-StudioLight *BKE_studiolight_new(const char *path, int orientation);
+StudioLight *BKE_studiolight_load(const char *path, int orientation);
+StudioLight *BKE_studiolight_create(const char *path, const SolidLight light[4], const float light_ambient[3]);
+StudioLight *BKE_studiolight_studio_edit_get(void);
void BKE_studiolight_remove(StudioLight *sl);
void BKE_studiolight_set_free_function(StudioLight *sl, StudioLightFreeFunction *free_function, void *data);
void BKE_studiolight_unset_icon_id(StudioLight *sl, int icon_id);
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 937c24c47e6..10d9dcfbfec 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -35,9 +35,11 @@
#include "BKE_appdir.h"
#include "BKE_icons.h"
+#include "BLI_dynstr.h"
#include "BLI_fileops.h"
#include "BLI_fileops_types.h"
#include "BLI_listbase.h"
+#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_math_color.h"
#include "BLI_path_util.h"
@@ -82,7 +84,7 @@ static int last_studiolight_id = 0;
*/
#define STUDIOLIGHT_LOAD_CACHED_FILES
-static const char *STUDIOLIGHT_LIGHTS_FOLDER = "studiolights/light/";
+static const char *STUDIOLIGHT_LIGHTS_FOLDER = "studiolights/studio/";
static const char *STUDIOLIGHT_WORLD_FOLDER = "studiolights/world/";
static const char *STUDIOLIGHT_MATCAP_FOLDER = "studiolights/matcap/";
@@ -168,13 +170,15 @@ static struct StudioLight *studiolight_create(int flag)
sl->free_function = NULL;
sl->flag = flag;
sl->index = ++last_studiolight_id;
- if (flag & STUDIOLIGHT_TYPE_MATCAP) {
+ if (flag & STUDIOLIGHT_TYPE_STUDIO) {
+ sl->icon_id_irradiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE);
+ }
+ else if (flag & STUDIOLIGHT_TYPE_MATCAP) {
sl->icon_id_matcap = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_MATCAP);
sl->icon_id_matcap_flipped = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED);
}
else {
sl->icon_id_radiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_RADIANCE);
- sl->icon_id_irradiance = BKE_icon_ensure_studio_light(sl, STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE);
}
for (int index = 0; index < 6; index++) {
@@ -184,6 +188,99 @@ static struct StudioLight *studiolight_create(int flag)
return sl;
}
+#define STUDIOLIGHT_FILE_VERSION 1
+
+#define READ_VAL(type, parser, id, val, lines) do { \
+ for (LinkNode *line = lines; line; line = line->next) { \
+ char *val_str, *str = line->link; \
+ if ((val_str = strstr(str, id " "))) { \
+ val_str += sizeof(id); /* Skip id + spacer. */ \
+ val = parser(val_str); \
+ } \
+ } \
+} while (0)
+
+#define READ_FVAL(id, val, lines) READ_VAL(float, atof, id, val, lines)
+#define READ_IVAL(id, val, lines) READ_VAL(int, atoi, id, val, lines)
+
+#define READ_VEC3(id, val, lines) do { \
+ READ_FVAL(id ".x", val[0], lines); \
+ READ_FVAL(id ".y", val[1], lines); \
+ READ_FVAL(id ".z", val[2], lines); \
+} while (0)
+
+#define READ_SOLIDLIGHT(sl, i, lines) do { \
+ READ_IVAL("light[" STRINGIFY(i) "].flag", sl[i].flag, lines); \
+ READ_FVAL("light[" STRINGIFY(i) "].smooth", sl[i].smooth, lines); \
+ READ_VEC3("light[" STRINGIFY(i) "].col", sl[i].col, lines); \
+ READ_VEC3("light[" STRINGIFY(i) "].spec", sl[i].spec, lines); \
+ READ_VEC3("light[" STRINGIFY(i) "].vec", sl[i].vec, lines); \
+} while (0)
+
+static void studiolight_load_solid_light(StudioLight *sl)
+{
+ LinkNode *lines = BLI_file_read_as_lines(sl->path);
+ if (lines) {
+ READ_VEC3("light_ambient", sl->light_ambient, lines);
+ READ_SOLIDLIGHT(sl->light, 0, lines);
+ READ_SOLIDLIGHT(sl->light, 1, lines);
+ READ_SOLIDLIGHT(sl->light, 2, lines);
+ READ_SOLIDLIGHT(sl->light, 3, lines);
+ }
+ BLI_file_free_lines(lines);
+}
+
+#undef READ_SOLIDLIGHT
+#undef READ_VEC3
+#undef READ_IVAL
+#undef READ_FVAL
+
+#define WRITE_FVAL(str, id, val) (BLI_dynstr_appendf(str, id " %f\n", val))
+#define WRITE_IVAL(str, id, val) (BLI_dynstr_appendf(str, id " %d\n", val))
+
+#define WRITE_VEC3(str, id, val) do { \
+ WRITE_FVAL(str, id ".x", val[0]); \
+ WRITE_FVAL(str, id ".y", val[1]); \
+ WRITE_FVAL(str, id ".z", val[2]); \
+} while (0)
+
+#define WRITE_SOLIDLIGHT(str, sl, i) do { \
+ WRITE_IVAL(str, "light[" STRINGIFY(i) "].flag", sl[i].flag); \
+ WRITE_FVAL(str, "light[" STRINGIFY(i) "].smooth", sl[i].smooth); \
+ WRITE_VEC3(str, "light[" STRINGIFY(i) "].col", sl[i].col); \
+ WRITE_VEC3(str, "light[" STRINGIFY(i) "].spec", sl[i].spec); \
+ WRITE_VEC3(str, "light[" STRINGIFY(i) "].vec", sl[i].vec); \
+} while (0)
+
+static void studiolight_write_solid_light(StudioLight *sl)
+{
+ FILE *fp = BLI_fopen(sl->path, "wb");
+ if (fp) {
+ DynStr *str = BLI_dynstr_new();
+
+ /* Very dumb ascii format. One value per line separated by a space. */
+ WRITE_IVAL(str, "version", STUDIOLIGHT_FILE_VERSION);
+ WRITE_VEC3(str, "light_ambient", sl->light_ambient);
+ WRITE_SOLIDLIGHT(str, sl->light, 0);
+ WRITE_SOLIDLIGHT(str, sl->light, 1);
+ WRITE_SOLIDLIGHT(str, sl->light, 2);
+ WRITE_SOLIDLIGHT(str, sl->light, 3);
+
+ char *cstr = BLI_dynstr_get_cstring(str);
+
+ fwrite(cstr, BLI_dynstr_get_len(str), 1, fp);
+ fclose(fp);
+
+ MEM_freeN(cstr);
+ BLI_dynstr_free(str);
+ }
+}
+
+#undef WRITE_SOLIDLIGHT
+#undef WRITE_VEC3
+#undef WRITE_IVAL
+#undef WRITE_FVAL
+
static void direction_to_equirect(float r[2], const float dir[3])
{
r[0] = (atan2f(dir[1], dir[0]) - M_PI) / -(M_PI * 2);
@@ -732,6 +829,83 @@ static void studiolight_irradiance_eval(StudioLight *sl, float color[3], const f
}
#endif
+static float brdf_approx(float spec_color, float roughness, float NV)
+{
+ /* Very rough own approx. We don't need it to be correct, just fast.
+ * Just simulate fresnel effect with roughness attenuation. */
+ float fresnel = exp2(-8.35f * NV) * (1.0f - roughness);
+ return spec_color * (1.0f - fresnel) + fresnel;
+}
+
+/* NL need to be unclamped. w in [0..1] range. */
+static float wrapped_lighting(float NL, float w)
+{
+ float w_1 = w + 1.0f;
+ return max_ff((NL + w) / (w_1 * w_1), 0.0f);
+}
+
+static float blinn_specular(
+ const float L[3], const float I[3], const float N[3], float R[3], float NL, float roughness, float wrap)
+{
+ float half_dir[3];
+ float wrapped_NL = dot_v3v3(L, R);
+ add_v3_v3v3(half_dir, L, I);
+ normalize_v3(half_dir);
+ float spec_angle = max_ff(dot_v3v3(half_dir, N), 0.0f);
+
+ float gloss = 1.0f - roughness;
+ /* Reduce gloss for smooth light. (simulate bigger light) */
+ gloss *= 1.0f - wrap;
+ float shininess = exp2(10.0f * gloss + 1.0f);
+
+ /* Pi is already divided in the lamp power.
+ * normalization_factor = (shininess + 8.0) / (8.0 * M_PI) */
+ float normalization_factor = shininess * 0.125f + 1.0f;
+ float spec_light = powf(spec_angle, shininess) * max_ff(NL, 0.0f) * normalization_factor;
+
+ /* Simulate Env. light. */
+ float w = wrap * (1.0 - roughness) + roughness;
+ float spec_env = wrapped_lighting(wrapped_NL, w);
+
+ float w2 = wrap * wrap;
+
+ return spec_light * (1.0 - w2) + spec_env * w2;
+}
+
+/* Keep in sync with the glsl shader function get_world_lighting() */
+static void studiolight_lights_eval(StudioLight *sl, float color[3], const float normal[3])
+{
+ float R[3], I[3] = {0.0f, 0.0f, 1.0f}, N[3] = {normal[0], normal[2], -normal[1]};
+ const float roughness = 0.5f;
+ const float diffuse_color = 0.8f;
+ const float specular_color = brdf_approx(0.05f, roughness, N[2]);
+ float diff_light[3], spec_light[3];
+
+ /* Ambient lighting */
+ copy_v3_v3(diff_light, sl->light_ambient);
+ copy_v3_v3(spec_light, sl->light_ambient);
+
+ reflect_v3_v3v3(R, I, N);
+ for (int i = 0; i < 3; ++i) {
+ SolidLight *light = &sl->light[i];
+ if (light->flag) {
+ /* Diffuse lighting */
+ float NL = dot_v3v3(light->vec, N);
+ float diff = wrapped_lighting(NL, light->smooth);
+ madd_v3_v3fl(diff_light, light->col, diff);
+ /* Specular lighting */
+ float spec = blinn_specular(light->vec, I, N, R, NL, roughness, light->smooth);
+ madd_v3_v3fl(spec_light, light->spec, spec);
+ }
+ }
+
+ /* Multiply result by surface colors. */
+ mul_v3_fl(diff_light, diffuse_color * (1.0 - specular_color));
+ mul_v3_fl(spec_light, specular_color);
+
+ add_v3_v3v3(color, diff_light, spec_light);
+}
+
static bool studiolight_load_irradiance_equirect_image(StudioLight *sl)
{
#ifdef STUDIOLIGHT_LOAD_CACHED_FILES
@@ -819,12 +993,21 @@ static StudioLight *studiolight_add_file(const char *path, int flag)
{
char filename[FILE_MAXFILE];
BLI_split_file_part(path, filename, FILE_MAXFILE);
- if (BLI_path_extension_check_array(filename, imb_ext_image)) {
+
+ if ((((flag & STUDIOLIGHT_TYPE_STUDIO) != 0) && BLI_path_extension_check(filename, ".sl")) ||
+ BLI_path_extension_check_array(filename, imb_ext_image))
+ {
StudioLight *sl = studiolight_create(STUDIOLIGHT_EXTERNAL_FILE | flag);
BLI_strncpy(sl->name, filename, FILE_MAXFILE);
BLI_strncpy(sl->path, path, FILE_MAXFILE);
- sl->path_irr_cache = BLI_string_joinN(path, ".irr");
- sl->path_sh_cache = BLI_string_joinN(path, ".sh2");
+
+ if ((flag & STUDIOLIGHT_TYPE_STUDIO) != 0) {
+ studiolight_load_solid_light(sl);
+ }
+ else {
+ sl->path_irr_cache = BLI_string_joinN(path, ".irr");
+ sl->path_sh_cache = BLI_string_joinN(path, ".sh2");
+ }
BLI_addtail(&studiolights, sl);
return sl;
}
@@ -971,8 +1154,6 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool
static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl)
{
- BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED);
-
ITER_PIXELS(uint, icon_buffer, 1,
STUDIOLIGHT_ICON_SIZE,
STUDIOLIGHT_ICON_SIZE)
@@ -988,7 +1169,7 @@ static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl)
SWAP(float, normal[1], normal[2]);
normal[1] = -normal[1];
- studiolight_spherical_harmonics_eval(sl, color, normal);
+ studiolight_lights_eval(sl, color, normal);
*pixel = rgb_to_cpack(
linearrgb_to_srgb(color[0]),
@@ -1005,31 +1186,34 @@ static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl)
/* 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(STUDIOLIGHT_INTERNAL | STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED | STUDIOLIGHT_TYPE_STUDIO);
+ StudioLight * sl = studiolight_create(STUDIOLIGHT_INTERNAL | STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED | STUDIOLIGHT_TYPE_STUDIO);
BLI_strncpy(sl->name, "Default", FILE_MAXFILE);
- int i = 0;
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], 1.03271556f, 1.07163882f, 1.11193657f);
-#if STUDIOLIGHT_SH_BANDS > 1
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], -0.00480952f, 0.05290511f, 0.16394117f);
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], -0.29686999f, -0.27378261f, -0.24797194f);
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], 0.47932500f, 0.48242140f, 0.47190312f);
-#endif
-#if STUDIOLIGHT_SH_BANDS > 2
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], -0.00576984f, 0.00504886f, 0.01640534f);
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], 0.15500379f, 0.15415503f, 0.16244425f);
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], -0.02483751f, -0.02245096f, -0.00536885f);
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], 0.11155496f, 0.11005443f, 0.10839636f);
- copy_v3_fl3(sl->spherical_harmonics_coefs[i++], 0.01363425f, 0.01278363f, -0.00159006f);
-#endif
+ copy_v4_fl4(sl->light_ambient, 0.025000, 0.025000, 0.025000, 1.000000);
+
+ copy_v4_fl4(sl->light[0].vec, -0.580952, 0.228571, 0.781185, 0.0);
+ copy_v4_fl4(sl->light[0].col, 0.900000, 0.900000, 0.900000, 1.000000);
+ copy_v4_fl4(sl->light[0].spec, 0.318547, 0.318547, 0.318547, 1.000000);
+ sl->light[0].flag = 1;
+ sl->light[0].smooth = 0.1;
+
+ copy_v4_fl4(sl->light[1].vec, 0.788218, 0.593482, -0.162765, 0.0);
+ copy_v4_fl4(sl->light[1].col, 0.267115, 0.269928, 0.358840, 1.000000);
+ copy_v4_fl4(sl->light[1].spec, 0.090838, 0.090838, 0.090838, 1.000000);
+ sl->light[1].flag = 1;
+ sl->light[1].smooth = 0.25;
+
+ copy_v4_fl4(sl->light[2].vec, 0.696472, -0.696472, -0.172785, 0.0);
+ copy_v4_fl4(sl->light[2].col, 0.293216, 0.304662, 0.401968, 1.000000);
+ copy_v4_fl4(sl->light[2].spec, 0.069399, 0.020331, 0.020331, 1.000000);
+ sl->light[2].flag = 1;
+ sl->light[2].smooth = 0.5;
BLI_addtail(&studiolights, sl);
+ /* go over the preset folder and add a studiolight for every image with its path */
+ /* Also reserve icon space for it. */
studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_LIGHTS_FOLDER, STUDIOLIGHT_TYPE_STUDIO);
studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES, STUDIOLIGHT_LIGHTS_FOLDER, STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED);
studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_WORLD_FOLDER, STUDIOLIGHT_TYPE_WORLD);
@@ -1161,12 +1345,42 @@ void BKE_studiolight_remove(StudioLight *sl)
}
}
-StudioLight *BKE_studiolight_new(const char *path, int orientation)
+StudioLight *BKE_studiolight_load(const char *path, int type)
{
- StudioLight *sl = studiolight_add_file(path, orientation | STUDIOLIGHT_USER_DEFINED);
+ StudioLight *sl = studiolight_add_file(path, type | STUDIOLIGHT_USER_DEFINED);
return sl;
}
+StudioLight *BKE_studiolight_create(const char *path, const SolidLight light[4], const float light_ambient[3])
+{
+ StudioLight *sl = studiolight_create(STUDIOLIGHT_EXTERNAL_FILE | STUDIOLIGHT_USER_DEFINED | STUDIOLIGHT_TYPE_STUDIO);
+
+ char filename[FILE_MAXFILE];
+ BLI_split_file_part(path, filename, FILE_MAXFILE);
+ BLI_snprintf(sl->path, FILE_MAXFILE, "%s%s", path, ".sl");
+ BLI_snprintf(sl->name, FILE_MAXFILE, "%s%s", filename, ".sl");
+
+ memcpy(sl->light, light, sizeof(*light) * 3);
+ memcpy(sl->light_ambient, light_ambient, sizeof(*light_ambient) * 3);
+
+ studiolight_write_solid_light(sl);
+
+ BLI_addtail(&studiolights, sl);
+ return sl;
+}
+
+/* Only useful for workbench while editing the userprefs. */
+StudioLight *BKE_studiolight_studio_edit_get(void)
+{
+ static StudioLight sl = {0};
+ sl.flag = STUDIOLIGHT_TYPE_STUDIO;
+
+ memcpy(sl.light, U.light, sizeof(*sl.light) * 3);
+ memcpy(sl.light_ambient, U.light_ambient, sizeof(sl.light_ambient) * 3);
+
+ return &sl;
+}
+
void BKE_studiolight_refresh(void)
{
BKE_studiolight_free();
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index b2d9a385c6f..5559982d820 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -2467,5 +2467,18 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ /* Move studio_light selection to lookdev_light. */
+ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "lookdev_light[256]")) {
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ memcpy(v3d->shading.lookdev_light, v3d->shading.studio_light, sizeof(char) * 256);
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index 298a67b811b..aa2f480597b 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -62,7 +62,7 @@ void EEVEE_lookdev_cache_init(
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
- StudioLight *sl = BKE_studiolight_find(v3d->shading.studio_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE);
+ StudioLight *sl = BKE_studiolight_find(v3d->shading.lookdev_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE);
if (sl && (sl->flag & STUDIOLIGHT_TYPE_WORLD)) {
GPUShader *shader = EEVEE_shaders_default_studiolight_sh_get();
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index fd72848da49..1cdf4c2b443 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -40,13 +40,13 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
}
else {
wpd->studio_light = BKE_studiolight_find(
- wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_TYPE_WORLD);
+ wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
}
/* If matcaps are missing, use this as fallback. */
if (UNLIKELY(wpd->studio_light == NULL)) {
wpd->studio_light = BKE_studiolight_find(
- wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_TYPE_WORLD);
+ wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
}
wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity;
@@ -79,7 +79,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
zero_v3(wd->background_color_high);
}
- studiolight_update_world(wpd->studio_light, wd);
+ studiolight_update_world(wpd, wpd->studio_light, wd);
copy_v3_v3(wd->object_outline_color, wpd->shading.object_outline_color);
wd->object_outline_color[3] = 1.0f;
@@ -157,9 +157,8 @@ void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, floa
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
WORKBENCH_UBO_World *wd = &wpd->world_data;
- float view_matrix[4][4], view_inv[4][4], rot_matrix[4][4];
+ float view_matrix[4][4];
DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
- DRW_viewport_matrix_get(view_inv, DRW_MAT_VIEWINV);
copy_v3_v3(r_light_direction, scene->display.light_direction);
negate_v3(r_light_direction);
@@ -167,46 +166,6 @@ void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, floa
/* Shadow direction. */
mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction);
- /* TODO enable when we support studiolight presets. */
- if (STUDIOLIGHT_TYPE_WORLD_ENABLED(wpd) && false) {
- axis_angle_to_mat4_single(rot_matrix, 'Y', -wpd->shading.studiolight_rot_z);
- mul_m4_m4m4(rot_matrix, rot_matrix, view_matrix);
- swap_v3_v3(rot_matrix[2], rot_matrix[1]);
- negate_v3(rot_matrix[2]);
- }
- else {
- unit_m4(rot_matrix);
- }
-
- /* Studio Lights. */
- for (int i = 0; i < 4; i++) {
- WORKBENCH_UBO_Light *light = &wd->lights[i];
- /* TODO use 4 lights in studiolights prefs. */
- if (i > 2) {
- copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f);
- copy_v3_fl(light->specular_color, 0.0f);
- copy_v3_fl(light->diffuse_color, 0.0f);
- continue;
- }
-
- SolidLight *sl = &U.light[i];
- if (sl->flag) {
- copy_v3_v3(light->light_direction, sl->vec);
- mul_mat3_m4_v3(rot_matrix, light->light_direction);
- /* We should predivide the power by PI but that makes the lights really dim. */
- copy_v3_v3(light->specular_color, sl->spec);
- copy_v3_v3(light->diffuse_color, sl->col);
- light->wrapped = sl->smooth;
- }
- else {
- copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f);
- copy_v3_fl(light->specular_color, 0.0f);
- copy_v3_fl(light->diffuse_color, 0.0f);
- }
- }
-
- copy_v4_v4(wd->ambient_color, U.light_ambient);
-
DRW_uniformbuffer_update(wpd->world_ubo, wd);
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 4ab0d39aa55..b1f3a589d05 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -299,7 +299,7 @@ void workbench_material_shgroup_uniform(
void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBENCH_MaterialData *source_material);
/* workbench_studiolight.c */
-void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd);
+void studiolight_update_world(WORKBENCH_PrivateData *wpd, StudioLight *sl, WORKBENCH_UBO_World *wd);
void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]);
bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c
index 901260d0660..183b285c69c 100644
--- a/source/blender/draw/engines/workbench/workbench_studiolight.c
+++ b/source/blender/draw/engines/workbench/workbench_studiolight.c
@@ -32,8 +32,56 @@
#include "BLI_math.h"
#include "BKE_global.h"
-void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd)
+void studiolight_update_world(WORKBENCH_PrivateData *wpd, StudioLight *studiolight, WORKBENCH_UBO_World *wd)
{
+ float view_matrix[4][4], rot_matrix[4][4];
+ DRW_viewport_matrix_get(view_matrix, DRW_MAT_VIEW);
+
+ /* TODO enable when we support studiolight presets. */
+ if (STUDIOLIGHT_TYPE_WORLD_ENABLED(wpd) && false) {
+ axis_angle_to_mat4_single(rot_matrix, 'Y', -wpd->shading.studiolight_rot_z);
+ mul_m4_m4m4(rot_matrix, rot_matrix, view_matrix);
+ swap_v3_v3(rot_matrix[2], rot_matrix[1]);
+ negate_v3(rot_matrix[2]);
+ }
+ else {
+ unit_m4(rot_matrix);
+ }
+
+ if (U.edit_solid_light) {
+ studiolight = BKE_studiolight_studio_edit_get();
+ }
+
+ /* Studio Lights. */
+ for (int i = 0; i < 4; i++) {
+ WORKBENCH_UBO_Light *light = &wd->lights[i];
+ /* TODO use 4 lights in studiolights prefs. */
+ if (i > 2) {
+ copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f);
+ copy_v3_fl(light->specular_color, 0.0f);
+ copy_v3_fl(light->diffuse_color, 0.0f);
+ continue;
+ }
+
+ SolidLight *sl = &studiolight->light[i];
+ if (sl->flag) {
+ copy_v3_v3(light->light_direction, sl->vec);
+ mul_mat3_m4_v3(rot_matrix, light->light_direction);
+ /* We should predivide the power by PI but that makes the lights really dim. */
+ copy_v3_v3(light->specular_color, sl->spec);
+ copy_v3_v3(light->diffuse_color, sl->col);
+ light->wrapped = sl->smooth;
+ }
+ else {
+ copy_v3_fl3(light->light_direction, 1.0f, 0.0f, 0.0f);
+ copy_v3_fl(light->specular_color, 0.0f);
+ copy_v3_fl(light->diffuse_color, 0.0f);
+ }
+ }
+
+ copy_v3_v3(wd->ambient_color, studiolight->light_ambient);
+
+#if 0
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED);
#if STUDIOLIGHT_SH_BANDS == 2
@@ -87,6 +135,7 @@ void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd)
copy_v3_v3(wd->spherical_harmonics_coefs[i], sl->spherical_harmonics_coefs[i]);
}
#endif
+#endif
}
static void compute_parallel_lines_nor_and_dist(const float v1[2], const float v2[2], const float v3[2], float r_line[2])
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 5bb3523a458..e0bed7216e2 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -589,7 +589,8 @@ typedef struct UserDef {
struct SolidLight light[3];
float light_ambient[3], pad7;
short gizmo_flag, gizmo_size;
- short pad6[3];
+ short edit_solid_light;
+ short pad6[2];
short textimeout, texcollectrate;
short dragthreshold;
int memcachelimit;
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index b06f94db064..5c31f377447 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -148,6 +148,7 @@ typedef struct View3DShading {
char pad[7];
char studio_light[256]; /* FILE_MAXFILE */
+ char lookdev_light[256]; /* FILE_MAXFILE */
char matcap[256]; /* FILE_MAXFILE */
float shadow_intensity;
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index fd6e7436351..74fb09f8088 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -754,9 +754,12 @@ static PointerRNA rna_View3DShading_selected_studio_light_get(PointerRNA *ptr)
if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
sl = BKE_studiolight_find(shading->matcap, STUDIOLIGHT_FLAG_ALL);
}
- else {
+ else if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_STUDIO) {
sl = BKE_studiolight_find(shading->studio_light, STUDIOLIGHT_FLAG_ALL);
}
+ else {
+ sl = BKE_studiolight_find(shading->lookdev_light, STUDIOLIGHT_FLAG_ALL);
+ }
return rna_pointer_inherit_refine(ptr, &RNA_StudioLight, sl);
}
@@ -805,13 +808,14 @@ static int rna_View3DShading_studio_light_get(PointerRNA *ptr)
View3DShading *shading = (View3DShading *)ptr->data;
char *dna_storage = shading->studio_light;
- int flag = STUDIOLIGHT_ORIENTATIONS_SOLID;
+ int flag = STUDIOLIGHT_TYPE_STUDIO;
if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
flag = STUDIOLIGHT_TYPE_MATCAP;
dna_storage = shading->matcap;
}
else if (shading->type == OB_MATERIAL) {
- flag = STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE;
+ flag = STUDIOLIGHT_TYPE_WORLD;
+ dna_storage = shading->lookdev_light;
}
StudioLight *sl = BKE_studiolight_find(dna_storage, flag);
if (sl) {
@@ -828,13 +832,14 @@ static void rna_View3DShading_studio_light_set(PointerRNA *ptr, int value)
View3DShading *shading = (View3DShading *)ptr->data;
char *dna_storage = shading->studio_light;
- int flag = STUDIOLIGHT_ORIENTATIONS_SOLID;
+ int flag = STUDIOLIGHT_TYPE_STUDIO;
if (shading->type == OB_SOLID && shading->light == V3D_LIGHTING_MATCAP) {
flag = STUDIOLIGHT_TYPE_MATCAP;
dna_storage = shading->matcap;
}
else if (shading->type == OB_MATERIAL) {
- flag = STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE;
+ flag = STUDIOLIGHT_TYPE_WORLD;
+ dna_storage = shading->lookdev_light;
}
StudioLight *sl = BKE_studiolight_findindex(value, flag);
if (sl) {
@@ -876,8 +881,7 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(
switch (shading->type) {
case OB_SOLID:
case OB_TEXTURE:
- show_studiolight = (
- (sl->flag & (STUDIOLIGHT_TYPE_WORLD | STUDIOLIGHT_TYPE_STUDIO)) != 0);
+ show_studiolight = ((sl->flag & STUDIOLIGHT_TYPE_STUDIO) != 0);
break;
case OB_MATERIAL:
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 89f777625a0..af6150704e0 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -628,9 +628,15 @@ static void rna_StudioLights_remove(UserDef *UNUSED(userdef), StudioLight *studi
BKE_studiolight_remove(studio_light);
}
-static StudioLight *rna_StudioLights_new(UserDef *UNUSED(userdef), const char *path, int type)
+static StudioLight *rna_StudioLights_load(UserDef *UNUSED(userdef), const char *path, int type)
{
- return BKE_studiolight_new(path, type);
+ return BKE_studiolight_load(path, type);
+}
+
+/* TODO: Make it accept arguments. */
+static StudioLight *rna_StudioLights_new(UserDef *userdef, const char *name)
+{
+ return BKE_studiolight_create(name, userdef->light, userdef->light_ambient);
}
/* StudioLight.name */
@@ -3315,8 +3321,8 @@ static void rna_def_userdef_studiolights(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_ui_text(srna, "Studio Lights", "Collection of studio lights");
- func = RNA_def_function(srna, "new", "rna_StudioLights_new");
- RNA_def_function_ui_description(func, "Create a new studiolight");
+ func = RNA_def_function(srna, "load", "rna_StudioLights_load");
+ RNA_def_function_ui_description(func, "Load studiolight from file");
parm = RNA_def_string(func, "path", NULL, 0, "File Path", "File path where the studio light file can be found");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_enum(func, "type", rna_enum_studio_light_type_items, STUDIOLIGHT_TYPE_WORLD, "Type", "The type for the new studio light");
@@ -3324,6 +3330,13 @@ static void rna_def_userdef_studiolights(BlenderRNA *brna)
parm = RNA_def_pointer(func, "studio_light", "StudioLight", "", "Newly created StudioLight");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "new", "rna_StudioLights_new");
+ RNA_def_function_ui_description(func, "Create studiolight from default lighting");
+ parm = RNA_def_string(func, "path", NULL, 0, "Path", "Path to the file that will contain the lighing info (without extension)");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "studio_light", "StudioLight", "", "Newly created StudioLight");
+ RNA_def_function_return(func, parm);
+
func = RNA_def_function(srna, "remove", "rna_StudioLights_remove");
RNA_def_function_ui_description(func, "Remove a studio light");
parm = RNA_def_pointer(func, "studio_light", "StudioLight", "", "The studio light to remove");
@@ -4297,6 +4310,12 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Ambient Color", "Color of the ambient light that uniformly lit the scene");
RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
+ prop = RNA_def_property(srna, "edit_solid_light", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "edit_solid_light", 1);
+ RNA_def_property_ui_text(prop, "Edit Solid Light",
+ "View the result of the solid lights in the viewport");
+ RNA_def_property_update(prop, 0, "rna_UserDef_viewport_lights_update");
+
prop = RNA_def_property(srna, "use_weight_color_range", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_CUSTOM_RANGE);
RNA_def_property_ui_text(prop, "Use Weight Color Range",