Workbench: Specular Highlighting for MatCaps
With Blender 2.80 we introduced a more flexible matcap system. One change we did was to multiply the matcap with the base color that was shaded. As matcaps contains diffuse and specular lighting in a single texture this lead to rendering artifacts. Artists were complaining that everything looked to metalic. We now support a separate `diffuse` and `specular` pass for matcaps. `shaded_color = diffuse_light * base_color + specular_light` For matcaps to support this feature they need to be multilayer openexr files with 2 renderpasses (named `diffuse` and `specular`). In the future we can change this to first pass/second pass in stead of this naming convention. Reviewed By: fclem, brecht Differential Revision: https://developer.blender.org/D5335
This commit is contained in:
parent
bc51250c1f
commit
6670019607
|
@ -5251,8 +5251,10 @@ class VIEW3D_PT_shading_options(Panel):
|
|||
sub.active = shading.show_object_outline
|
||||
sub.prop(shading, "object_outline_color", text="")
|
||||
|
||||
if shading.type == 'SOLID':
|
||||
col = layout.column()
|
||||
if (shading.light == 'STUDIO') and (shading.type != 'WIREFRAME'):
|
||||
if (shading.light in ['STUDIO', 'MATCAP']):
|
||||
col.active = shading.selected_studio_light.has_specular_highlight_pass
|
||||
col.prop(shading, "show_specular_highlight", text="Specular Lighting")
|
||||
|
||||
|
||||
|
|
|
@ -87,6 +87,11 @@ enum StudioLightFlag {
|
|||
STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 11),
|
||||
STUDIOLIGHT_USER_DEFINED = (1 << 12),
|
||||
STUDIOLIGHT_UI_EXPANDED = (1 << 13),
|
||||
|
||||
STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE = (1 << 14),
|
||||
STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE = (1 << 15),
|
||||
/* Is set for studio lights and matcaps with specular highlight pass. */
|
||||
STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS = (1 << 16),
|
||||
};
|
||||
|
||||
#define STUDIOLIGHT_FLAG_ALL (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_EXTERNAL_FILE)
|
||||
|
@ -97,6 +102,11 @@ enum StudioLightFlag {
|
|||
|
||||
typedef void StudioLightFreeFunction(struct StudioLight *, void *data);
|
||||
|
||||
typedef struct StudioLightImage {
|
||||
ImBuf *ibuf;
|
||||
struct GPUTexture *gputexture;
|
||||
} StudioLightImage;
|
||||
|
||||
typedef struct StudioLight {
|
||||
struct StudioLight *next, *prev;
|
||||
|
||||
|
@ -112,6 +122,8 @@ typedef struct StudioLight {
|
|||
int icon_id_matcap_flipped;
|
||||
float spherical_harmonics_coefs[STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN][3];
|
||||
float light_direction[3];
|
||||
StudioLightImage matcap_diffuse;
|
||||
StudioLightImage matcap_specular;
|
||||
ImBuf *equirect_radiance_buffer;
|
||||
ImBuf *equirect_irradiance_buffer;
|
||||
ImBuf *radiance_cubemap_buffers[6];
|
||||
|
|
|
@ -46,13 +46,16 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "intern/openexr/openexr_multi.h"
|
||||
|
||||
/* Statics */
|
||||
static ListBase studiolights;
|
||||
static int last_studiolight_id = 0;
|
||||
#define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 96
|
||||
#define STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT 32
|
||||
#define STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * 2)
|
||||
|
||||
#define STUDIOLIGHT_PASSNAME_DIFFUSE "diffuse"
|
||||
#define STUDIOLIGHT_PASSNAME_SPECULAR "specular"
|
||||
/*
|
||||
* The method to calculate the irradiance buffers
|
||||
* The irradiance buffer is only shown in the background when in LookDev.
|
||||
|
@ -152,6 +155,10 @@ static void studiolight_free(struct StudioLight *sl)
|
|||
GPU_TEXTURE_SAFE_FREE(sl->equirect_irradiance_gputexture);
|
||||
IMB_SAFE_FREE(sl->equirect_radiance_buffer);
|
||||
IMB_SAFE_FREE(sl->equirect_irradiance_buffer);
|
||||
GPU_TEXTURE_SAFE_FREE(sl->matcap_diffuse.gputexture);
|
||||
GPU_TEXTURE_SAFE_FREE(sl->matcap_specular.gputexture);
|
||||
IMB_SAFE_FREE(sl->matcap_diffuse.ibuf);
|
||||
IMB_SAFE_FREE(sl->matcap_specular.ibuf);
|
||||
MEM_SAFE_FREE(sl->path_irr_cache);
|
||||
MEM_SAFE_FREE(sl->path_sh_cache);
|
||||
MEM_SAFE_FREE(sl);
|
||||
|
@ -342,72 +349,232 @@ static void cube_face_uv_to_direction(float r_dir[3], float x, float y, int face
|
|||
normalize_v3(r_dir);
|
||||
}
|
||||
|
||||
typedef struct MultilayerConvertContext {
|
||||
int num_diffuse_channels;
|
||||
float *diffuse_pass;
|
||||
int num_specular_channels;
|
||||
float *specular_pass;
|
||||
} MultilayerConvertContext;
|
||||
|
||||
static void *studiolight_multilayer_addview(void *UNUSED(base), const char *UNUSED(view_name))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static void *studiolight_multilayer_addlayer(void *base, const char *UNUSED(layer_name))
|
||||
{
|
||||
return base;
|
||||
}
|
||||
|
||||
/* Convert a multilayer pass to ImBuf channel 4 float buffer.
|
||||
* NOTE: Parameter rect will become invalid. Do not use rect after calling this
|
||||
* function */
|
||||
static float *studiolight_multilayer_convert_pass(ImBuf *ibuf,
|
||||
float *rect,
|
||||
const unsigned int channels)
|
||||
{
|
||||
if (channels == 4) {
|
||||
return rect;
|
||||
}
|
||||
else {
|
||||
float *new_rect = MEM_callocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__);
|
||||
|
||||
IMB_buffer_float_from_float(new_rect,
|
||||
rect,
|
||||
channels,
|
||||
IB_PROFILE_LINEAR_RGB,
|
||||
IB_PROFILE_LINEAR_RGB,
|
||||
false,
|
||||
ibuf->x,
|
||||
ibuf->y,
|
||||
ibuf->x,
|
||||
ibuf->x);
|
||||
|
||||
MEM_freeN(rect);
|
||||
return new_rect;
|
||||
}
|
||||
}
|
||||
|
||||
static void studiolight_multilayer_addpass(void *base,
|
||||
void *UNUSED(lay),
|
||||
const char *pass_name,
|
||||
float *rect,
|
||||
int num_channels,
|
||||
const char *UNUSED(chan_id),
|
||||
const char *UNUSED(view_name))
|
||||
{
|
||||
MultilayerConvertContext *ctx = base;
|
||||
/* NOTE: This function must free pass pixels data if it is not used, this
|
||||
* is how IMB_exr_multilayer_convert() is working. */
|
||||
/* If we've found a first combined pass, skip all the rest ones. */
|
||||
if (STREQ(pass_name, STUDIOLIGHT_PASSNAME_DIFFUSE)) {
|
||||
ctx->diffuse_pass = rect;
|
||||
ctx->num_diffuse_channels = num_channels;
|
||||
}
|
||||
else if (STREQ(pass_name, STUDIOLIGHT_PASSNAME_SPECULAR)) {
|
||||
ctx->specular_pass = rect;
|
||||
ctx->num_specular_channels = num_channels;
|
||||
}
|
||||
else {
|
||||
MEM_freeN(rect);
|
||||
}
|
||||
}
|
||||
|
||||
static void studiolight_load_equirect_image(StudioLight *sl)
|
||||
{
|
||||
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
|
||||
ImBuf *ibuf = NULL;
|
||||
ibuf = IMB_loadiffname(sl->path, 0, NULL);
|
||||
if (ibuf == NULL) {
|
||||
float *colbuf = MEM_mallocN(sizeof(float[4]), __func__);
|
||||
copy_v4_fl4(colbuf, 1.0f, 0.0f, 1.0f, 1.0f);
|
||||
ibuf = IMB_allocFromBuffer(NULL, colbuf, 1, 1);
|
||||
ImBuf *ibuf = IMB_loadiffname(sl->path, IB_multilayer, NULL);
|
||||
ImBuf *specular_ibuf = NULL;
|
||||
ImBuf *diffuse_ibuf = NULL;
|
||||
const bool failed = (ibuf == NULL);
|
||||
|
||||
if (ibuf) {
|
||||
if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
|
||||
/* the read file is a multilayered openexr file (userdata != NULL)
|
||||
* This file is currently only supported for MATCAPS where
|
||||
* the first found 'diffuse' pass will be used for diffuse lighting
|
||||
* and the first found 'specular' pass will be used for specular lighting */
|
||||
MultilayerConvertContext ctx = {};
|
||||
IMB_exr_multilayer_convert(ibuf->userdata,
|
||||
&ctx,
|
||||
&studiolight_multilayer_addview,
|
||||
&studiolight_multilayer_addlayer,
|
||||
&studiolight_multilayer_addpass);
|
||||
|
||||
/* `ctx.diffuse_pass` and `ctx.specular_pass` can be freed inside
|
||||
* `studiolight_multilayer_convert_pass` when conversion happens.
|
||||
* When not converted we move the ownership of the buffer to the
|
||||
* `converted_pass`. We only need to free `converted_pass` as it holds
|
||||
* the unmodified allocation from the `ctx.*_pass` or the converted data.
|
||||
*/
|
||||
if (ctx.diffuse_pass != NULL) {
|
||||
float *converted_pass = studiolight_multilayer_convert_pass(
|
||||
ibuf, ctx.diffuse_pass, ctx.num_diffuse_channels);
|
||||
diffuse_ibuf = IMB_allocFromBuffer(
|
||||
NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_diffuse_channels);
|
||||
MEM_freeN(converted_pass);
|
||||
}
|
||||
|
||||
if (ctx.specular_pass != NULL) {
|
||||
float *converted_pass = studiolight_multilayer_convert_pass(
|
||||
ibuf, ctx.specular_pass, ctx.num_specular_channels);
|
||||
specular_ibuf = IMB_allocFromBuffer(
|
||||
NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_specular_channels);
|
||||
MEM_freeN(converted_pass);
|
||||
}
|
||||
|
||||
IMB_exr_close(ibuf->userdata);
|
||||
ibuf->userdata = NULL;
|
||||
IMB_freeImBuf(ibuf);
|
||||
ibuf = NULL;
|
||||
}
|
||||
else {
|
||||
/* read file is an single layer openexr file or the read file isn't
|
||||
* an openexr file */
|
||||
IMB_float_from_rect(ibuf);
|
||||
diffuse_ibuf = ibuf;
|
||||
ibuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (diffuse_ibuf == NULL) {
|
||||
/* Create 1x1 diffuse buffer, in case image failed to load or if there was
|
||||
* only a specular pass in the multilayer file or no passes were found. */
|
||||
const float black[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
const float magenta[4] = {1.0f, 0.0f, 1.0f, 1.0f};
|
||||
diffuse_ibuf = IMB_allocFromBuffer(
|
||||
NULL, (failed || (specular_ibuf == NULL)) ? magenta : black, 1, 1, 4);
|
||||
}
|
||||
|
||||
if ((sl->flag & STUDIOLIGHT_TYPE_MATCAP)) {
|
||||
sl->matcap_diffuse.ibuf = diffuse_ibuf;
|
||||
sl->matcap_specular.ibuf = specular_ibuf;
|
||||
if (specular_ibuf != NULL) {
|
||||
sl->flag |= STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sl->equirect_radiance_buffer = diffuse_ibuf;
|
||||
if (specular_ibuf != NULL) {
|
||||
IMB_freeImBuf(specular_ibuf);
|
||||
}
|
||||
}
|
||||
IMB_float_from_rect(ibuf);
|
||||
sl->equirect_radiance_buffer = ibuf;
|
||||
}
|
||||
|
||||
sl->flag |= STUDIOLIGHT_EXTERNAL_IMAGE_LOADED;
|
||||
}
|
||||
|
||||
static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl)
|
||||
{
|
||||
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
|
||||
char error[256];
|
||||
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
|
||||
ImBuf *ibuf = sl->equirect_radiance_buffer;
|
||||
|
||||
if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
|
||||
float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__);
|
||||
|
||||
float(*offset4)[4] = (float(*)[4])ibuf->rect_float;
|
||||
float(*offset3)[3] = (float(*)[3])gpu_matcap_3components;
|
||||
for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) {
|
||||
copy_v3_v3(*offset3, *offset4);
|
||||
}
|
||||
|
||||
sl->equirect_radiance_gputexture = GPU_texture_create_nD(ibuf->x,
|
||||
ibuf->y,
|
||||
0,
|
||||
2,
|
||||
gpu_matcap_3components,
|
||||
GPU_R11F_G11F_B10F,
|
||||
GPU_DATA_FLOAT,
|
||||
0,
|
||||
false,
|
||||
error);
|
||||
|
||||
MEM_SAFE_FREE(gpu_matcap_3components);
|
||||
}
|
||||
else {
|
||||
sl->equirect_radiance_gputexture = GPU_texture_create_2d(
|
||||
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
|
||||
GPUTexture *tex = sl->equirect_radiance_gputexture;
|
||||
GPU_texture_bind(tex, 0);
|
||||
GPU_texture_filter_mode(tex, true);
|
||||
GPU_texture_wrap_mode(tex, true);
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
sl->equirect_radiance_gputexture = GPU_texture_create_2d(
|
||||
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
|
||||
GPUTexture *tex = sl->equirect_radiance_gputexture;
|
||||
GPU_texture_bind(tex, 0);
|
||||
GPU_texture_filter_mode(tex, true);
|
||||
GPU_texture_wrap_mode(tex, true);
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE;
|
||||
}
|
||||
|
||||
static void studiolight_create_matcap_gputexture(StudioLightImage *sli)
|
||||
{
|
||||
BLI_assert(sli->ibuf);
|
||||
ImBuf *ibuf = sli->ibuf;
|
||||
float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__);
|
||||
|
||||
float(*offset4)[4] = (float(*)[4])ibuf->rect_float;
|
||||
float(*offset3)[3] = (float(*)[3])gpu_matcap_3components;
|
||||
for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) {
|
||||
copy_v3_v3(*offset3, *offset4);
|
||||
}
|
||||
|
||||
sli->gputexture = GPU_texture_create_nD(ibuf->x,
|
||||
ibuf->y,
|
||||
0,
|
||||
2,
|
||||
gpu_matcap_3components,
|
||||
GPU_R11F_G11F_B10F,
|
||||
GPU_DATA_FLOAT,
|
||||
0,
|
||||
false,
|
||||
NULL);
|
||||
MEM_SAFE_FREE(gpu_matcap_3components);
|
||||
}
|
||||
|
||||
static void studiolight_create_matcap_diffuse_gputexture(StudioLight *sl)
|
||||
{
|
||||
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
|
||||
if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
|
||||
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
|
||||
studiolight_create_matcap_gputexture(&sl->matcap_diffuse);
|
||||
}
|
||||
}
|
||||
sl->flag |= STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE;
|
||||
}
|
||||
static void studiolight_create_matcap_specular_gputexture(StudioLight *sl)
|
||||
{
|
||||
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
|
||||
if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
|
||||
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
|
||||
if (sl->matcap_specular.ibuf) {
|
||||
studiolight_create_matcap_gputexture(&sl->matcap_specular);
|
||||
}
|
||||
}
|
||||
}
|
||||
sl->flag |= STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE;
|
||||
}
|
||||
|
||||
static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl)
|
||||
{
|
||||
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
|
||||
char error[256];
|
||||
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED);
|
||||
ImBuf *ibuf = sl->equirect_irradiance_buffer;
|
||||
sl->equirect_irradiance_gputexture = GPU_texture_create_2d(
|
||||
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
|
||||
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
|
||||
GPUTexture *tex = sl->equirect_irradiance_gputexture;
|
||||
GPU_texture_bind(tex, 0);
|
||||
GPU_texture_filter_mode(tex, true);
|
||||
|
@ -457,32 +624,32 @@ static void studiolight_calculate_radiance_cubemap_buffers(StudioLight *sl)
|
|||
/* front */
|
||||
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 2, 1, 1, -1, 1);
|
||||
sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer(
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
|
||||
|
||||
/* back */
|
||||
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 2, 1, 1, 1, -1);
|
||||
sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer(
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
|
||||
|
||||
/* left */
|
||||
studiolight_calculate_radiance_buffer(ibuf, colbuf, 2, 1, 0, 1, -1, 1);
|
||||
sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer(
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
|
||||
|
||||
/* right */
|
||||
studiolight_calculate_radiance_buffer(ibuf, colbuf, 2, 1, 0, -1, -1, -1);
|
||||
sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer(
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
|
||||
|
||||
/* top */
|
||||
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 1, 2, -1, -1, 1);
|
||||
sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer(
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
|
||||
|
||||
/* bottom */
|
||||
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 1, 2, 1, -1, -1);
|
||||
sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer(
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
|
||||
NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
|
||||
|
||||
#if 0
|
||||
IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS],
|
||||
|
@ -603,7 +770,8 @@ static void studiolight_spherical_harmonics_calculate_coefficients(StudioLight *
|
|||
/* Take monochrome SH as input */
|
||||
static float studiolight_spherical_harmonics_lambda_get(float *sh, float max_laplacian)
|
||||
{
|
||||
/* From Peter-Pike Sloan's Stupid SH Tricks http://www.ppsloan.org/publications/StupidSH36.pdf */
|
||||
/* From Peter-Pike Sloan's Stupid SH Tricks http://www.ppsloan.org/publications/StupidSH36.pdf
|
||||
*/
|
||||
float table_l[STUDIOLIGHT_SH_BANDS];
|
||||
float table_b[STUDIOLIGHT_SH_BANDS];
|
||||
|
||||
|
@ -720,7 +888,6 @@ BLI_INLINE void studiolight_spherical_harmonics_eval(StudioLight *sl,
|
|||
}
|
||||
return;
|
||||
#else
|
||||
|
||||
/* L0 */
|
||||
mul_v3_v3fl(color, sl->spherical_harmonics_coefs[0], 0.282095f);
|
||||
# if STUDIOLIGHT_SH_BANDS > 1 /* L1 */
|
||||
|
@ -1045,7 +1212,8 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl)
|
|||
sl->equirect_irradiance_buffer = IMB_allocFromBuffer(NULL,
|
||||
colbuf,
|
||||
STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH,
|
||||
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT);
|
||||
STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT,
|
||||
4);
|
||||
MEM_freeN(colbuf);
|
||||
|
||||
#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
|
||||
|
@ -1196,7 +1364,8 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool
|
|||
{
|
||||
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
|
||||
|
||||
ImBuf *ibuf = sl->equirect_radiance_buffer;
|
||||
ImBuf *diffuse_buffer = sl->matcap_diffuse.ibuf;
|
||||
ImBuf *specular_buffer = sl->matcap_specular.ibuf;
|
||||
|
||||
ITER_PIXELS (uint, icon_buffer, 1, STUDIOLIGHT_ICON_SIZE, STUDIOLIGHT_ICON_SIZE) {
|
||||
float dy = RESCALE_COORD(y);
|
||||
|
@ -1206,7 +1375,15 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool
|
|||
}
|
||||
|
||||
float color[4];
|
||||
nearest_interpolation_color(ibuf, NULL, color, dx * ibuf->x - 1.0f, dy * ibuf->y - 1.0f);
|
||||
float u = dx * diffuse_buffer->x - 1.0f;
|
||||
float v = dy * diffuse_buffer->y - 1.0f;
|
||||
nearest_interpolation_color(diffuse_buffer, NULL, color, u, v);
|
||||
|
||||
if (specular_buffer) {
|
||||
float specular[4];
|
||||
nearest_interpolation_color(specular_buffer, NULL, specular, u, v);
|
||||
add_v3_v3(color, specular);
|
||||
}
|
||||
|
||||
uint alphamask = alpha_circle_mask(dx, dy, 0.5f - texel_size[0], 0.5f);
|
||||
|
||||
|
@ -1303,9 +1480,9 @@ void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4])
|
|||
void BKE_studiolight_init(void)
|
||||
{
|
||||
/* Add default studio light */
|
||||
StudioLight *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 | STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
|
||||
BLI_strncpy(sl->name, "Default", FILE_MAXFILE);
|
||||
|
||||
BLI_addtail(&studiolights, sl);
|
||||
|
@ -1317,7 +1494,8 @@ void BKE_studiolight_init(void)
|
|||
if (!BKE_appdir_app_is_portable_install()) {
|
||||
studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,
|
||||
STUDIOLIGHT_LIGHTS_FOLDER,
|
||||
STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED);
|
||||
STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED |
|
||||
STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
|
||||
studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,
|
||||
STUDIOLIGHT_WORLD_FOLDER,
|
||||
STUDIOLIGHT_TYPE_WORLD | STUDIOLIGHT_USER_DEFINED);
|
||||
|
@ -1325,8 +1503,10 @@ void BKE_studiolight_init(void)
|
|||
STUDIOLIGHT_MATCAP_FOLDER,
|
||||
STUDIOLIGHT_TYPE_MATCAP | STUDIOLIGHT_USER_DEFINED);
|
||||
}
|
||||
studiolight_add_files_from_datafolder(
|
||||
BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_LIGHTS_FOLDER, STUDIOLIGHT_TYPE_STUDIO);
|
||||
studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES,
|
||||
STUDIOLIGHT_LIGHTS_FOLDER,
|
||||
STUDIOLIGHT_TYPE_STUDIO |
|
||||
STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
|
||||
studiolight_add_files_from_datafolder(
|
||||
BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_WORLD_FOLDER, STUDIOLIGHT_TYPE_WORLD);
|
||||
studiolight_add_files_from_datafolder(
|
||||
|
@ -1456,6 +1636,12 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
|
|||
studiolight_calculate_irradiance_equirect_image(sl);
|
||||
}
|
||||
}
|
||||
if ((flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE)) {
|
||||
studiolight_create_matcap_diffuse_gputexture(sl);
|
||||
}
|
||||
if ((flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE)) {
|
||||
studiolight_create_matcap_specular_gputexture(sl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -5,7 +5,8 @@ uniform sampler2D materialBuffer;
|
|||
uniform sampler2D normalBuffer;
|
||||
/* normalBuffer contains viewport normals */
|
||||
uniform sampler2D cavityBuffer;
|
||||
uniform sampler2D matcapImage;
|
||||
uniform sampler2D matcapDiffuseImage;
|
||||
uniform sampler2D matcapSpecularImage;
|
||||
|
||||
uniform vec2 invertedViewportSize;
|
||||
uniform vec4 viewvecs[3];
|
||||
|
@ -55,8 +56,15 @@ void main()
|
|||
normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport;
|
||||
bool flipped = world_data.matcap_orientation != 0;
|
||||
vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
|
||||
vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
|
||||
vec3 shaded_color = matcap * base_color;
|
||||
vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb;
|
||||
|
||||
# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
|
||||
vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb;
|
||||
# else
|
||||
vec3 matcap_specular = vec3(0.0);
|
||||
# endif
|
||||
|
||||
vec3 shaded_color = matcap_diffuse * base_color + matcap_specular;
|
||||
|
||||
#elif defined(V3D_LIGHTING_STUDIO)
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@ in vec2 uv_interp;
|
|||
in vec3 vertexColor;
|
||||
#endif
|
||||
#ifdef V3D_LIGHTING_MATCAP
|
||||
uniform sampler2D matcapImage;
|
||||
uniform sampler2D matcapDiffuseImage;
|
||||
uniform sampler2D matcapSpecularImage;
|
||||
#endif
|
||||
|
||||
layout(std140) uniform world_block
|
||||
|
@ -68,8 +69,13 @@ void main()
|
|||
#elif defined(V3D_LIGHTING_MATCAP)
|
||||
bool flipped = world_data.matcap_orientation != 0;
|
||||
vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped);
|
||||
vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
|
||||
vec3 shaded_color = matcap * diffuse_color.rgb;
|
||||
vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb;
|
||||
# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
|
||||
vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb;
|
||||
# else
|
||||
vec3 matcap_specular = vec3(0.0);
|
||||
# endif
|
||||
vec3 shaded_color = matcap_diffuse * diffuse_color.rgb + matcap_specular;
|
||||
|
||||
#elif defined(V3D_LIGHTING_STUDIO)
|
||||
vec3 shaded_color = get_world_lighting(
|
||||
|
|
|
@ -694,16 +694,22 @@ static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingG
|
|||
if (CAVITY_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx);
|
||||
}
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
|
||||
}
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
|
||||
}
|
||||
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
|
||||
BKE_studiolight_ensure_flag(wpd->studio_light,
|
||||
STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
|
||||
STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
|
||||
grp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture);
|
||||
if (workbench_is_specular_highlight_enabled(wpd)) {
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,11 +186,17 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
|
|||
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
|
||||
workbench_material_copy(material, &material_template);
|
||||
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
|
||||
BKE_studiolight_ensure_flag(wpd->studio_light,
|
||||
STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
|
||||
STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
|
||||
grp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture);
|
||||
if (workbench_is_specular_highlight_enabled(wpd)) {
|
||||
DRW_shgroup_uniform_texture(
|
||||
grp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture);
|
||||
}
|
||||
}
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd) || MATCAP_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
|
||||
}
|
||||
if (SHADOW_ENABLED(wpd)) {
|
||||
|
@ -528,11 +534,17 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
|
|||
float hair_alpha = XRAY_ALPHA(wpd) * 0.33f;
|
||||
DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha);
|
||||
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
|
||||
BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
|
||||
BKE_studiolight_ensure_flag(wpd->studio_light,
|
||||
STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
|
||||
STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
|
||||
DRW_shgroup_uniform_texture(
|
||||
shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
|
||||
shgrp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture);
|
||||
if (workbench_is_specular_highlight_enabled(wpd)) {
|
||||
DRW_shgroup_uniform_texture(
|
||||
shgrp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture);
|
||||
}
|
||||
}
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd) || MATCAP_ENABLED(wpd)) {
|
||||
DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
|
|||
/* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */
|
||||
if (mat) {
|
||||
data->alpha *= mat->a;
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd)) {
|
||||
copy_v3_v3(data->base_color, &mat->r);
|
||||
mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic);
|
||||
mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic);
|
||||
|
@ -121,7 +121,7 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
|
|||
if (SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) {
|
||||
BLI_dynstr_append(ds, "#define WB_CAVITY\n");
|
||||
}
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd)) {
|
||||
BLI_dynstr_append(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
|
||||
}
|
||||
if (STUDIOLIGHT_ENABLED(wpd)) {
|
||||
|
@ -195,11 +195,12 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
|
|||
/* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */
|
||||
int index = 0;
|
||||
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
|
||||
index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
|
||||
index = wpd->shading.light;
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2);
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3);
|
||||
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4);
|
||||
SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 5);
|
||||
SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6);
|
||||
BLI_assert(index < MAX_COMPOSITE_SHADERS);
|
||||
return index;
|
||||
}
|
||||
|
@ -246,12 +247,13 @@ int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
|
|||
/* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
|
||||
int index = 0;
|
||||
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
|
||||
index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
|
||||
index = wpd->shading.light;
|
||||
SET_FLAG_FROM_TEST(index, use_textures, 1 << 2);
|
||||
SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 3);
|
||||
SET_FLAG_FROM_TEST(index, is_hair, 1 << 4);
|
||||
/* 1 bits SHADOWS (only facing factor) */
|
||||
SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 5);
|
||||
SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6);
|
||||
BLI_assert(index < MAX_ACCUM_SHADERS);
|
||||
return index;
|
||||
}
|
||||
|
@ -333,7 +335,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
|
|||
1);
|
||||
}
|
||||
|
||||
if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
|
||||
if (workbench_is_specular_highlight_enabled(wpd)) {
|
||||
if (use_metallic) {
|
||||
DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
|
||||
}
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
|
||||
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
|
||||
#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
|
||||
#define MAX_COMPOSITE_SHADERS (1 << 6)
|
||||
#define MAX_COMPOSITE_SHADERS (1 << 7)
|
||||
#define MAX_PREPASS_SHADERS (1 << 7)
|
||||
#define MAX_ACCUM_SHADERS (1 << 6)
|
||||
#define MAX_ACCUM_SHADERS (1 << 7)
|
||||
#define MAX_CAVITY_SHADERS (1 << 3)
|
||||
|
||||
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR)
|
||||
|
@ -77,9 +77,6 @@
|
|||
#define IS_NAVIGATING(wpd) \
|
||||
((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING))
|
||||
|
||||
#define SPECULAR_HIGHLIGHT_ENABLED(wpd) \
|
||||
(STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && \
|
||||
(!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
|
||||
#define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
|
||||
#define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
|
||||
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) \
|
||||
|
@ -316,6 +313,16 @@ typedef struct WORKBENCH_ObjectData {
|
|||
} WORKBENCH_ObjectData;
|
||||
|
||||
/* inline helper functions */
|
||||
BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
if ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) {
|
||||
if (STUDIOLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
|
||||
return (wpd->studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS) != 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd)
|
||||
{
|
||||
if (DRW_state_is_image_render()) {
|
||||
|
|
|
@ -348,7 +348,7 @@ static void gpu_texture_update_scaled(
|
|||
}
|
||||
|
||||
/* Scale pixels. */
|
||||
ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h);
|
||||
ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h, 4);
|
||||
IMB_scaleImBuf(ibuf, sub_w, sub_h);
|
||||
|
||||
if (ibuf->rect_float) {
|
||||
|
@ -648,13 +648,13 @@ void GPU_create_gl_tex(uint *bind,
|
|||
recth = smaller_power_of_2_limit(recth);
|
||||
|
||||
if (frect) {
|
||||
ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
|
||||
ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy, 4);
|
||||
IMB_scaleImBuf(ibuf, rectw, recth);
|
||||
|
||||
frect = ibuf->rect_float;
|
||||
}
|
||||
else {
|
||||
ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
|
||||
ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy, 4);
|
||||
IMB_scaleImBuf(ibuf, rectw, recth);
|
||||
|
||||
rect = ibuf->rect;
|
||||
|
|
|
@ -145,7 +145,8 @@ bool IMB_initImBuf(
|
|||
struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
|
||||
const float *rectf,
|
||||
unsigned int w,
|
||||
unsigned int h);
|
||||
unsigned int h,
|
||||
unsigned int channels);
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -428,7 +428,8 @@ bool imb_addrectImBuf(ImBuf *ibuf)
|
|||
struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
|
||||
const float *rectf,
|
||||
unsigned int w,
|
||||
unsigned int h)
|
||||
unsigned int h,
|
||||
unsigned int channels)
|
||||
{
|
||||
ImBuf *ibuf = NULL;
|
||||
|
||||
|
@ -438,6 +439,7 @@ struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
|
|||
|
||||
ibuf = IMB_allocImBuf(w, h, 32, 0);
|
||||
|
||||
ibuf->channels = channels;
|
||||
if (rectf) {
|
||||
ibuf->rect_float = MEM_dupallocN(rectf);
|
||||
ibuf->flags |= IB_rectfloat;
|
||||
|
|
|
@ -912,6 +912,13 @@ static bool rna_UserDef_studiolight_is_user_defined_get(PointerRNA *ptr)
|
|||
return (sl->flag & STUDIOLIGHT_USER_DEFINED) != 0;
|
||||
}
|
||||
|
||||
/* StudioLight.is_user_defined */
|
||||
static bool rna_UserDef_studiolight_has_specular_highlight_pass_get(PointerRNA *ptr)
|
||||
{
|
||||
StudioLight *sl = (StudioLight *)ptr->data;
|
||||
return sl->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS;
|
||||
}
|
||||
|
||||
/* StudioLight.type */
|
||||
|
||||
static int rna_UserDef_studiolight_type_get(PointerRNA *ptr)
|
||||
|
@ -3700,6 +3707,15 @@ static void rna_def_userdef_studiolight(BlenderRNA *brna)
|
|||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "User Defined", "");
|
||||
|
||||
prop = RNA_def_property(srna, "has_specular_highlight_pass", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, "rna_UserDef_studiolight_has_specular_highlight_pass_get", NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Has Specular Highlight",
|
||||
"Studio light image file has separate \"diffuse\" and \"specular\" passes");
|
||||
|
||||
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, rna_enum_studio_light_type_items);
|
||||
RNA_def_property_enum_funcs(prop, "rna_UserDef_studiolight_type_get", NULL, NULL);
|
||||
|
|
Loading…
Reference in New Issue