Skip to content

Commit

Permalink
Implement distance fade and transparency
Browse files Browse the repository at this point in the history
The built-in ALPHA in spatial shaders comes pre-set with a per-instance
transparency value. Multiply by it if you want to keep it.

The transparency value of any given GeometryInstance3D is affected by:
   - Its new "transparency" property.
   - Its own visiblity range when the new "visibility_range_fade_mode"
     property is set to "Self".
   - Its parent visibility range when the parent's fade mode is
     set to "Dependencies".

The "Self" mode will fade-out the instance when reaching the visibility
range limits, while the "Dependencies" mode will fade-in its
dependencies.

Per-instance transparency is only implemented in the forward clustered
renderer, support for mobile should be added in the future.

Co-authored-by: reduz <[email protected]>
  • Loading branch information
JFonS and reduz committed Oct 25, 2021
1 parent 88d9914 commit c571e4a
Show file tree
Hide file tree
Showing 21 changed files with 371 additions and 92 deletions.
17 changes: 16 additions & 1 deletion doc/classes/GeometryInstance3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,24 @@
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.
</member>
<member name="transparency" type="float" setter="set_transparency" getter="get_transparency" default="0.0">
Transparency applied to the whole geometry. In spatial shaders, transparency is set as the default value of the [code]ALPHA[/code] built-in.
</member>
<member name="visibility_range_begin" type="float" setter="set_visibility_range_begin" getter="get_visibility_range_begin" default="0.0">
Starting distance from which the GeometryInstance3D will be visible, taking [member visibility_range_begin_margin] into account as well. The default value of 0 is used to disable the range check.
</member>
<member name="visibility_range_begin_margin" type="float" setter="set_visibility_range_begin_margin" getter="get_visibility_range_begin_margin" default="0.0">
Margin for the [member visibility_range_begin] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_begin] threshold by this amount.
</member>
<member name="visibility_range_end" type="float" setter="set_visibility_range_end" getter="get_visibility_range_end" default="0.0">
Distance from which the GeometryInstance3D will be hidden, taking [member visibility_range_end_margin] into account as well. The default value of 0 is used to disable the range check..
Distance from which the GeometryInstance3D will be hidden, taking [member visibility_range_end_margin] into account as well. The default value of 0 is used to disable the range check.
</member>
<member name="visibility_range_end_margin" type="float" setter="set_visibility_range_end_margin" getter="get_visibility_range_end_margin" default="0.0">
Margin for the [member visibility_range_end] threshold. The GeometryInstance3D will only change its visibility state when it goes over or under the [member visibility_range_end] threshold by this amount.
</member>
<member name="visibility_range_fade_mode" type="int" setter="set_visibility_range_fade_mode" getter="get_visibility_range_fade_mode" enum="GeometryInstance3D.VisibilityRangeFadeMode" default="0">
Controls which instances will be faded when approaching the limits of the visibility range. See [enum VisibilityRangeFadeMode] for possible values.
</member>
</members>
<constants>
<constant name="SHADOW_CASTING_SETTING_OFF" value="0" enum="ShadowCastingSetting">
Expand Down Expand Up @@ -94,5 +100,14 @@
</constant>
<constant name="LIGHTMAP_SCALE_MAX" value="4" enum="LightmapScale">
</constant>
<constant name="VISIBILITY_RANGE_FADE_DISABLED" value="0" enum="VisibilityRangeFadeMode">
Will not fade itself nor its visibility dependencies, hysteresis will be used instead. See [member visibility_range_begin] and [member Node3D.visibility_parent] for more information.
</constant>
<constant name="VISIBILITY_RANGE_FADE_SELF" value="1" enum="VisibilityRangeFadeMode">
Will fade-out itself when reaching the limits of its own visibility range. The fading range is determined by [member visibility_range_begin_margin] and [member visibility_range_end_margin].
</constant>
<constant name="VISIBILITY_RANGE_FADE_DEPENDENCIES" value="2" enum="VisibilityRangeFadeMode">
Will fade-in its visibility dependencies (see [member Node3D.visibility_parent]) when reaching the limits of its own visibility range. The fading range is determined by [member visibility_range_begin_margin] and [member visibility_range_end_margin].
</constant>
</constants>
</class>
18 changes: 18 additions & 0 deletions doc/classes/RenderingServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1377,13 +1377,22 @@
<description>
</description>
</method>
<method name="instance_geometry_set_transparency">
<return type="void" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="transparency" type="float" />
<description>
Sets the transparency for the given geometry instance. Equivalent to [member GeometryInstance3D.transparency].
</description>
</method>
<method name="instance_geometry_set_visibility_range">
<return type="void" />
<argument index="0" name="instance" type="RID" />
<argument index="1" name="min" type="float" />
<argument index="2" name="max" type="float" />
<argument index="3" name="min_margin" type="float" />
<argument index="4" name="max_margin" type="float" />
<argument index="5" name="fade_mode" type="int" enum="RenderingServer.VisibilityRangeFadeMode" />
<description>
Sets the visibility range values for the given geometry instance. Equivalent to [member GeometryInstance3D.visibility_range_begin] and related properties.
</description>
Expand Down Expand Up @@ -4178,6 +4187,15 @@
<constant name="SHADOW_CASTING_SETTING_SHADOWS_ONLY" value="3" enum="ShadowCastingSetting">
Only render the shadows from the object. The object itself will not be drawn.
</constant>
<constant name="VISIBILITY_RANGE_FADE_DISABLED" value="0" enum="VisibilityRangeFadeMode">
Disable visibility range fading for the given instance.
</constant>
<constant name="VISIBILITY_RANGE_FADE_SELF" value="1" enum="VisibilityRangeFadeMode">
Fade-out the given instance when it approaches its visibility range limits.
</constant>
<constant name="VISIBILITY_RANGE_FADE_DEPENDENCIES" value="2" enum="VisibilityRangeFadeMode">
Fade-in the given instance's dependencies when reaching its visibility range limits.
</constant>
<constant name="BAKE_CHANNEL_ALBEDO_ALPHA" value="0" enum="BakeChannels">
</constant>
<constant name="BAKE_CHANNEL_NORMAL" value="1" enum="BakeChannels">
Expand Down
39 changes: 34 additions & 5 deletions scene/3d/visual_instance_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,18 @@ Ref<Material> GeometryInstance3D::get_material_override() const {
return material_override;
}

void GeometryInstance3D::set_transparecy(float p_transparency) {
transparency = CLAMP(p_transparency, 0.0f, 1.0f);
RS::get_singleton()->instance_geometry_set_transparency(get_instance(), transparency);
}

float GeometryInstance3D::get_transparency() const {
return transparency;
}

void GeometryInstance3D::set_visibility_range_begin(float p_dist) {
visibility_range_begin = p_dist;
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin, (RS::VisibilityRangeFadeMode)visibility_range_fade_mode);
update_configuration_warnings();
}

Expand All @@ -164,7 +173,7 @@ float GeometryInstance3D::get_visibility_range_begin() const {

void GeometryInstance3D::set_visibility_range_end(float p_dist) {
visibility_range_end = p_dist;
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin, (RS::VisibilityRangeFadeMode)visibility_range_fade_mode);
update_configuration_warnings();
}

Expand All @@ -174,7 +183,7 @@ float GeometryInstance3D::get_visibility_range_end() const {

void GeometryInstance3D::set_visibility_range_begin_margin(float p_dist) {
visibility_range_begin_margin = p_dist;
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin, (RS::VisibilityRangeFadeMode)visibility_range_fade_mode);
}

float GeometryInstance3D::get_visibility_range_begin_margin() const {
Expand All @@ -183,13 +192,22 @@ float GeometryInstance3D::get_visibility_range_begin_margin() const {

void GeometryInstance3D::set_visibility_range_end_margin(float p_dist) {
visibility_range_end_margin = p_dist;
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin);
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin, (RS::VisibilityRangeFadeMode)visibility_range_fade_mode);
}

float GeometryInstance3D::get_visibility_range_end_margin() const {
return visibility_range_end_margin;
}

void GeometryInstance3D::set_visibility_range_fade_mode(VisibilityRangeFadeMode p_mode) {
visibility_range_fade_mode = p_mode;
RS::get_singleton()->instance_geometry_set_visibility_range(get_instance(), visibility_range_begin, visibility_range_end, visibility_range_begin_margin, visibility_range_end_margin, (RS::VisibilityRangeFadeMode)visibility_range_fade_mode);
}

GeometryInstance3D::VisibilityRangeFadeMode GeometryInstance3D::get_visibility_range_fade_mode() const {
return visibility_range_fade_mode;
}

void GeometryInstance3D::_notification(int p_what) {
}

Expand Down Expand Up @@ -375,6 +393,9 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_lod_bias", "bias"), &GeometryInstance3D::set_lod_bias);
ClassDB::bind_method(D_METHOD("get_lod_bias"), &GeometryInstance3D::get_lod_bias);

ClassDB::bind_method(D_METHOD("set_transparency", "transparency"), &GeometryInstance3D::set_transparecy);
ClassDB::bind_method(D_METHOD("get_transparency"), &GeometryInstance3D::get_transparency);

ClassDB::bind_method(D_METHOD("set_visibility_range_end_margin", "distance"), &GeometryInstance3D::set_visibility_range_end_margin);
ClassDB::bind_method(D_METHOD("get_visibility_range_end_margin"), &GeometryInstance3D::get_visibility_range_end_margin);

Expand All @@ -387,6 +408,9 @@ void GeometryInstance3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_visibility_range_begin", "distance"), &GeometryInstance3D::set_visibility_range_begin);
ClassDB::bind_method(D_METHOD("get_visibility_range_begin"), &GeometryInstance3D::get_visibility_range_begin);

ClassDB::bind_method(D_METHOD("set_visibility_range_fade_mode", "mode"), &GeometryInstance3D::set_visibility_range_fade_mode);
ClassDB::bind_method(D_METHOD("get_visibility_range_fade_mode"), &GeometryInstance3D::get_visibility_range_fade_mode);

ClassDB::bind_method(D_METHOD("set_shader_instance_uniform", "uniform", "value"), &GeometryInstance3D::set_shader_instance_uniform);
ClassDB::bind_method(D_METHOD("get_shader_instance_uniform", "uniform"), &GeometryInstance3D::get_shader_instance_uniform);

Expand All @@ -408,6 +432,7 @@ void GeometryInstance3D::_bind_methods() {

ADD_GROUP("Geometry", "");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material_override", PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_DEFERRED_SET_RESOURCE), "set_material_override", "get_material_override");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "transparency", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_transparency", "get_transparency");
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::FLOAT, "extra_cull_margin", PROPERTY_HINT_RANGE, "0,16384,0.01"), "set_extra_cull_margin", "get_extra_cull_margin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lod_bias", PROPERTY_HINT_RANGE, "0.001,128,0.001"), "set_lod_bias", "get_lod_bias");
Expand All @@ -421,7 +446,7 @@ void GeometryInstance3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_begin_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_begin_margin", "get_visibility_range_begin_margin");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end", "get_visibility_range_end");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visibility_range_end_margin", PROPERTY_HINT_RANGE, "0.0,4096.0,0.01"), "set_visibility_range_end_margin", "get_visibility_range_end_margin");

ADD_PROPERTY(PropertyInfo(Variant::INT, "visibility_range_fade_mode", PROPERTY_HINT_ENUM, "Disabled,Self,Dependencies"), "set_visibility_range_fade_mode", "get_visibility_range_fade_mode");
//ADD_SIGNAL( MethodInfo("visibility_changed"));

BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF);
Expand All @@ -438,6 +463,10 @@ void GeometryInstance3D::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_4X);
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_8X);
BIND_ENUM_CONSTANT(LIGHTMAP_SCALE_MAX);

BIND_ENUM_CONSTANT(VISIBILITY_RANGE_FADE_DISABLED);
BIND_ENUM_CONSTANT(VISIBILITY_RANGE_FADE_SELF);
BIND_ENUM_CONSTANT(VISIBILITY_RANGE_FADE_DEPENDENCIES);
}

GeometryInstance3D::GeometryInstance3D() {
Expand Down
17 changes: 14 additions & 3 deletions scene/3d/visual_instance_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ class GeometryInstance3D : public VisualInstance3D {
LIGHTMAP_SCALE_MAX,
};

enum VisibilityRangeFadeMode {
VISIBILITY_RANGE_FADE_DISABLED = RS::VISIBILITY_RANGE_FADE_DISABLED,
VISIBILITY_RANGE_FADE_SELF = RS::VISIBILITY_RANGE_FADE_SELF,
VISIBILITY_RANGE_FADE_DEPENDENCIES = RS::VISIBILITY_RANGE_FADE_DEPENDENCIES,
};

private:
ShadowCastingSetting shadow_casting_setting = SHADOW_CASTING_SETTING_ON;
Ref<Material> material_override;
Expand All @@ -109,8 +115,9 @@ class GeometryInstance3D : public VisualInstance3D {
float visibility_range_end = 0.0;
float visibility_range_begin_margin = 0.0;
float visibility_range_end_margin = 0.0;
VisibilityRangeFadeMode visibility_range_fade_mode = VISIBILITY_RANGE_FADE_DISABLED;

Vector<NodePath> visibility_range_children;
float transparency = 0.0f;

float lod_bias = 1.0;

Expand All @@ -136,6 +143,9 @@ class GeometryInstance3D : public VisualInstance3D {
void set_cast_shadows_setting(ShadowCastingSetting p_shadow_casting_setting);
ShadowCastingSetting get_cast_shadows_setting() const;

void set_transparecy(float p_transparency);
float get_transparency() const;

void set_visibility_range_begin(float p_dist);
float get_visibility_range_begin() const;

Expand All @@ -148,8 +158,8 @@ class GeometryInstance3D : public VisualInstance3D {
void set_visibility_range_end_margin(float p_dist);
float get_visibility_range_end_margin() const;

void set_visibility_range_parent(const Node *p_parent);
void clear_visibility_range_parent();
void set_visibility_range_fade_mode(VisibilityRangeFadeMode p_mode);
VisibilityRangeFadeMode get_visibility_range_fade_mode() const;

void set_material_override(const Ref<Material> &p_material);
Ref<Material> get_material_override() const;
Expand Down Expand Up @@ -181,5 +191,6 @@ class GeometryInstance3D : public VisualInstance3D {
VARIANT_ENUM_CAST(GeometryInstance3D::ShadowCastingSetting);
VARIANT_ENUM_CAST(GeometryInstance3D::LightmapScale);
VARIANT_ENUM_CAST(GeometryInstance3D::GIMode);
VARIANT_ENUM_CAST(GeometryInstance3D::VisibilityRangeFadeMode);

#endif
2 changes: 1 addition & 1 deletion scene/resources/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1086,7 +1086,7 @@ void BaseMaterial3D::_update_shader() {
code += " ALPHA = 1.0;\n";

} else if (transparency != TRANSPARENCY_DISABLED || flags[FLAG_USE_SHADOW_TO_OPACITY] || (distance_fade == DISTANCE_FADE_PIXEL_ALPHA) || proximity_fade_enabled) {
code += " ALPHA = albedo.a * albedo_tex.a;\n";
code += " ALPHA *= albedo.a * albedo_tex.a;\n";
}
if (transparency == TRANSPARENCY_ALPHA_HASH) {
code += " ALPHA_HASH_SCALE = alpha_hash_scale;\n";
Expand Down
3 changes: 3 additions & 0 deletions servers/rendering/rasterizer_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class RasterizerSceneDummy : public RendererSceneRender {
void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}

uint32_t geometry_instance_get_pair_mask() override { return 0; }
void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
Expand Down
Loading

0 comments on commit c571e4a

Please sign in to comment.