Hi, it’s me again threading uncharted waters in shaders. I know you can do (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz in a GDShader quad and render that in front of a camera, but is that the best method..?
That would work, but it sounds dumb. I know it’s significantly more efficient than calculating the position every fragment, since any sensible scene will have less vertices than fragments, especially with good culling, but still, it feels wrong…
Compositor effects, and compute shaders in general, are not really meant for rasterizing geometry. If you need the fragment coordinate in a compute shader, you’ll have to render it to a texture using a regular rasterizing shader and then pass that texture to a compute shader.
Wouldn’t a texture like that be clamped to 1.0, tho? I understand I’ll need the good old postprocessing quad technique, but wouldn’t getting there have this one catch?
Or does enabling HDR in the SubViewport allow me to output that no problem?
How do I do it without a quad..? I can’t assign a GDShader to a SubViewport to have vertex()and fragment(), so how would I compute and render that without it?
By applying it to the geometry, you mean applying to each MeshInstance3D? I was thinking to utilise the coordinates for every fragment, every frame, for a fake NaN propagation effect, which makes it rather inefficient to do anything other than a quad using depth and the view matrix.
If you can’t apply the shader directly to the geometry, you’ll have to use the depth buffer. You don’t need to render an additional texture on a quad though, to avoid the extra viewport overhead. Depth buffer data is accessible from the compositor compute shader. Simply send the inverse view/projection matrix to the shader and calculate the coordinate there.
Which is why I referenced RenderSceneData.get_view_projection() and RenderSceneBuffersRD.get_depth_layer().
What I can also do is link those to their respective documentations, tho. That is all you should need to make your own code with the desirable results.
Edit: It’s depth_layer, not depth_texture. Also added the documentation to the Compositor.
Edit 2: Also mentioned _render_callback() and linked to it as well. Also about RenderData.
I’m progressing more on this, and I’ve found 2 issues:
I can’t access an equivalent to the VIEW_MATRIX present in GDShader. RenderSceneData.get_view_projection() and RenderSceneData.get_cam_projection() return the same matrix, which seem to be equivalent to PROJECTION_MATRIX in GDShader.
I’d need 2 mat4s to be pushed, alongside the vec2 size, and that’s 138 bytes in size, when the maximum that is allowed to be passed to the compute shader is 128 bytes.
Am I dealing with an impossible shader, or can I jank this in somehow? I could pass the data for the matrices in a 4x4 grayscale texture, but not having the view matrix is a buzz kill…
The thing is, logically, it is everything you need. The thought process is complete. The problem is that due to Godot’s implementation of compute shaders, you need to jank the matrices through the memory limitation using a 4x4 single channel texture.
Other than that, all I need to figure out is how to translate the camera transform into the projection matrix I need. It’s a personal knowledge failure, a skill issue, if you will.
Hi, reporting back, this solution should work. My desk is unusable at the moment, but I’ll test it myself and update the solution comment with what I find that works.
This is the “hard” part of the solution to your problem. What’s left is just implementation detail that, given the relevant keywords from this solution post, everyone with a half of brain can google.
Let me give you a bit of a hint regarding etiquette. When a stranger on the internet solves your problem, you should mark their post as a solution as a matter of courtesy. What you shouldn’t do is go search for the implementation minutia and post that as your own solution. It’ll demotivate knowledgeable forum regulars to help you in the future.
Most of the people who ask for help here understand this intuitively, but there are few that don’t. And they go on doing precisely what you did in this thread. They get the actual hard part of the solution then they add some detail on top of it and mark their trivial intervention as an actual solution. And that intervention would hardly ever happen had they not get the answer that did the actual heavy lifting.
Ironically, what you previously posted as a solution still “didn’t work”.
As for sending matrices to the shader, here are two hints. Firstly, the inverse view matrix is simply the camera transform matrix. You can get it from the camera node or via RenderSceneData::get_cam_transform(). Secondly, for the operation you’re doing in the shader, you don’t need those two matrices separately as they are applied consecutively. Just multiply them and send a single resulting matrix to the shader.