SceneDepth VisualShaderNode 4.4

Visual shader node that retrieves the pixel depth buffer from Godot. Equivalent of UE’s SceneDepth node. Captured in the texture is the depth of the opaque objects; translucency is not written to depth buffer

Use raw depth if you just want world units, ranged depth returns a clamped (0-1) depth gradient whose min / max distance values are defined by the input pins.

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

Shader code
@tool
class_name VSNode_SceneDepth
extends VisualShaderNodeCustom

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

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

func _get_description() -> String:
	return "Returns the scene depth buffer with raw depth and ranged depth outputs"

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

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

func _get_input_port_name(port: int) -> String:
	match port:
		0: return "Min Distance"
		1: return "Max Distance"
	return ""

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

func _get_input_port_default_value(port: int) -> Variant:
	match port:
		0: return 0.0  # Default min distance
		1: return 100.0  # Default max distance
	return 0.0

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

func _get_output_port_name(port: int) -> String:
	match port:
		0: return "Raw Depth"
		1: return "Ranged Depth"
	return ""

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
		vec4 view = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
		view.xyz /= view.w;
		float linear_depth = -view.z;
		
		// Output raw depth
		{raw_output} = linear_depth;
		
		// Calculate ranged depth (normalized between min and max)
		float min_dist = {min_input};
		float max_dist = {max_input};
		float ranged_depth = clamp((linear_depth - min_dist) / (max_dist - min_dist), 0.0, 1.0);
		{ranged_output} = ranged_depth;
	}}
	"""

	return code_template.format({
		"min_input": input_vars[0] if input_vars[0] != "" else "0.0",
		"max_input": input_vars[1] if input_vars[1] != "" else "100.0",
		"raw_output": output_vars[0],
		"ranged_output": output_vars[1]
	})

func _is_available(mode: Shader.Mode, type: VisualShader.Type) -> bool:
	return mode == Shader.MODE_SPATIAL && type == VisualShader.TYPE_FRAGMENT
Live Preview
Tags
3d, godot 4, Godot 4.0, LKS, 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

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Purpbatboi2i
3 months ago

Seems to be broken in 4.5 compatibility