How to dump world space coordinates into a render target / texture / SubViewport

Godot Version



What is the right way in Godot to set up a camera that renders world space coordinates to a texture?

I have two cameras. I want camera A to render a world using shader A to a SubViewport. Shader A should output the world space coordinates of the fragment.

Then, in shader B, I want camera B to read from the SubViewport in order to get the world space coordinates of each fragment rendered by camera A.

I have a problem with getting shader A to work properly. Here it is so far:

shader_type spatial;
render_mode unshaded; //don't light the scene, just render a colour
void fragment() { 
  ALBEDO = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz; //get view space vertex and multiply back to world space

I have this shader assigned as the surface material override of a quad mesh instance which is the child of camera A. In the inspector, there is a preview for the surface material override, and there the shader appears as expected: there is a different saturated colour in each of the four screenspace corners.

Q1: when I add camera A as a child of a SubViewport, there are no saturated colours. The entire scene is in grayscale - objects can be distinguished from one another (maybe the scene is somehow lit despite the shader using the unshaded render mode?), but every object is rendered completely flat.

Q2: I believe SubViewports automatically do some kind of tonemapping or gamma correction or something by default. If this is the case, how do I turn it completely off? This texture effectively contains data, rather than an image, so it really should be treated as such.

Q3: I can’t find the setting to change the SubViewport’s framebuffer format. To store world space coordinates in a texture, I think it would be simplest for me to just use a ridiculously huge framebuffer format, something with three 32-bit channels. Is that an option?