Merge pull request #50823 from fbcosentino/3d-material-overlay
This commit is contained in:
commit
4103b0b7d8
17 changed files with 124 additions and 0 deletions
|
@ -61,6 +61,10 @@
|
|||
The GeometryInstance's min LOD margin.
|
||||
[b]Note:[/b] This property currently has no effect.
|
||||
</member>
|
||||
<member name="material_overlay" type="Material" setter="set_material_overlay" getter="get_material_overlay">
|
||||
The material overlay for the whole geometry.
|
||||
If a material is assigned to this property, it will be rendered on top of any other active material for all the surfaces.
|
||||
</member>
|
||||
<member name="material_override" type="Material" setter="set_material_override" getter="get_material_override">
|
||||
The material override for the whole geometry.
|
||||
If a material is assigned to this property, it will be used instead of any material set in any material slot of the mesh.
|
||||
|
|
|
@ -1374,6 +1374,14 @@
|
|||
Sets the flag for a given [enum InstanceFlags]. See [enum InstanceFlags] for more details.
|
||||
</description>
|
||||
</method>
|
||||
<method name="instance_geometry_set_material_overlay">
|
||||
<return type="void" />
|
||||
<argument index="0" name="instance" type="RID" />
|
||||
<argument index="1" name="material" type="RID" />
|
||||
<description>
|
||||
Sets a material that will be rendered for all surfaces on top of active materials for the mesh associated with this instance. Equivalent to [member GeometryInstance.material_overlay].
|
||||
</description>
|
||||
</method>
|
||||
<method name="instance_geometry_set_material_override">
|
||||
<return type="void" />
|
||||
<argument index="0" name="instance" type="RID" />
|
||||
|
|
|
@ -979,6 +979,27 @@ void RasterizerSceneGLES2::_add_geometry(RasterizerStorageGLES2::Geometry *p_geo
|
|||
|
||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
||||
}
|
||||
|
||||
// Repeat the "nested chain" logic also for the overlay
|
||||
if (p_instance->material_overlay.is_valid()) {
|
||||
material = storage->material_owner.getornull(p_instance->material_overlay);
|
||||
|
||||
if (!material || !material->shader || !material->shader->valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
||||
|
||||
while (material->next_pass.is_valid()) {
|
||||
material = storage->material_owner.getornull(material->next_pass);
|
||||
|
||||
if (!material || !material->shader || !material->shader->valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, material, p_depth_pass, p_shadow_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass) {
|
||||
bool has_base_alpha = (p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.uses_screen_texture || p_material->shader->spatial.uses_depth_texture;
|
||||
|
|
|
@ -5899,6 +5899,10 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
|
|||
ins->material_override = RID();
|
||||
}
|
||||
|
||||
if (ins->material_overlay == p_rid) {
|
||||
ins->material_overlay = RID();
|
||||
}
|
||||
|
||||
for (int i = 0; i < ins->materials.size(); i++) {
|
||||
if (ins->materials[i] == p_rid) {
|
||||
ins->materials.write[i] = RID();
|
||||
|
|
|
@ -2222,6 +2222,27 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo
|
|||
}
|
||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass);
|
||||
}
|
||||
|
||||
// Repeat the "nested chain" logic also for the overlay
|
||||
if (p_instance->material_overlay.is_valid()) {
|
||||
m = storage->material_owner.getornull(p_instance->material_overlay);
|
||||
|
||||
if (!m || !m->shader || !m->shader->valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass);
|
||||
|
||||
while (m->next_pass.is_valid()) {
|
||||
m = storage->material_owner.getornull(m->next_pass);
|
||||
|
||||
if (!m || !m->shader || !m->shader->valid) {
|
||||
break;
|
||||
}
|
||||
|
||||
_add_geometry_with_material(p_geometry, p_instance, p_owner, m, p_depth_pass, p_shadow_pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass, bool p_shadow_pass) {
|
||||
|
|
|
@ -7787,10 +7787,15 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
|
|||
}
|
||||
for (Map<RasterizerScene::InstanceBase *, int>::Element *E = material->instance_owners.front(); E; E = E->next()) {
|
||||
RasterizerScene::InstanceBase *ins = E->key();
|
||||
|
||||
if (ins->material_override == p_rid) {
|
||||
ins->material_override = RID();
|
||||
}
|
||||
|
||||
if (ins->material_overlay == p_rid) {
|
||||
ins->material_overlay = RID();
|
||||
}
|
||||
|
||||
for (int i = 0; i < ins->materials.size(); i++) {
|
||||
if (ins->materials[i] == p_rid) {
|
||||
ins->materials.write[i] = RID();
|
||||
|
|
|
@ -733,6 +733,14 @@ void MeshInstance::set_material_override(const Ref<Material> &p_material) {
|
|||
}
|
||||
}
|
||||
|
||||
void MeshInstance::set_material_overlay(const Ref<Material> &p_material) {
|
||||
if (p_material == get_material_overlay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GeometryInstance::set_material_overlay(p_material);
|
||||
}
|
||||
|
||||
void MeshInstance::set_software_skinning_transform_normals(bool p_enabled) {
|
||||
if (p_enabled == is_software_skinning_transform_normals_enabled()) {
|
||||
return;
|
||||
|
@ -852,6 +860,11 @@ bool MeshInstance::is_mergeable_with(const MeshInstance &p_other) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// overlay materials must match
|
||||
if (get_material_overlay() != p_other.get_material_overlay()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int n = 0; n < num_surfaces; n++) {
|
||||
// materials must match
|
||||
if (get_active_material(n) != p_other.get_active_material(n)) {
|
||||
|
@ -1154,6 +1167,9 @@ bool MeshInstance::create_by_merging(Vector<MeshInstance *> p_list) {
|
|||
set_surface_material(n, first->get_active_material(n));
|
||||
}
|
||||
|
||||
// set overlay material
|
||||
set_material_overlay(first->get_material_overlay());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,8 @@ public:
|
|||
|
||||
virtual void set_material_override(const Ref<Material> &p_material);
|
||||
|
||||
virtual void set_material_overlay(const Ref<Material> &p_material);
|
||||
|
||||
void set_software_skinning_transform_normals(bool p_enabled);
|
||||
bool is_software_skinning_transform_normals_enabled() const;
|
||||
|
||||
|
|
|
@ -175,6 +175,15 @@ Ref<Material> GeometryInstance::get_material_override() const {
|
|||
return material_override;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_material_overlay(const Ref<Material> &p_material) {
|
||||
material_overlay = p_material;
|
||||
VS::get_singleton()->instance_geometry_set_material_overlay(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
|
||||
}
|
||||
|
||||
Ref<Material> GeometryInstance::get_material_overlay() const {
|
||||
return material_overlay;
|
||||
}
|
||||
|
||||
void GeometryInstance::set_generate_lightmap(bool p_enabled) {
|
||||
generate_lightmap = p_enabled;
|
||||
}
|
||||
|
@ -275,6 +284,9 @@ void GeometryInstance::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_material_override", "material"), &GeometryInstance::set_material_override);
|
||||
ClassDB::bind_method(D_METHOD("get_material_override"), &GeometryInstance::get_material_override);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_material_overlay", "material"), &GeometryInstance::set_material_overlay);
|
||||
ClassDB::bind_method(D_METHOD("get_material_overlay"), &GeometryInstance::get_material_overlay);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_flag", "flag", "value"), &GeometryInstance::set_flag);
|
||||
ClassDB::bind_method(D_METHOD("get_flag", "flag"), &GeometryInstance::get_flag);
|
||||
|
||||
|
@ -308,6 +320,7 @@ void GeometryInstance::_bind_methods() {
|
|||
|
||||
ADD_GROUP("Geometry", "");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"), "set_material_override", "get_material_override");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_overlay", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,SpatialMaterial"), "set_material_overlay", "get_material_overlay");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "cast_shadow", PROPERTY_HINT_ENUM, "Off,On,Double-Sided,Shadows Only"), "set_cast_shadows_setting", "get_cast_shadows_setting");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::REAL, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ private:
|
|||
LightmapScale lightmap_scale;
|
||||
ShadowCastingSetting shadow_casting_setting;
|
||||
Ref<Material> material_override;
|
||||
Ref<Material> material_overlay;
|
||||
float lod_min_distance;
|
||||
float lod_max_distance;
|
||||
float lod_min_hysteresis;
|
||||
|
@ -152,6 +153,9 @@ public:
|
|||
virtual void set_material_override(const Ref<Material> &p_material);
|
||||
Ref<Material> get_material_override() const;
|
||||
|
||||
virtual void set_material_overlay(const Ref<Material> &p_material);
|
||||
Ref<Material> get_material_overlay() const;
|
||||
|
||||
void set_extra_cull_margin(float p_margin);
|
||||
float get_extra_cull_margin() const;
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
|
||||
RID skeleton;
|
||||
RID material_override;
|
||||
RID material_overlay;
|
||||
|
||||
Transform transform;
|
||||
|
||||
|
|
|
@ -618,6 +618,7 @@ public:
|
|||
BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
||||
BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
|
||||
BIND2(instance_geometry_set_material_override, RID, RID)
|
||||
BIND2(instance_geometry_set_material_overlay, RID, RID)
|
||||
|
||||
BIND5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||
BIND2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||
|
|
|
@ -1520,6 +1520,20 @@ void VisualServerScene::instance_geometry_set_material_override(RID p_instance,
|
|||
VSG::storage->material_add_instance_owner(instance->material_override, instance);
|
||||
}
|
||||
}
|
||||
void VisualServerScene::instance_geometry_set_material_overlay(RID p_instance, RID p_material) {
|
||||
Instance *instance = instance_owner.get(p_instance);
|
||||
ERR_FAIL_COND(!instance);
|
||||
|
||||
if (instance->material_overlay.is_valid()) {
|
||||
VSG::storage->material_remove_instance_owner(instance->material_overlay, instance);
|
||||
}
|
||||
instance->material_overlay = p_material;
|
||||
instance->base_changed(false, true);
|
||||
|
||||
if (instance->material_overlay.is_valid()) {
|
||||
VSG::storage->material_add_instance_owner(instance->material_overlay, instance);
|
||||
}
|
||||
}
|
||||
|
||||
void VisualServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) {
|
||||
}
|
||||
|
@ -3988,6 +4002,11 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
|
|||
}
|
||||
}
|
||||
|
||||
if (p_instance->material_overlay.is_valid()) {
|
||||
can_cast_shadows = can_cast_shadows || VSG::storage->material_casts_shadows(p_instance->material_overlay);
|
||||
is_animated = is_animated || VSG::storage->material_is_animated(p_instance->material_overlay);
|
||||
}
|
||||
|
||||
if (can_cast_shadows != geom->can_cast_shadows) {
|
||||
//ability to cast shadows change, let lights now
|
||||
for (List<Instance *>::Element *E = geom->lighting.front(); E; E = E->next()) {
|
||||
|
@ -4057,6 +4076,7 @@ bool VisualServerScene::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());
|
||||
|
||||
update_dirty_instances(); //in case something changed this
|
||||
|
|
|
@ -690,6 +690,7 @@ public:
|
|||
virtual void instance_geometry_set_flag(RID p_instance, VS::InstanceFlags p_flags, bool p_enabled);
|
||||
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting);
|
||||
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
|
||||
virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material);
|
||||
|
||||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin);
|
||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance);
|
||||
|
|
|
@ -541,6 +541,7 @@ public:
|
|||
FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool)
|
||||
FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting)
|
||||
FUNC2(instance_geometry_set_material_override, RID, RID)
|
||||
FUNC2(instance_geometry_set_material_overlay, RID, RID)
|
||||
|
||||
FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float)
|
||||
FUNC2(instance_geometry_set_as_instance_lod, RID, RID)
|
||||
|
|
|
@ -2144,6 +2144,7 @@ void VisualServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &VisualServer::instance_geometry_set_flag);
|
||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &VisualServer::instance_geometry_set_cast_shadows_setting);
|
||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &VisualServer::instance_geometry_set_material_override);
|
||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_material_overlay", "instance", "material"), &VisualServer::instance_geometry_set_material_overlay);
|
||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_draw_range", "instance", "min", "max", "min_margin", "max_margin"), &VisualServer::instance_geometry_set_draw_range);
|
||||
ClassDB::bind_method(D_METHOD("instance_geometry_set_as_instance_lod", "instance", "as_lod_of_instance"), &VisualServer::instance_geometry_set_as_instance_lod);
|
||||
|
||||
|
|
|
@ -961,6 +961,7 @@ public:
|
|||
virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0;
|
||||
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0;
|
||||
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0;
|
||||
virtual void instance_geometry_set_material_overlay(RID p_instance, RID p_material) = 0;
|
||||
|
||||
virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0;
|
||||
virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0;
|
||||
|
|
Loading…
Reference in a new issue