Where (if anywhere) is data stored when setting values through a Shader?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By toblin

I’m trying to use Shaders for general purpose programming. As such, I want to give a bunch of 3D positions (vertices) to the shader, run the shader code once, and then have it save the output for example through the COLOR variable. The output I want to be able to access through GDScript.

Where do I find the output data once the Shader has run? I’m thinking it should be somewhere e.g. in the ShaderMaterial, in the Texture, or somewhere similar.

I’m also guessing that it could be that the Shader outputs are not stored anywhere, but simply used for continuously executing the same script based on the same input. I doubt this to be the case though, as it runs contrary to how I think Shaders operate. But it wouldn’t be the first time I was wrong…

:bust_in_silhouette: Reply From: Tim Martin

Don’t think you can do this with Godot I’m afraid. You may need to look into other software environments.

The (interpolated) per-vertex COLOR variable is supplied to the per-pixel fragment shader.

But there are always going to be numerous outputs: the final colour of each pixel drawn to the screen is an output of the shader. There is no functionality in Godot to recombine the result of each concurrent per-pixel calculation to give a single value.

This is why people typically debug shaders by using vivid colours to try and understand what is going on.

Talking to people on the Godot channel has lead me to believe that one can provide a uniform texture input to the Shader where data can be stored and read afterwards. This would not be efficient if done every frame, but given my use case it should probably speed things up.

What is your opinion on this method?

toblin | 2020-09-09 07:03

Right, I’m not aware of a mechanism to do this via a uniform. The docs explicitly say that “Uniforms can’t be written from within the shader.”

But you could setup a Viewport of know size. Render onto a rectangle which fills the viewport, grab the image data from the viewport, then loop over the pixels in the image to read the result of the shader code.

That would technically work, and could be an OK workaround if you didn’t need to do it very often.

Set the Viewport to UPDATE_ONCE before each read of the image.

This is similar to the first part of the Using a Viewport as a texture — Godot Engine (stable) documentation in English example.

Tim Martin | 2020-09-09 12:24