How to identify the viewport a compositor effect is rendering to?

Godot Version

4.7.1.stable

Question

Did I really just step into a limitation of the godot engine?
I’m trying to make a compositor effect that uses more than one camera, where the second one follows the main one with a different layer mask, for masking purposes. I want it to work in the editor when the viewport is split into multiple smaller viewports, but I’m failing to get a way to determine which auxiliary camera is tied to which viewport texture inside the _render_callback() function.

I’m assuming the viewport can only be split 4 ways, as that’s what in the documentation. This is what I’ve tried:

# In compositor_effect.gd
func _render_callback(_effect_callback_type: int, render_data: RenderData) -> void:
	if ShaderGlobals.aux_viewports.size() > 0:
		var scene_buffers: RenderSceneBuffersRD = render_data.get_render_scene_buffers()
		for view in scene_buffers.get_view_count():
			for index in range(4):
				var view_texture: RID = RenderingServer.viewport_get_texture(ShaderGlobals.tree.root.get_viewport_rid())
				if view_texture == scene_buffers.get_texture("", ""):
					print("Found!")

and

func _render_callback(_effect_callback_type: int, render_data: RenderData) -> void:
	if ShaderGlobals.aux_viewports.size() > 0:
		var scene_buffers: RenderSceneBuffersRD = render_data.get_render_scene_buffers()
		for view in scene_buffers.get_view_count():
			for index in range(4):
				var view_texture: RID = RenderingServer.texture_2d_get(RenderingServer.viewport_get_texture(ShaderGlobals.tree.root.get_viewport_rid()))
				if view_texture == scene_buffers.get_color_layer(view):
					print("Found!")

The print("Found!") line never triggers, because either the scene_buffers.get_texture() doesn’t work like that (I know it doesn’t, but no idea on how it actually works, it’s not documented), or the color_buffer isn’t a texture, of which I’m aware, but what else can I try?

Is that just not possible in Godot 4.7?

Blasphemy! Of course it’s possible :smiley:

  • iterate through all 4 editor viewports you get from EditorInterface::get_editor_viewport_3d()
  • for each viewport:
    – get its rid by calling get_viewport_rid() on it
    – pass that rid to RenderingServer::viewport_get_render_target() to get its render target rid
    – compare that rid to render target rid gotten from render_data you received in _render_callback()

Code:

@tool
class_name Effect extends CompositorEffect

func _render_callback(effect_callback_type, render_data):
	var render_target: RID = render_data.get_render_scene_buffers().get_render_target()
	for i in 4:
		var vp: SubViewport = EditorInterface.get_editor_viewport_3d(i)
		var vp_rid: RID = vp.get_viewport_rid()
		var vp_render_target_rid: RID = RenderingServer.viewport_get_render_target(vp_rid)
		if vp_render_target_rid == render_target:
			print("Now rendering viewport: ", vp)

It worked, but I’ll open another topic, I’m getting some weird errors with the whole project that is only sorta related to this topic, but not really.