Trouble Getting Depth with Compositor Effect

Godot Version

4.4.1

Question

I’ve been trying to display the depth texture to the screen, but it doesn’t work. I’m not really sure how. My screen is just white the entire time.

Here’s the code in GDScript getting the matrices:

var cam_tr = render_scene_data.get_cam_transform()
var view_proj = render_scene_data.get_view_projection(view)


var inv_view_mat = [
	cam_tr.basis.x.x, cam_tr.basis.x.y, cam_tr.basis.x.z, 0.0, 
	cam_tr.basis.y.x, cam_tr.basis.y.y, cam_tr.basis.y.z, 0.0, 
	cam_tr.basis.z.x, cam_tr.basis.z.y, cam_tr.basis.z.z, 0.0, 
	cam_tr.origin.x, cam_tr.origin.y, cam_tr.origin.z, 1.0, 
]

var proj_mat = [
	view_proj.x.x, view_proj.x.y, view_proj.x.z, view_proj.x.w, 
	view_proj.y.x, view_proj.y.y, view_proj.y.z, view_proj.y.w, 
	view_proj.z.x, view_proj.z.y, view_proj.z.z, view_proj.z.w, 
	view_proj.w.x, view_proj.w.y, view_proj.w.z, view_proj.w.w, 
]

var mat_buffer := PackedByteArray()
mat_buffer.append_array(PackedFloat32Array(inv_view_mat).to_byte_array())
mat_buffer.append_array(PackedFloat32Array(proj_mat).to_byte_array())

And here’s the code in the shader:

layout(rgba16f, set = 0, binding = 0) uniform image2D render_texture;
layout(set = 0, binding = 1) uniform sampler2D depth_sampler;

layout(binding = 2) uniform uniformBufferMat {
	mat4 inv_view;
	mat4 proj;
} mat;

layout(push_constant, std430) uniform Params {
	vec2 raster_size;
};


void main() {
	ivec2 pixel = ivec2(gl_GlobalInvocationID.xy);
	ivec2 size = ivec2(raster_size);
	vec2 uv = pixel / size;
	
	if (pixel.x >= size.x || pixel.y >= size.y) return;
	
	float depth = texture(depth_sampler, uv).x;
	vec3 ndc = vec3(uv * 2.0 - 1.0, depth);
	vec4 view = inverse(mat.proj) * vec4(ndc, 1.0);
	view.xyz /= view.w;
	float linear_depth = -view.z;
	
	imageStore(render_texture, pixel, vec4(vec3(fract(linear_depth)), 1.0));
}

The code sampling the depth is from the docs, but I’m not sure it carries over to compositor effects. Does this code carry over, or is there something that I’m missing?

No, it does not. Compositor effects and normal shaders are different. To get the depth texture RID you’ll need to obtain the RenderSceneBuffersRD from the RenderData object that’s passed in the CompositorEffect._render_callback() callback.

Something like:

var render_scene_buffers : RenderSceneBuffersRD = render_data.get_render_scene_buffers()
var depth_texture = render_scene_buffers.get_depth_texture()

var uniform: RDUniform = RDUniform.new()
uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE
uniform.binding = 1
uniform.add_id(depth_texture)
var uniform_set = UniformSetCacheRD.get_cache(shader, 0, [ uniform ])

# bind the uniform set

You can read more about the compositor in the documentation The Compositor — Godot Engine (stable) documentation in English

I have already done that, just slightly differently to account for using sampler2D instead of image2D. What I really meant was if the shader code side of things had to be different. (I had heard of needing to convert between color spaces? But I’m not sure on that, nor how to do it.)

Here’s the code for creating the depth buffer uniform:

# Tried both get_depth_texture() and get_depth_layer(view)
var depth_image: RID = render_scene_buffers.get_depth_texture()

var uniform := RDUniform.new()
# Using sampler instead of image.
uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_SAMPLER_WITH_TEXTURE
uniform.binding = 1
uniform.add_id(nearest_sampler)
uniform.add_id(depth_image)

# Do all the rest of the uniform/binding stuff.

And in _init():

var sampler_state := RDSamplerState.new()
sampler_state.min_filter = RenderingDevice.SAMPLER_FILTER_NEAREST
sampler_state.mag_filter = RenderingDevice.SAMPLER_FILTER_NEAREST
nearest_sampler = rd.sampler_create(sampler_state)

Oh, I see. I’m not sure either.

I’ve found this project GitHub - pink-arcana/godot-distance-field-outlines: A Godot 4.3 demo project. that have some helper functions to read the depth buffer here godot-distance-field-outlines/project/df_outline_ce/shaders/includes/scene_data_helpers.glsl at 815fe196028cfb4c5d70dcb24d17bc074cf24c46 · pink-arcana/godot-distance-field-outlines · GitHub which pretty much does the same as you do. The only thing different as far as I can tell is the matrix used.