DepthIntersectionMask VisualShaderNode 4.4

A shader node that creates a depth intersection mask. Useful for hiding geometry intersections, like for fog cards clipping through geometry and such. Contains an ifdef for compatibility pulled from the GD docs, but I have not tested it in compatibility mode.

To install: copypaste this code into a .gd file. The node will show up under Addons/Utility

Shader code
@tool
class_name VSNode_DepthIntersectionMask
extends VisualShaderNodeCustom

###################
## Base Props
###################
func _get_name() -> String:
	return "DepthIntersectionMask"

func _get_category() -> String:
	return "Utility"

func _get_description() -> String:
	return "Creates a mask based on depth intersection with scene geometry"

func _get_return_icon_type() -> PortType:
	return VisualShaderNode.PORT_TYPE_SCALAR

#################
## Input props
#################
func _get_input_port_count() -> int:
	return 1

func _get_input_port_name(port: int) -> String:
	return "Distance"

func _get_input_port_type(port: int) -> PortType:
	return VisualShaderNode.PORT_TYPE_SCALAR

func _get_input_port_default_value(port: int) -> Variant:
	return 1.0  # Default intersection distance

#################
## Output props
#################
func _get_output_port_count() -> int:
	return 1

func _get_output_port_name(port: int) -> String:
	return "Mask"

func _get_output_port_type(port: int) -> PortType:
	return VisualShaderNode.PORT_TYPE_SCALAR

#################
## Global code
#################
func _get_global_code(mode: Shader.Mode) -> String:
	return """
uniform sampler2D depth_texture : hint_depth_texture, filter_nearest;
"""

#################
## Main shader code
#################
func _get_code(input_vars: Array[String], output_vars: Array[String],
		mode: Shader.Mode, type: VisualShader.Type) -> String:
	
	var code_template = """
	{{
		// Sample the depth texture
		float depth = texture(depth_texture, SCREEN_UV).x;
		
		// Convert to normalized device coordinates based on renderer
		vec3 ndc;
		#if CURRENT_RENDERER == RENDERER_COMPATIBILITY
			ndc = vec3(SCREEN_UV, depth) * 2.0 - 1.0;
		#else
			ndc = vec3(SCREEN_UV * 2.0 - 1.0, depth);
		#endif
		
		// Convert to view space to get linear depth
		vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
		view.xyz /= view.w;
		float scene_linear_depth = -view.z;
		
		// Get current fragment depth in view space
		float fragment_depth = -VERTEX.z;
		
		// Calculate depth difference 
		float depth_diff = abs(scene_linear_depth - fragment_depth);
		
		// Create mask based on intersection distance (inverted by default)
		float intersection_distance = {distance_input};
		float mask = 1.0 - clamp(depth_diff / intersection_distance, 0.0, 1.0);
		
		{mask_output} = mask;
	}}
	"""

	return code_template.format({
		"distance_input": input_vars[0] if input_vars[0] != "" else "1.0",
		"mask_output": output_vars[0]
	})

func _is_available(mode: Shader.Mode, type: VisualShader.Type) -> bool:
	return mode == Shader.MODE_SPATIAL && type == VisualShader.TYPE_FRAGMENT
Live Preview
Tags
3d, fx, godot 4, Godot 4.0, LKS, mask, pbr
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from wendallhitherd

Related shaders

guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
CornFarmer
CornFarmer
4 months ago

works very well