Added material_overlay property to MeshInstance3D

Applying overlay materials into multi-surface meshes currently
requires adding a next pass material to all the surfaces, which
might be cumbersome when the material is to be applied to a range
of different geometries. This also makes it not trivial to use
AnimationPlayer to control the material in case of visual effects.
The material_override property is not an option as it works
replacing the active material for the surfaces, not adding a new pass.

This commit adds the material_overlay property to GeometryInstance3D
(and therefore MeshInstance3D), having the same reach as
material_override (that is, all surfaces) but adding a new material
pass on top of the active materials, instead of replacing them.
This commit is contained in:
Fernando Cosentino 2021-09-25 19:40:26 +01:00 committed by Rémi Verschelde
parent 2c7fcdd7f9
commit ca79373d13
No known key found for this signature in database
GPG key ID: C3336907360768E1
18 changed files with 147 additions and 20 deletions

View file

@ -636,6 +636,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay);
scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
@ -1222,6 +1223,19 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
}
}
void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, RID p_material) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
instance->material_overlay = p_material;
_instance_queue_update(instance, false, true);
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material);
}
}
void RendererSceneCull::instance_geometry_set_visibility_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin, RS::VisibilityRangeFadeMode p_fade_mode) {
Instance *instance = instance_owner.get_or_null(p_instance);
ERR_FAIL_COND(!instance);
@ -3656,6 +3670,10 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
RSG::storage->material_update_dependency(p_instance->material_override, &p_instance->dependency_tracker);
}
if (p_instance->material_overlay.is_valid()) {
RSG::storage->material_update_dependency(p_instance->material_overlay, &p_instance->dependency_tracker);
}
if (p_instance->base_type == RS::INSTANCE_MESH) {
//remove materials no longer used and un-own them
@ -3785,6 +3803,12 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
}
if (p_instance->material_overlay.is_valid()) {
can_cast_shadows = can_cast_shadows || RSG::storage->material_casts_shadows(p_instance->material_overlay);
is_animated = is_animated || RSG::storage->material_is_animated(p_instance->material_overlay);
_update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
}
if (can_cast_shadows != geom->can_cast_shadows) {
//ability to cast shadows change, let lights now
for (Set<Instance *>::Element *E = geom->lights.front(); E; E = E->next()) {
@ -3897,6 +3921,7 @@ bool RendererSceneCull::free(RID p_rid) {
instance_set_scenario(p_rid, RID());
instance_set_base(p_rid, RID());
instance_geometry_set_material_override(p_rid, RID());
instance_geometry_set_material_overlay(p_rid, RID());
instance_attach_skeleton(p_rid, RID());
if (instance->instance_allocated_shader_parameters) {