Skip to content

Commit

Permalink
Fix BaseMaterial3D refracting objects located in front of the material
Browse files Browse the repository at this point in the history
Depth comparison is now used to prevent refraction from occurring
if the pixel being refracted is located in front of the object.

For pixels slightly behind the object, a `smoothstep()` curve
is used to progressively increases refraction intensity
as the distance between the object and the refraction increases.
This avoids sudden discontinuities in the refraction.

Co-authored-by: GeneralLegendary <generallegendary456@gmail.com>
  • Loading branch information
Calinou and Meccanizer committed Sep 5, 2024
1 parent b6223c0 commit 600170b
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions scene/resources/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ uniform vec4 refraction_texture_channel;
code += "uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_linear_mipmap;\n";
}

if (proximity_fade_enabled) {
if (features[FEATURE_REFRACTION] || proximity_fade_enabled) {
code += "uniform sampler2D depth_texture : hint_depth_texture, repeat_disable, filter_nearest;\n";
}

Expand Down Expand Up @@ -1627,7 +1627,14 @@ void fragment() {)";
}
code += R"(
float ref_amount = 1.0 - albedo.a * albedo_tex.a;
EMISSION += textureLod(screen_texture, ref_ofs, ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE;
float refraction_depth_tex = textureLod(depth_texture, ref_ofs, 0.0).r;
vec4 refraction_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, refraction_depth_tex, 1.0);
refraction_world_pos.xyz /= refraction_world_pos.w;
// If the depth buffer is lower then the model's Z position, use the refracted UV, otherwise use the normal screen UV.
// At low depth differences, decrease refraction intensity to avoid sudden discontinuities.
EMISSION += textureLod(screen_texture, mix(SCREEN_UV, ref_ofs, smoothstep(0.0, 1.0, VERTEX.z - refraction_world_pos.z)), ROUGHNESS * 8.0).rgb * ref_amount * EXPOSURE;
ALBEDO *= 1.0 - ref_amount;
// Force transparency on the material (required for refraction).
ALPHA = 1.0;
Expand All @@ -1649,10 +1656,10 @@ void fragment() {)";
if (proximity_fade_enabled) {
code += R"(
// Proximity Fade: Enabled
float depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r;
vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth_tex, 1.0);
world_pos.xyz /= world_pos.w;
ALPHA *= clamp(1.0 - smoothstep(world_pos.z + proximity_fade_distance, world_pos.z, VERTEX.z), 0.0, 1.0);
float proximity_depth_tex = textureLod(depth_texture, SCREEN_UV, 0.0).r;
vec4 proximity_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, proximity_depth_tex, 1.0);
proximity_world_pos.xyz /= proximity_world_pos.w;
ALPHA *= clamp(1.0 - smoothstep(proximity_world_pos.z + proximity_fade_distance, proximity_world_pos.z, VERTEX.z), 0.0, 1.0);
)";
}

Expand Down

0 comments on commit 600170b

Please sign in to comment.