EEVEE: Lookdev: Add support for partially blurred background

This is using the GGX probe as background. This has the drawback of
having the resolution choosed in the indirect lighting setting.
The blurring is not really high-quality.

The pros is that it has a simple implementation and is fast to evaluate.

This patch also fades the background alpha to make overlay engine draw the
default background color in the correct color space. Removing one colorspace
hack.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D6895
This commit is contained in:
Clément Foucault 2020-02-25 13:25:49 +01:00 committed by Clément Foucault
parent 7e7c927602
commit 6e23433c1a
Notes: blender-bot 2023-02-14 05:51:15 +01:00
Referenced by issue #74206, Crashes when selecting Material Properties tab.
Referenced by issue #74174, Eevee: Crash upon opening material properties
10 changed files with 99 additions and 46 deletions

View File

@ -5415,6 +5415,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.prop(shading, "studiolight_rotate_z", text="Rotation")
col.prop(shading, "studiolight_intensity")
col.prop(shading, "studiolight_background_alpha")
col.prop(shading, "studiolight_background_blur")
col = split.column() # to align properly with above
elif shading.type == 'RENDERED':
@ -5438,6 +5439,7 @@ class VIEW3D_PT_shading_lighting(Panel):
col.prop(shading, "studiolight_rotate_z", text="Rotation")
col.prop(shading, "studiolight_intensity")
col.prop(shading, "studiolight_background_alpha")
col.prop(shading, "studiolight_background_blur")
col = split.column() # to align properly with above

View File

@ -4498,5 +4498,19 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
/* Add Lookdev blur property. */
if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "studiolight_blur")) {
for (bScreen *screen = bmain->screens.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;
v3d->shading.studiolight_blur = 0.5f;
}
}
}
}
}
}
}

View File

@ -343,7 +343,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
const float *col = G_draw.block.colorBackground;
/* LookDev */
EEVEE_lookdev_cache_init(vedata, &grp, psl->probe_background, 1.0f, wo, pinfo);
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo);
/* END */
if (!grp && wo) {
col = &wo->horr;

View File

@ -57,9 +57,9 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata)
}
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
DRWShadingGroup **grp,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **r_grp,
DRWPass *pass,
float background_alpha,
World *UNUSED(world),
EEVEE_LightProbesInfo *pinfo)
{
@ -69,8 +69,11 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_PrivateData *g_data = stl->g_data;
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
View3DShading *shading = &v3d->shading;
Scene *scene = draw_ctx->scene;
const bool probe_render = pinfo != NULL;
effects->lookdev_view = NULL;
if (LOOK_DEV_OVERLAY_ENABLED(v3d)) {
@ -95,12 +98,11 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
}
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
StudioLight *sl = BKE_studiolight_find(v3d->shading.lookdev_light,
StudioLight *sl = BKE_studiolight_find(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();
GPUTexture *tex = NULL;
GPUShader *shader = probe_render ? EEVEE_shaders_default_studiolight_sh_get() :
EEVEE_shaders_background_studiolight_sh_get();
/* If one of the component is missing we start from scratch. */
if ((stl->lookdev_grid_data == NULL) || (stl->lookdev_cube_data == NULL) ||
@ -138,49 +140,45 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
txl->lookdev_cube_tx = stl->lookdev_lightcache->cube_tx.tex;
}
stl->g_data->light_cache = stl->lookdev_lightcache;
g_data->light_cache = stl->lookdev_lightcache;
static float background_color[4];
UI_GetThemeColor4fv(TH_BACK, background_color);
/* XXX: Really quick conversion to avoid washed out background.
* Needs to be addressed properly (color managed using ocio). */
srgb_to_linearrgb_v4(background_color, background_color);
DRWShadingGroup *grp = *r_grp = DRW_shgroup_create(shader, pass);
axis_angle_to_mat3_single(g_data->studiolight_matrix, 'Z', shading->studiolight_rot_z);
DRW_shgroup_uniform_mat3(grp, "StudioLightMatrix", g_data->studiolight_matrix);
*grp = DRW_shgroup_create(shader, pass);
axis_angle_to_mat3_single(
stl->g_data->studiolight_matrix, 'Z', v3d->shading.studiolight_rot_z);
DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix);
DRW_shgroup_uniform_float_copy(*grp, "backgroundAlpha", background_alpha);
DRW_shgroup_uniform_float(
*grp, "studioLightIntensity", &v3d->shading.studiolight_intensity, 1);
DRW_shgroup_uniform_vec3(*grp, "color", background_color, 1);
DRW_shgroup_call(*grp, geom, NULL);
if (!pinfo) {
if (probe_render) {
DRW_shgroup_uniform_float_copy(
grp, "studioLightIntensity", shading->studiolight_intensity);
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
DRW_shgroup_uniform_texture(grp, "image", sl->equirect_radiance_gputexture);
/* Do not fadeout when doing probe rendering, only when drawing the background */
DRW_shgroup_uniform_float(
*grp, "studioLightBackground", &v3d->shading.studiolight_background, 1);
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE);
tex = sl->equirect_irradiance_gputexture;
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
}
else {
DRW_shgroup_uniform_float_copy(*grp, "studioLightBackground", 1.0f);
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
tex = sl->equirect_radiance_gputexture;
float background_alpha = g_data->background_alpha * shading->studiolight_background;
float studiolight_blur = powf(shading->studiolight_blur, 2.5f);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", background_alpha);
DRW_shgroup_uniform_float_copy(grp, "studioLightBlur", studiolight_blur);
DRW_shgroup_uniform_texture(grp, "probeCubes", txl->lookdev_cube_tx);
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
}
DRW_shgroup_uniform_texture(*grp, "image", tex);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
/* Do we need to recalc the lightprobes? */
if (g_data->studiolight_index != sl->index ||
g_data->studiolight_rot_z != v3d->shading.studiolight_rot_z ||
g_data->studiolight_intensity != v3d->shading.studiolight_intensity ||
g_data->studiolight_rot_z != shading->studiolight_rot_z ||
g_data->studiolight_intensity != shading->studiolight_intensity ||
g_data->studiolight_cubemap_res != scene->eevee.gi_cubemap_resolution ||
g_data->studiolight_glossy_clamp != scene->eevee.gi_glossy_clamp ||
g_data->studiolight_filter_quality != scene->eevee.gi_filter_quality) {
stl->lookdev_lightcache->flag |= LIGHTCACHE_UPDATE_WORLD;
g_data->studiolight_index = sl->index;
g_data->studiolight_rot_z = v3d->shading.studiolight_rot_z;
g_data->studiolight_intensity = v3d->shading.studiolight_intensity;
g_data->studiolight_rot_z = shading->studiolight_rot_z;
g_data->studiolight_intensity = shading->studiolight_intensity;
g_data->studiolight_cubemap_res = scene->eevee.gi_cubemap_resolution;
g_data->studiolight_glossy_clamp = scene->eevee.gi_glossy_clamp;
g_data->studiolight_filter_quality = scene->eevee.gi_filter_quality;

View File

@ -1158,8 +1158,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const float *col = G_draw.block.colorBackground;
EEVEE_lookdev_cache_init(
vedata, &grp, psl->background_pass, stl->g_data->background_alpha, wo, NULL);
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL);
if (!grp && wo) {
col = &wo->horr;

View File

@ -987,6 +987,7 @@ struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void);
@ -1196,9 +1197,9 @@ void EEVEE_render_update_passes(struct RenderEngine *engine,
/** eevee_lookdev.c */
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **grp,
DRWPass *pass,
float background_alpha,
struct World *world,
EEVEE_LightProbesInfo *pinfo);
void EEVEE_lookdev_draw(EEVEE_Data *vedata);

View File

@ -44,6 +44,7 @@ static struct {
/* Probes */
struct GPUShader *probe_default_sh;
struct GPUShader *probe_default_studiolight_sh;
struct GPUShader *probe_background_studiolight_sh;
struct GPUShader *probe_grid_display_sh;
struct GPUShader *probe_cube_display_sh;
struct GPUShader *probe_planar_display_sh;
@ -191,6 +192,27 @@ GPUShader *EEVEE_shaders_default_studiolight_sh_get(void)
return e_data.probe_default_studiolight_sh;
}
GPUShader *EEVEE_shaders_background_studiolight_sh_get(void)
{
if (e_data.probe_background_studiolight_sh == NULL) {
char *frag_str = BLI_string_joinN(datatoc_octahedron_lib_glsl,
datatoc_common_uniforms_lib_glsl,
datatoc_bsdf_common_lib_glsl,
datatoc_lightprobe_lib_glsl,
datatoc_default_world_frag_glsl);
e_data.probe_background_studiolight_sh = DRW_shader_create_with_lib(
datatoc_background_vert_glsl,
NULL,
frag_str,
datatoc_common_view_lib_glsl,
"#define LOOKDEV_BG\n" SHADER_DEFINES);
MEM_freeN(frag_str);
}
return e_data.probe_background_studiolight_sh;
}
GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void)
{
if (e_data.probe_cube_display_sh == NULL) {
@ -299,6 +321,7 @@ void EEVEE_shaders_free(void)
DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_planar_downsample_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_studiolight_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_background_studiolight_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_cube_display_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh);

View File

@ -4,11 +4,12 @@ uniform vec3 color;
out vec4 FragColor;
#ifdef LOOKDEV
#if defined(LOOKDEV_BG) || defined(LOOKDEV)
uniform mat3 StudioLightMatrix;
uniform sampler2D image;
uniform float studioLightBackground = 1.0;
uniform float studioLightIntensity = 1.0;
uniform float studioLightBlur = 0.0;
in vec3 viewPosition;
# define M_PI 3.14159265358979323846
@ -49,11 +50,17 @@ vec4 node_tex_environment_equirectangular(vec3 co, sampler2D ima)
void main()
{
vec3 background_color;
#ifdef LOOKDEV
#if defined(LOOKDEV_BG)
vec3 worldvec = background_transform_to_world(viewPosition);
background_color = probe_evaluate_world_spec(worldvec, studioLightBlur).rgb;
background_color *= studioLightIntensity;
#elif defined(LOOKDEV)
vec3 worldvec = background_transform_to_world(viewPosition);
background_color = node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image).rgb;
background_color *= studioLightIntensity;
background_color = mix(color, background_color, studioLightBackground);
#else
background_color = color;
#endif

View File

@ -170,6 +170,7 @@ typedef struct View3DShading {
float studiolight_rot_z;
float studiolight_background;
float studiolight_intensity;
float studiolight_blur;
float object_outline_color[3];
float xray_alpha;
@ -185,7 +186,6 @@ typedef struct View3DShading {
/* Render pass displayed in the viewport. Is an `eScenePassType` where one bit is set */
int render_pass;
char _pad2[4];
struct IDProperty *prop;
} View3DShading;

View File

@ -3239,9 +3239,18 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
prop = RNA_def_property(srna, "studiolight_background_alpha", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "studiolight_background");
RNA_def_property_ui_text(prop, "Background", "Show the studiolight in the background");
RNA_def_property_ui_text(prop, "World Opacity", "Show the studiolight in the background");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.00f, 1.0f, 1, 3);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "studiolight_background_blur", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "studiolight_blur");
RNA_def_property_ui_text(prop, "Blur", "Blur the studiolight in the background");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 2);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);