41#define STUDIOLIGHT_PASSNAME_DIFFUSE "diffuse"
42#define STUDIOLIGHT_PASSNAME_SPECULAR "specular"
66#define ITER_PIXELS(type, src, channels, width, height) \
68 float texel_size[2]; \
69 texel_size[0] = 1.0f / width; \
70 texel_size[1] = 1.0f / height; \
71 type(*pixel_)[channels] = (type(*)[channels])src; \
72 for (float y = 0.5 * texel_size[1]; y < 1.0; y += texel_size[1]) { \
73 for (float x = 0.5 * texel_size[0]; x < 1.0; x += texel_size[0], pixel_++) { \
74 type *pixel = *pixel_;
76#define ITER_PIXELS_END \
83#define IMB_SAFE_FREE(p) \
91#define GPU_TEXTURE_SAFE_FREE(p) \
94 GPU_texture_free(p); \
109#define STUDIOLIGHT_DELETE_ICON(s) \
112 BKE_icon_delete(s); \
124#undef STUDIOLIGHT_DELETE_ICON
144 if (is_used_in_viewport) {
173#define STUDIOLIGHT_FILE_VERSION 1
175#define READ_VAL(type, parser, id, val, lines) \
177 for (LinkNode *line = lines; line; line = line->next) { \
178 char *val_str, *str = static_cast<char *>(line->link); \
179 if ((val_str = strstr(str, id " "))) { \
180 val_str += sizeof(id); \
181 val = parser(val_str); \
186#define READ_FVAL(id, val, lines) READ_VAL(float, atof, id, val, lines)
187#define READ_IVAL(id, val, lines) READ_VAL(int, atoi, id, val, lines)
189#define READ_VEC3(id, val, lines) \
191 READ_FVAL(id ".x", val[0], lines); \
192 READ_FVAL(id ".y", val[1], lines); \
193 READ_FVAL(id ".z", val[2], lines); \
196#define READ_SOLIDLIGHT(sl, i, lines) \
198 READ_IVAL("light[" STRINGIFY(i) "].flag", sl[i].flag, lines); \
199 READ_FVAL("light[" STRINGIFY(i) "].smooth", sl[i].smooth, lines); \
200 READ_VEC3("light[" STRINGIFY(i) "].col", sl[i].col, lines); \
201 READ_VEC3("light[" STRINGIFY(i) "].spec", sl[i].spec, lines); \
202 READ_VEC3("light[" STRINGIFY(i) "].vec", sl[i].vec, lines); \
218#undef READ_SOLIDLIGHT
223#define WRITE_FVAL(str, id, val) BLI_dynstr_appendf(str, id " %f\n", val)
224#define WRITE_IVAL(str, id, val) BLI_dynstr_appendf(str, id " %d\n", val)
226#define WRITE_VEC3(str, id, val) \
228 WRITE_FVAL(str, id ".x", val[0]); \
229 WRITE_FVAL(str, id ".y", val[1]); \
230 WRITE_FVAL(str, id ".z", val[2]); \
233#define WRITE_SOLIDLIGHT(str, sl, i) \
235 WRITE_IVAL(str, "light[" STRINGIFY(i) "].flag", sl[i].flag); \
236 WRITE_FVAL(str, "light[" STRINGIFY(i) "].smooth", sl[i].smooth); \
237 WRITE_VEC3(str, "light[" STRINGIFY(i) "].col", sl[i].col); \
238 WRITE_VEC3(str, "light[" STRINGIFY(i) "].spec", sl[i].spec); \
239 WRITE_VEC3(str, "light[" STRINGIFY(i) "].vec", sl[i].vec); \
266#undef WRITE_SOLIDLIGHT
279struct MultilayerConvertContext {
280 int num_diffuse_channels;
282 int num_specular_channels;
283 float *specular_pass;
327 const char *pass_name,
333 MultilayerConvertContext *ctx =
static_cast<MultilayerConvertContext *
>(base);
338 ctx->diffuse_pass = rect;
339 ctx->num_diffuse_channels = num_channels;
342 ctx->specular_pass = rect;
343 ctx->num_specular_channels = num_channels;
354 ImBuf *specular_ibuf =
nullptr;
355 ImBuf *diffuse_ibuf =
nullptr;
356 const bool failed = (ibuf ==
nullptr);
364 MultilayerConvertContext ctx = {0};
377 if (ctx.diffuse_pass !=
nullptr) {
379 ibuf, ctx.diffuse_pass, ctx.num_diffuse_channels);
381 nullptr, converted_pass, ibuf->
x, ibuf->
y, ctx.num_diffuse_channels);
384 if (ctx.specular_pass !=
nullptr) {
386 ibuf, ctx.specular_pass, ctx.num_specular_channels);
388 nullptr, converted_pass, ibuf->
x, ibuf->
y, ctx.num_specular_channels);
405 if (diffuse_ibuf ==
nullptr) {
408 const float black[4] = {0.0f, 0.0f, 0.0f, 1.0f};
409 const float magenta[4] = {1.0f, 0.0f, 1.0f, 1.0f};
411 nullptr, (failed || (specular_ibuf ==
nullptr)) ? magenta : black, 1, 1, 4);
417 if (specular_ibuf !=
nullptr) {
423 if (specular_ibuf !=
nullptr) {
439 "studiolight_radiance",
443 blender::gpu::TextureFormat::SFLOAT_16_16_16_16,
461 float (*offset3)[3] = (
float (*)[3])gpu_matcap_3components;
462 for (
size_t i = 0;
i < ibuf_pixel_count;
i++, offset4++, offset3++) {
470 blender::gpu::TextureFormat::UFLOAT_11_11_10,
516static float brdf_approx(
float spec_color,
float roughness,
float NV)
520 float fresnel =
exp2(-8.35f * NV) * (1.0f - roughness);
521 return spec_color * (1.0f - fresnel) + fresnel;
527 float w_1 =
w + 1.0f;
528 return max_ff((
NL +
w) / (w_1 * w_1), 0.0f);
545 float gloss = 1.0f - roughness;
547 gloss *= 1.0f -
wrap;
548 float shininess =
exp2(10.0f * gloss + 1.0f);
552 float normalization_factor = shininess * 0.125f + 1.0f;
553 float spec_light =
powf(spec_angle, shininess) *
max_ff(
NL, 0.0f) * normalization_factor;
556 float w =
wrap * (1.0 - roughness) + roughness;
561 return spec_light * (1.0 - w2) + spec_env * w2;
567 float R[3],
I[3] = {0.0f, 0.0f, 1.0f},
N[3] = {normal[0], normal[2], -normal[1]};
568 const float roughness = 0.5f;
569 const float diffuse_color = 0.8f;
570 const float specular_color =
brdf_approx(0.05f, roughness,
N[2]);
571 float diff_light[3], spec_light[3];
592 mul_v3_fl(diff_light, diffuse_color * (1.0 - specular_color));
620 const char *subfolder,
631 for (
i = 0;
i < dirs_num;
i++) {
632 if (dirs[
i].type & S_IFREG) {
657 if (flagorder1 < flagorder2) {
660 if (flagorder1 > flagorder2) {
675 const float co[2] = {u - 0.5f,
v - 0.5f};
677 float alpha = 1.0f + (inner_edge - dist) / (outer_edge - inner_edge);
683#define STUDIOLIGHT_DIAMETER 0.95f
685#define RESCALE_COORD(x) (x / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f)
690 normal[0] = u * 2.0f - 1.0f;
691 normal[1] =
v * 2.0f - 1.0f;
692 float dist =
len_v2(normal);
705 if (alphamask != 0) {
706 float normal[3], direction[3];
707 const float incoming[3] = {0.0f, 0.0f, -1.0f};
711 std::swap(direction[1], direction[2]);
712 direction[1] = -direction[1];
744 float u = dx * diffuse_buffer->
x - 1.0f;
745 float v = dy * diffuse_buffer->
y - 1.0f;
748 if (specular_buffer) {
770 if (alphamask != 0) {
771 float normal[3],
color[3];
774 std::swap(normal[1], normal[2]);
775 normal[1] = -normal[1];
796 lights[0].
smooth = 0.526620f;
797 lights[0].
col[0] = 0.033103f;
798 lights[0].
col[1] = 0.033103f;
799 lights[0].
col[2] = 0.033103f;
800 lights[0].
spec[0] = 0.266761f;
801 lights[0].
spec[1] = 0.266761f;
802 lights[0].
spec[2] = 0.266761f;
803 lights[0].
vec[0] = -0.352546f;
804 lights[0].
vec[1] = 0.170931f;
805 lights[0].
vec[2] = -0.920051f;
808 lights[1].
smooth = 0.000000f;
809 lights[1].
col[0] = 0.521083f;
810 lights[1].
col[1] = 0.538226f;
811 lights[1].
col[2] = 0.538226f;
812 lights[1].
spec[0] = 0.599030f;
813 lights[1].
spec[1] = 0.599030f;
814 lights[1].
spec[2] = 0.599030f;
815 lights[1].
vec[0] = -0.408163f;
816 lights[1].
vec[1] = 0.346939f;
817 lights[1].
vec[2] = 0.844415f;
820 lights[2].
smooth = 0.478261f;
821 lights[2].
col[0] = 0.038403f;
822 lights[2].
col[1] = 0.034357f;
823 lights[2].
col[2] = 0.049530f;
824 lights[2].
spec[0] = 0.106102f;
825 lights[2].
spec[1] = 0.125981f;
826 lights[2].
spec[2] = 0.158523f;
827 lights[2].
vec[0] = 0.521739f;
828 lights[2].
vec[1] = 0.826087f;
829 lights[2].
vec[2] = 0.212999f;
832 lights[3].
smooth = 0.200000f;
833 lights[3].
col[0] = 0.090838f;
834 lights[3].
col[1] = 0.082080f;
835 lights[3].
col[2] = 0.072255f;
836 lights[3].
spec[0] = 0.106535f;
837 lights[3].
spec[1] = 0.084771f;
838 lights[3].
spec[2] = 0.066080f;
839 lights[3].
vec[0] = 0.624519f;
840 lights[3].
vec[1] = -0.562067f;
841 lights[3].
vec[2] = -0.542269f;
889 const char *default_name =
"";
899 if ((sl->flag &
flag) &&
STREQ(sl->name, default_name)) {
905 if (sl->flag &
flag) {
916 if (sl->flag &
flag) {
931 if (sl->index == index) {
946 switch (icon_id_type) {
1008 const float light_ambient[3])
1019 memcpy(sl->
light, light,
sizeof(*light) * 4);
1020 memcpy(sl->
light_ambient, light_ambient,
sizeof(*light_ambient) * 3);
1033 memcpy(sl.
light,
U.light_param,
sizeof(*sl.
light) * 4);
std::optional< std::string > BKE_appdir_folder_id(int folder_id, const char *subfolder) ATTR_WARN_UNUSED_RESULT
@ BLENDER_SYSTEM_DATAFILES
int BKE_icon_ensure_studio_light(struct StudioLight *sl, int id_type)
#define STUDIOLIGHT_ICON_ID_TYPE_MATCAP
#define STUDIOLIGHT_ICON_ID_TYPE_MATCAP_FLIPPED
#define STUDIOLIGHT_ICON_ID_TYPE_RADIANCE
@ STUDIOLIGHT_EXTERNAL_IMAGE_LOADED
@ STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE
@ STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE
@ STUDIOLIGHT_USER_DEFINED
@ STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE
@ STUDIOLIGHT_TYPE_MATCAP
@ STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS
@ STUDIOLIGHT_TYPE_STUDIO
@ STUDIOLIGHT_EXTERNAL_FILE
void StudioLightFreeFunction(struct StudioLight *, void *data)
#define STUDIOLIGHT_ICON_SIZE
#define STUDIOLIGHT_ICON_ID_TYPE_IRRADIANCE
#define STUDIOLIGHT_MAX_LIGHT
A dynamically sized string ADT.
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_dynstr_get_len(const DynStr *ds) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist)
struct LinkNode * BLI_file_read_as_lines(const char *filepath) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_file_free_lines(struct LinkNode *lines)
void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries)
Some types for dealing with directories.
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE float square_f(float a)
unsigned int rgb_to_cpack(float r, float g, float b)
float linearrgb_to_srgb(float c)
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
void reflect_v3_v3v3(float out[3], const float v[3], const float normal[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float normalize_v3(float n[3])
bool BLI_path_extension_check_array(const char *path, const char **ext_array) ATTR_NONNULL(1
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_extension_check(const char *path, const char *ext) ATTR_NONNULL(1
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
char * STRNCPY(char(&dst)[N], const char *src)
#define STREQLEN(a, b, n)
These structs are the foundation for all linked lists in the library system.
void GPU_texture_extend_mode(blender::gpu::Texture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_filter_mode(blender::gpu::Texture *texture, bool use_filter)
void GPU_texture_update(blender::gpu::Texture *texture, eGPUDataFormat data_format, const void *data)
ImBuf * IMB_load_image_from_filepath(const char *filepath, const int flags, char r_colorspace[IM_MAX_SPACE]=nullptr)
ImBuf * IMB_allocFromBuffer(const uint8_t *byte_buffer, const float *float_buffer, unsigned int w, unsigned int h, unsigned int channels)
ImBuf * IMB_allocFromBufferOwn(uint8_t *byte_buffer, float *float_buffer, unsigned int w, unsigned int h, unsigned int channels)
void IMB_buffer_float_from_float(float *rect_to, const float *rect_from, int channels_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
void IMB_freeImBuf(ImBuf *ibuf)
size_t IMB_get_pixel_count(const ImBuf *ibuf)
Get the length of the data of the given image buffer in pixels.
void IMB_float_from_byte(ImBuf *ibuf)
#define IB_PROFILE_LINEAR_RGB
const char * imb_ext_image[]
void IMB_exr_close(ExrHandle *handle)
void IMB_exr_multilayer_convert(ExrHandle *handle, void *base, void *(*addview)(void *base, const char *str), void *(*addlayer)(void *base, const char *str), void(*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view))
Read Guarded memory(de)allocation.
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
ccl_device_inline float3 atan2(const float3 y, const float3 x)
float4 interpolate_nearest_border_fl(const ImBuf *in, float u, float v)
VecBase< float, 4 > float4
float wrap(float value, float max, float min)
ImBufFloatBuffer float_buffer
blender::gpu::Texture * gputexture
StudioLightImage matcap_specular
SolidLight light[STUDIOLIGHT_MAX_LIGHT]
void * free_function_data
blender::gpu::Texture * equirect_radiance_gputexture
StudioLightFreeFunction * free_function
struct ImBuf * equirect_radiance_buffer
int icon_id_matcap_flipped
StudioLightImage matcap_diffuse
static void studiolight_create_matcap_specular_gputexture(StudioLight *sl)
#define STUDIOLIGHT_FILE_VERSION
static const char * STUDIOLIGHT_LIGHTS_FOLDER
static void * studiolight_multilayer_addlayer(void *base, const char *)
static void studiolight_radiance_preview(uint *icon_buffer, StudioLight *sl)
#define WRITE_IVAL(str, id, val)
void BKE_studiolight_remove(StudioLight *sl)
#define STUDIOLIGHT_PASSNAME_DIFFUSE
static StudioLight * studiolight_add_file(const char *filepath, int flag)
static void studiolight_lights_eval(StudioLight *sl, const float normal[3], float r_color[3])
StudioLight * BKE_studiolight_studio_edit_get()
static float * studiolight_multilayer_convert_pass(const ImBuf *ibuf, float *rect, const uint channels)
static void studiolight_free_temp_resources(StudioLight *sl)
static void studiolight_irradiance_preview(uint *icon_buffer, StudioLight *sl)
static const char * STUDIOLIGHT_MATCAP_DEFAULT
static float4 studiolight_calculate_radiance(const ImBuf *ibuf, const float direction[3])
#define WRITE_SOLIDLIGHT(str, sl, i)
static int last_studiolight_id
static int studiolight_cmp(const void *a, const void *b)
#define ITER_PIXELS(type, src, channels, width, height)
static int studiolight_flag_cmp_order(const StudioLight *sl)
StudioLight * BKE_studiolight_load(const char *filepath, int type)
static StudioLight * studiolight_create(int flag)
static ListBase studiolights
static void studiolight_free(StudioLight *sl)
static void studiolight_load_equirect_image(StudioLight *sl)
void BKE_studiolight_unset_icon_id(StudioLight *sl, int icon_id)
static uint alpha_circle_mask(float u, float v, float inner_edge, float outer_edge)
StudioLight * BKE_studiolight_find_default(int flag)
static void studiolight_multilayer_addpass(void *base, void *, const char *pass_name, float *rect, int num_channels, const char *, const char *)
static void studiolight_create_matcap_gputexture(StudioLightImage *sli)
static void sphere_normal_from_uv(float normal[3], float u, float v)
void BKE_studiolight_set_free_function(StudioLight *sl, StudioLightFreeFunction *free_function, void *data)
StudioLight * BKE_studiolight_find(const char *name, int flag)
void BKE_studiolight_free()
static void studiolight_add_files_from_datafolder(const int folder_id, const char *subfolder, int flag)
#define WRITE_VEC3(str, id, val)
void BKE_studiolight_init()
BLI_INLINE float area_element(float x, float y)
void BKE_studiolight_default(SolidLight lights[4], float light_ambient[3])
StudioLight * BKE_studiolight_findindex(int index, int flag)
static void studiolight_load_solid_light(StudioLight *sl)
static float wrapped_lighting(float NL, float w)
#define STUDIOLIGHT_DELETE_ICON(s)
static void studiolight_free_image_buffers(StudioLight *sl)
#define STUDIOLIGHT_PASSNAME_SPECULAR
static const char * STUDIOLIGHT_WORLD_FOLDER
static void studiolight_create_matcap_diffuse_gputexture(StudioLight *sl)
#define READ_VEC3(id, val, lines)
void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
ListBase * BKE_studiolight_listbase()
StudioLight * BKE_studiolight_create(const char *filepath, const SolidLight light[4], const float light_ambient[3])
static const char * STUDIOLIGHT_MATCAP_FOLDER
static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl)
static float brdf_approx(float spec_color, float roughness, float NV)
#define GPU_TEXTURE_SAFE_FREE(p)
static void direction_to_equirect(float r[2], const float dir[3])
static void studiolight_write_solid_light(StudioLight *sl)
static const char * STUDIOLIGHT_WORLD_DEFAULT
static void * studiolight_multilayer_addview(void *, const char *)
#define READ_SOLIDLIGHT(sl, i, lines)
static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool flipped)
void BKE_studiolight_refresh()
static float blinn_specular(const float L[3], const float I[3], const float N[3], const float R[3], float NL, float roughness, float wrap)
void BKE_studiolight_preview(uint *icon_buffer, StudioLight *sl, int icon_id_type)