EEVEE-Next: Lookdev Background Blur
This PR implements the background blurring for studiolight/lookdev HDRIs. The visual appearance matches EEVEE-Classic closely. **Technical details** - LOD0 is skipped as the regular background color can be used. The regular background color is blended towards LOD1. - Volume probe is mixed in to remove baked in artifacts in the higher LODs. Pull Request: https://projects.blender.org/blender/blender/pulls/119872
This commit is contained in:
parent
c056c58493
commit
aedd5f2837
@ -6573,8 +6573,7 @@ class VIEW3D_PT_shading_lighting(Panel):
|
||||
|
||||
col.prop(shading, "studiolight_intensity")
|
||||
col.prop(shading, "studiolight_background_alpha")
|
||||
if engine != 'BLENDER_EEVEE_NEXT':
|
||||
col.prop(shading, "studiolight_background_blur")
|
||||
col.prop(shading, "studiolight_background_blur")
|
||||
col = split.column() # to align properly with above
|
||||
|
||||
elif shading.type == 'RENDERED':
|
||||
@ -6599,8 +6598,7 @@ class VIEW3D_PT_shading_lighting(Panel):
|
||||
col.prop(shading, "studiolight_intensity")
|
||||
col.prop(shading, "studiolight_background_alpha")
|
||||
engine = context.scene.render.engine
|
||||
if engine != 'BLENDER_EEVEE_NEXT':
|
||||
col.prop(shading, "studiolight_background_blur")
|
||||
col.prop(shading, "studiolight_background_blur")
|
||||
col = split.column() # to align properly with above
|
||||
|
||||
|
||||
|
@ -202,6 +202,7 @@ class LightProbeModule {
|
||||
friend class VolumeProbeModule;
|
||||
friend class PlanarProbeModule;
|
||||
friend class SphereProbeModule;
|
||||
friend class BackgroundPipeline;
|
||||
|
||||
private:
|
||||
Instance &inst_;
|
||||
|
@ -72,6 +72,11 @@ class LookdevWorld {
|
||||
{
|
||||
return parameters_.background_opacity;
|
||||
}
|
||||
|
||||
float background_blur_get()
|
||||
{
|
||||
return parameters_.blur;
|
||||
}
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -24,7 +24,9 @@ namespace blender::eevee {
|
||||
* Used to draw background.
|
||||
* \{ */
|
||||
|
||||
void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacity)
|
||||
void BackgroundPipeline::sync(GPUMaterial *gpumat,
|
||||
const float background_opacity,
|
||||
const float background_blur)
|
||||
{
|
||||
Manager &manager = *inst_.manager;
|
||||
RenderBuffers &rbufs = inst_.render_buffers;
|
||||
@ -33,6 +35,9 @@ void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacit
|
||||
world_ps_.state_set(DRW_STATE_WRITE_COLOR);
|
||||
world_ps_.material_set(manager, gpumat);
|
||||
world_ps_.push_constant("world_opacity_fade", background_opacity);
|
||||
world_ps_.push_constant("world_background_blur", square_f(background_blur));
|
||||
SphereProbeData &world_data = *static_cast<SphereProbeData *>(&inst_.light_probes.world_sphere_);
|
||||
world_ps_.push_constant("world_coord_packed", reinterpret_cast<int4 *>(&world_data.atlas_coord));
|
||||
world_ps_.bind_texture("utility_tx", inst_.pipelines.utility_tx);
|
||||
/* RenderPasses & AOVs. Cleared by background (even if bad practice). */
|
||||
world_ps_.bind_image("rp_color_img", &rbufs.rp_color_tx);
|
||||
@ -41,6 +46,9 @@ void BackgroundPipeline::sync(GPUMaterial *gpumat, const float background_opacit
|
||||
/* Required by validation layers. */
|
||||
world_ps_.bind_resources(inst_.cryptomatte);
|
||||
world_ps_.bind_resources(inst_.uniform_data);
|
||||
world_ps_.bind_resources(inst_.sampling);
|
||||
world_ps_.bind_resources(inst_.sphere_probes);
|
||||
world_ps_.bind_resources(inst_.volume_probes);
|
||||
world_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
/* To allow opaque pass rendering over it. */
|
||||
world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
|
||||
@ -74,6 +82,8 @@ void WorldPipeline::sync(GPUMaterial *gpumat)
|
||||
Manager &manager = *inst_.manager;
|
||||
pass.material_set(manager, gpumat);
|
||||
pass.push_constant("world_opacity_fade", 1.0f);
|
||||
pass.push_constant("world_background_blur", 0.0f);
|
||||
pass.push_constant("world_coord_packed", int4(0.0f));
|
||||
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
|
||||
pass.bind_image("rp_normal_img", dummy_renderpass_tx_);
|
||||
pass.bind_image("rp_light_img", dummy_renderpass_tx_);
|
||||
@ -89,6 +99,9 @@ void WorldPipeline::sync(GPUMaterial *gpumat)
|
||||
/* Required by validation layers. */
|
||||
pass.bind_resources(inst_.cryptomatte);
|
||||
pass.bind_resources(inst_.uniform_data);
|
||||
pass.bind_resources(inst_.sampling);
|
||||
pass.bind_resources(inst_.sphere_probes);
|
||||
pass.bind_resources(inst_.volume_probes);
|
||||
pass.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ class BackgroundPipeline {
|
||||
public:
|
||||
BackgroundPipeline(Instance &inst) : inst_(inst){};
|
||||
|
||||
void sync(GPUMaterial *gpumat, float background_opacity);
|
||||
void sync(GPUMaterial *gpumat, float background_opacity, float background_blur);
|
||||
void render(View &view);
|
||||
};
|
||||
|
||||
|
@ -133,8 +133,9 @@ void World::sync()
|
||||
|
||||
float opacity = inst_.use_studio_light() ? lookdev_world_.background_opacity_get() :
|
||||
inst_.film.background_opacity_get();
|
||||
float background_blur = inst_.use_studio_light() ? lookdev_world_.background_blur_get() : 0.0;
|
||||
|
||||
inst_.pipelines.background.sync(gpumat, opacity);
|
||||
inst_.pipelines.background.sync(gpumat, opacity, background_blur);
|
||||
inst_.pipelines.world.sync(gpumat);
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,7 @@ void init_globals_curves()
|
||||
/* Random cosine normal distribution on the hair surface. */
|
||||
float noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy, UTIL_BLUE_NOISE_LAYER).x;
|
||||
# ifdef EEVEE_SAMPLING_DATA
|
||||
/* Needs to check for SAMPLING_DATA,
|
||||
* otherwise Surfel and World (?!?!) shader validation fails. */
|
||||
/* Needs to check for SAMPLING_DATA, otherwise surfel shader validation fails. */
|
||||
noise = fract(noise + sampling_rng_1D_get(SAMPLING_CURVES_U));
|
||||
# endif
|
||||
cos_theta = noise * 2.0 - 1.0;
|
||||
|
@ -13,6 +13,9 @@
|
||||
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_colorspace_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_reflection_probe_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_lightprobe_volume_eval_lib.glsl)
|
||||
|
||||
vec4 closure_to_rgba(Closure cl)
|
||||
{
|
||||
@ -38,6 +41,23 @@ void main()
|
||||
out_background.rgb = colorspace_safe_color(g_emission) * (1.0 - g_holdout);
|
||||
out_background.a = saturate(average(g_transmittance)) * g_holdout;
|
||||
|
||||
if (g_data.ray_type == RAY_TYPE_CAMERA && world_background_blur != 0.0 &&
|
||||
world_opacity_fade != 0.0)
|
||||
{
|
||||
float base_lod = sphere_probe_roughness_to_lod(world_background_blur);
|
||||
float lod = max(1.0, base_lod);
|
||||
float mix_factor = min(1.0, base_lod);
|
||||
SphereProbeUvArea world_atlas_coord = reinterpret_as_atlas_coord(world_coord_packed);
|
||||
vec4 probe_color = reflection_probes_sample(-g_data.N, lod, world_atlas_coord);
|
||||
out_background.rgb = mix(out_background.rgb, probe_color.rgb, mix_factor);
|
||||
|
||||
SphericalHarmonicL1 volume_irradiance = lightprobe_irradiance_sample(
|
||||
g_data.P, vec3(0.0), g_data.Ng);
|
||||
vec3 radiance_sh = spherical_harmonics_evaluate_lambert(-g_data.N, volume_irradiance);
|
||||
float radiance_mix_factor = sphere_probe_roughness_to_mix_fac(world_background_blur);
|
||||
out_background.rgb = mix(out_background.rgb, radiance_sh, radiance_mix_factor);
|
||||
}
|
||||
|
||||
/* World opacity. */
|
||||
out_background = mix(vec4(0.0, 0.0, 0.0, 1.0), out_background, world_opacity_fade);
|
||||
|
||||
|
@ -218,9 +218,14 @@ GPU_SHADER_CREATE_INFO(eevee_surf_depth)
|
||||
|
||||
GPU_SHADER_CREATE_INFO(eevee_surf_world)
|
||||
.push_constant(Type::FLOAT, "world_opacity_fade")
|
||||
.push_constant(Type::FLOAT, "world_background_blur")
|
||||
.push_constant(Type::IVEC4, "world_coord_packed")
|
||||
.fragment_out(0, Type::VEC4, "out_background")
|
||||
.fragment_source("eevee_surf_world_frag.glsl")
|
||||
.additional_info("eevee_global_ubo",
|
||||
"eevee_reflection_probe_data",
|
||||
"eevee_volume_probe_data",
|
||||
"eevee_sampling_data",
|
||||
/* Optionally added depending on the material. */
|
||||
// "eevee_render_pass_out",
|
||||
// "eevee_cryptomatte_out",
|
||||
|
Loading…
Reference in New Issue
Block a user