EEVEE-Next: New shadow settings #113980

Merged
Miguel Pozo merged 20 commits from pragma37/blender:pull-eevee-shadow-settings into main 2023-11-06 15:45:10 +01:00
15 changed files with 108 additions and 35 deletions

View File

@ -1013,12 +1013,6 @@ class CyclesMaterialSettings(bpy.types.PropertyGroup):
default="AUTO",
)
use_transparent_shadow: BoolProperty(
name="Transparent Shadows",
description="Use transparent shadows for this material if it contains a Transparent BSDF, "
"disabling will render faster but not give accurate shadows",
default=True,
)
use_bump_map_correction: BoolProperty(
name="Bump Map Correction",
description="Apply corrections to solve shadow terminator artifacts caused by bump mapping",

View File

@ -1966,7 +1966,7 @@ class CYCLES_MATERIAL_PT_settings_surface(CyclesButtonsPanel, Panel):
col = layout.column()
col.prop(cmat, "displacement_method", text="Displacement")
col.prop(cmat, "emission_sampling")
col.prop(cmat, "use_transparent_shadow")
col.prop(mat, "use_transparent_shadow")
col.prop(cmat, "use_bump_map_correction")
def draw(self, context):

View File

@ -1550,7 +1550,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
/* settings */
PointerRNA cmat = RNA_pointer_get(&b_mat.ptr, "cycles");
shader->set_emission_sampling_method(get_emission_sampling(cmat));
shader->set_use_transparent_shadow(get_boolean(cmat, "use_transparent_shadow"));
shader->set_use_transparent_shadow(b_mat.use_transparent_shadow());
shader->set_use_bump_map_correction(get_boolean(cmat, "use_bump_map_correction"));
shader->set_heterogeneous_volume(!get_boolean(cmat, "homogeneous_volume"));
shader->set_volume_sampling_method(get_volume_sampling(cmat));

View File

@ -300,7 +300,7 @@ class EEVEE_NEXT_MATERIAL_PT_settings_surface(MaterialButtonsPanel, Panel):
col.prop(mat, "use_backface_culling_shadow", text="Shadow")
# TODO(fclem): Displacement option
# TODO(fclem): Transparent shadow option
layout.prop(mat, "use_transparent_shadow")
col = layout.column()
col.prop(mat, "surface_render_method", text="Render Method")

View File

@ -390,6 +390,11 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
col.prop(ob, "hide_render", text="Renders", toggle=False, invert_checkbox=True)
if context.engine == 'BLENDER_EEVEE_NEXT':
if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'CURVES', 'POINTCLOUD', 'VOLUME'}:
layout.separator()
col = layout.column(heading="Ray Visibility")
col.prop(ob, "visible_shadow", text="Shadow", toggle=False)
fclem marked this conversation as resolved

Use hide_shadow for consistency with the other visibility options for now.

Use `hide_shadow` for consistency with the other visibility options for now.
Review

I think having 2 different Python properties that change the same flag is going to be quite confusing for Python users.

I think having 2 different Python properties that change the same flag is going to be quite confusing for Python users.

Nevermind, I replied to this before we decided to unify the setting first. So use cycles naming convention for now. We can still create an alias if we decide to port it later.

I think having 2 different Python properties that change the same flag is going to be quite confusing for Python users.

We can do that for compatibility reasons.

Nevermind, I replied to this before we decided to unify the setting first. So use cycles naming convention for now. We can still create an alias if we decide to port it later. > I think having 2 different Python properties that change the same flag is going to be quite confusing for Python users. We can do that for compatibility reasons.
if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT', 'CURVES', 'POINTCLOUD', 'VOLUME', 'LIGHT'}:
layout.separator()
col = layout.column(heading="Light Probes")

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 4
#define BLENDER_FILE_SUBVERSION 5
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@ -47,11 +47,13 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_attribute.h"
#include "BKE_collection.h"
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_grease_pencil.hh"
#include "BKE_idprop.hh"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh_legacy_convert.hh"
#include "BKE_node.hh"
#include "BKE_node_runtime.hh"
@ -298,6 +300,30 @@ static void version_principled_bsdf_update_animdata(ID *owner_id, bNodeTree *ntr
}
}
static void versioning_eevee_shadow_settings(Object *object)
{
/** EEVEE no longer uses the Material::blend_shadow property.
* Instead, it uses Object::visibility_flag for disabling shadow casting
*/
short *material_len = BKE_object_material_len_p(object);
if (!material_len) {
return;
}
using namespace blender;
bool hide_shadows = *material_len > 0;
for (int i : IndexRange(*material_len)) {
Material *material = BKE_object_material_get(object, i + 1);
if (!material || material->blend_shadow != MA_BS_NONE) {
hide_shadows = false;
}
}
/* Enable the hide_shadow flag only if there's not any shadow casting material. */
SET_FLAG_FROM_TEST(object->visibility_flag, hide_shadows, OB_HIDE_SHADOW);
}
void do_versions_after_linking_400(FileData *fd, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 9)) {
@ -382,6 +408,16 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
BKE_mesh_legacy_face_map_to_generic(bmain);
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
Scene *scene = static_cast<Scene *>(bmain->scenes.first);
bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES);
if (!is_cycles) {
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
versioning_eevee_shadow_settings(object);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*
@ -1783,6 +1819,29 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 401, 5)) {
/* Unify Material::blend_shadow and Cycles.use_transparent_shadows into the
* Material::blend_flag. */
Scene *scene = static_cast<Scene *>(bmain->scenes.first);
bool is_cycles = scene && STREQ(scene->r.engine, RE_engine_id_CYCLES);
if (is_cycles) {
LISTBASE_FOREACH (Material *, material, &bmain->materials) {
bool transparent_shadows = true;
pragma37 marked this conversation as resolved Outdated

I'm not really sure what the purpose is of this logic. Why not just set this to true? The previous Cycles default does not depend on this DNA default.

I'm not really sure what the purpose is of this logic. Why not just set this to `true`? The previous Cycles default does not depend on this DNA default.
if (IDProperty *cmat = version_cycles_properties_from_ID(&material->id)) {
transparent_shadows = version_cycles_property_boolean(
cmat, "use_transparent_shadow", true);
}
SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadows, MA_BL_TRANSPARENT_SHADOW);
}
}
else {
LISTBASE_FOREACH (Material *, material, &bmain->materials) {
bool transparent_shadow = material->blend_shadow != MA_BS_SOLID;
SET_FLAG_FROM_TEST(material->blend_flag, transparent_shadow, MA_BL_TRANSPARENT_SHADOW);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*

View File

@ -69,19 +69,24 @@ enum eMaterialProbe {
static inline void material_type_from_shader_uuid(uint64_t shader_uuid,
eMaterialPipeline &pipeline_type,
eMaterialGeometry &geometry_type)
eMaterialGeometry &geometry_type,
bool &transparent_shadows)
{
const uint64_t geometry_mask = ((1u << 4u) - 1u);
const uint64_t pipeline_mask = ((1u << 4u) - 1u);
geometry_type = static_cast<eMaterialGeometry>(shader_uuid & geometry_mask);
pipeline_type = static_cast<eMaterialPipeline>((shader_uuid >> 4u) & pipeline_mask);
transparent_shadows = (shader_uuid >> 8u) & 1u;
}
static inline uint64_t shader_uuid_from_material_type(eMaterialPipeline pipeline_type,
eMaterialGeometry geometry_type)
eMaterialGeometry geometry_type,
char blend_flags)
{
BLI_assert(geometry_type < (1 << 4));
return geometry_type | (pipeline_type << 4);
BLI_assert(pipeline_type < (1 << 4));
uchar transparent_shadows = blend_flags & MA_BL_TRANSPARENT_SHADOW ? 1 : 0;
return geometry_type | (pipeline_type << 4) | (transparent_shadows << 8);
}
ENUM_OPERATORS(eClosureBits, CLOSURE_AMBIENT_OCCLUSION)
@ -142,7 +147,7 @@ struct MaterialKey {
MaterialKey(::Material *mat_, eMaterialGeometry geometry, eMaterialPipeline pipeline) : mat(mat_)
{
options = shader_uuid_from_material_type(pipeline, geometry);
options = shader_uuid_from_material_type(pipeline, geometry, mat_->blend_flag);
}
uint64_t hash() const

View File

@ -311,7 +311,8 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
eMaterialPipeline pipeline_type;
eMaterialGeometry geometry_type;
material_type_from_shader_uuid(shader_uuid, pipeline_type, geometry_type);
bool transparent_shadows;
material_type_from_shader_uuid(shader_uuid, pipeline_type, geometry_type, transparent_shadows);
GPUCodegenOutput &codegen = *codegen_;
ShaderCreateInfo &info = *reinterpret_cast<ShaderCreateInfo *>(codegen.create_info);
@ -356,7 +357,9 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
}
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
info.define("MAT_TRANSPARENT");
if (pipeline_type != MAT_PIPE_SHADOW || transparent_shadows) {
info.define("MAT_TRANSPARENT");
}
/* Transparent material do not have any velocity specific pipeline. */
if (pipeline_type == MAT_PIPE_PREPASS_FORWARD_VELOCITY) {
pipeline_type = MAT_PIPE_PREPASS_FORWARD;
@ -641,7 +644,8 @@ GPUMaterial *ShaderModule::material_shader_get(::Material *blender_mat,
{
bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_MATERIAL, MAT_PIPE_VOLUME_OCCUPANCY);
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type);
uint64_t shader_uuid = shader_uuid_from_material_type(
pipeline_type, geometry_type, blender_mat->blend_flag);
return DRW_shader_from_material(
blender_mat, nodetree, shader_uuid, is_volume, deferred_compilation, codegen_callback, this);
@ -656,7 +660,7 @@ GPUMaterial *ShaderModule::world_shader_get(::World *blender_world,
eMaterialGeometry geometry_type = is_volume ? MAT_GEOM_VOLUME_WORLD : MAT_GEOM_WORLD;
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type);
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type, 0);
return DRW_shader_from_world(
blender_world, nodetree, shader_uuid, is_volume, defer_compilation, codegen_callback, this);
@ -671,7 +675,7 @@ GPUMaterial *ShaderModule::material_shader_get(const char *name,
eMaterialGeometry geometry_type,
bool is_lookdev)
{
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type);
uint64_t shader_uuid = shader_uuid_from_material_type(pipeline_type, geometry_type, 0);
bool is_volume = ELEM(pipeline_type, MAT_PIPE_VOLUME_MATERIAL, MAT_PIPE_VOLUME_OCCUPANCY);

View File

@ -893,11 +893,12 @@ void ShadowModule::begin_sync()
}
}
void ShadowModule::sync_object(const ObjectHandle &handle,
void ShadowModule::sync_object(const Object *ob,
const ObjectHandle &handle,
const ResourceHandle &resource_handle,
bool is_shadow_caster,
bool is_alpha_blend)
{
bool is_shadow_caster = !(ob->visibility_flag & OB_HIDE_SHADOW);
if (!is_shadow_caster && !is_alpha_blend) {
return;
}

View File

@ -328,9 +328,9 @@ class ShadowModule {
void begin_sync();
/** Register a shadow caster or receiver. */
void sync_object(const ObjectHandle &handle,
void sync_object(const Object *ob,
const ObjectHandle &handle,
const ResourceHandle &resource_handle,
bool is_shadow_caster,
bool is_alpha_blend);
void end_sync();

View File

@ -140,7 +140,6 @@ void SyncModule::sync_mesh(Object *ob,
return;
}
bool is_shadow_caster = false;
bool is_alpha_blend = false;
for (auto i : material_array.gpu_materials.index_range()) {
GPUBatch *geom = mat_geom[i];
@ -173,7 +172,6 @@ void SyncModule::sync_mesh(Object *ob,
geometry_call(material.reflection_probe_prepass.sub_pass, geom, res_handle);
geometry_call(material.reflection_probe_shading.sub_pass, geom, res_handle);
is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr;
is_alpha_blend = is_alpha_blend || material.is_alpha_blend_transparent;
::Material *mat = GPU_material_get_material(gpu_material);
@ -182,7 +180,7 @@ void SyncModule::sync_mesh(Object *ob,
inst_.manager->extract_object_attributes(res_handle, ob_ref, material_array.gpu_materials);
inst_.shadows.sync_object(ob_handle, res_handle, is_shadow_caster, is_alpha_blend);
inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend);
inst_.cryptomatte.sync_object(ob, res_handle);
}
@ -215,7 +213,6 @@ bool SyncModule::sync_sculpt(Object *ob,
bool has_motion = false;
MaterialArray &material_array = inst_.materials.material_array_get(ob, has_motion);
bool is_shadow_caster = false;
bool is_alpha_blend = false;
for (SculptBatch &batch :
sculpt_batches_per_material_get(ob_ref.object, material_array.gpu_materials))
@ -249,7 +246,6 @@ bool SyncModule::sync_sculpt(Object *ob,
geometry_call(material.reflection_probe_prepass.sub_pass, geom, res_handle);
geometry_call(material.reflection_probe_shading.sub_pass, geom, res_handle);
is_shadow_caster = is_shadow_caster || material.shadow.sub_pass != nullptr;
is_alpha_blend = is_alpha_blend || material.is_alpha_blend_transparent;
GPUMaterial *gpu_material = material_array.gpu_materials[batch.material_slot];
@ -259,7 +255,7 @@ bool SyncModule::sync_sculpt(Object *ob,
inst_.manager->extract_object_attributes(res_handle, ob_ref, material_array.gpu_materials);
inst_.shadows.sync_object(ob_handle, res_handle, is_shadow_caster, is_alpha_blend);
inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend);
inst_.cryptomatte.sync_object(ob, res_handle);
return true;
@ -322,9 +318,8 @@ void SyncModule::sync_point_cloud(Object *ob,
::Material *mat = GPU_material_get_material(gpu_material);
inst_.cryptomatte.sync_material(mat);
bool is_caster = material.shadow.sub_pass != nullptr;
bool is_alpha_blend = material.is_alpha_blend_transparent;
inst_.shadows.sync_object(ob_handle, res_handle, is_caster, is_alpha_blend);
inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend);
}
/** \} */
@ -486,9 +481,8 @@ void SyncModule::sync_gpencil(Object *ob, ObjectHandle &ob_handle, ResourceHandl
gpencil_drawcall_flush(iter);
bool is_caster = true; /* TODO material.shadow.sub_pass. */
bool is_alpha_blend = true; /* TODO material.is_alpha_blend. */
inst_.shadows.sync_object(ob_handle, res_handle, is_caster, is_alpha_blend);
inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend);
}
/** \} */
@ -557,9 +551,8 @@ void SyncModule::sync_curves(Object *ob,
::Material *mat = GPU_material_get_material(gpu_material);
inst_.cryptomatte.sync_material(mat);
bool is_caster = material.shadow.sub_pass != nullptr;
bool is_alpha_blend = material.is_alpha_blend_transparent;
inst_.shadows.sync_object(ob_handle, res_handle, is_caster, is_alpha_blend);
inst_.shadows.sync_object(ob, ob_handle, res_handle, is_alpha_blend);
}
/** \} */

View File

@ -33,6 +33,8 @@
.alpha_threshold = 0.5f, \
\
.blend_shadow = MA_BS_SOLID, \
\
.blend_flag = MA_BL_TRANSPARENT_SHADOW,\
\
.lineart.mat_occlusion = 1, \
}

View File

@ -360,6 +360,7 @@ enum {
MA_BL_TRANSLUCENCY = (1 << 3),
MA_BL_LIGHTPROBE_VOLUME_DOUBLE_SIDED = (1 << 4),
MA_BL_CULL_BACKFACE_SHADOW = (1 << 5),
MA_BL_TRANSPARENT_SHADOW = (1 << 6),
};
/** #Material::blend_shadow */

View File

@ -909,6 +909,15 @@ void RNA_def_material(BlenderRNA *brna)
prop, "Shadow Backface Culling", "Use back face culling when casting shadows");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
prop = RNA_def_property(srna, "use_transparent_shadow", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "blend_flag", MA_BL_TRANSPARENT_SHADOW);
RNA_def_property_ui_text(
prop,
"Transparent Shadows",
"Use transparent shadows for this material if it contains a Transparent BSDF, "
"disabling will render faster but not give accurate shadows");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
prop = RNA_def_property(srna, "lightprobe_volume_single_sided", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(
prop, nullptr, "blend_flag", MA_BL_LIGHTPROBE_VOLUME_DOUBLE_SIDED);