Godot Version
4.7
Question
I apologize as this one’s a bit of a doozy but I’ve been scratching my head for about a week now. For my project I’m looking to implement a screen space fluid effect as described here: https://developer.download.nvidia.com/presentations/2010/gdc/Direct3D_Effects.pdf. For this effect to work, I need a pair of dedicated framebuffers that contain the depth of the fluid particles and an additively blending thickness value (attached are examples of the sort of buffers I want to make). My question is how should I go about actually making these dedicated framebuffers and drawing to them? There are two approaches I’ve thought of but both feel really hacky and I’m really not sure how I should move forward.
Examples of what I’m trying to make:
SubViewports
I can have a camera in here that only draws the fluid particles and nothing else. I can render the particles using a custom material that writes the depth to the albedo, and then I can sample this output texture to later composite the final effect. Problem is I’d have to duplicate all the particle geometry with a different material in another SubViewport in order to do the additive blending for the thickness which feels super wasteful. This doesn’t really feel like two passes and more just like a workaround of carrying duplicate instances that are drawn differently. Another big problem with this is that it doesn’t play nice with other Subviewports I have for other effects (like a mirror) as the cameras drawing the fluid buffers can only be synced to one camera at a time (player cam or the mirror cam) meaning to actually get reflections I’d have to have duplicates of both the depth and thickness SubViewports for each possible render target which just seems like a nightmare of design and performance.
RenderingDevice API
I could explicitly bind my own framebuffers and build my own custom pipelines with the RenderingDevice API and draw the particles to the exact sort of F32 textures I need directly without the overhead of the SubViewports. The problem here is that I’m not entirely sure exactly how I should go about injecting these custom pipelines. Could I do this in a POST_OPAQUE compositor effect? I know the compositor is intended for full screenspace postprocesses but I’d be drawing geometry here, is that okay? The other big worry I have is that I’d essentially be skipping right over Godot’s normal rendering entirely for these meaning I’d be losing all the frustum and occlusion culling benefits and I’d have to manage that myself. Is there some kind of way I could get a list of like potentially visible instances from Godot before submitting my drawlist or would I have to reimplement these systems from scratch? I know what I’m trying to do is really fighting Godot’s typical rendering pipeline and might not be possible to do cleanly.
If there’s anybody that has ever tried doing something similar or knows of someone / a project that has tackled this sort of thing I’d really appreciate any pointers or ideas. I’m scared to dive into setting up a bunch of explicit Vulkan pipeline management just to find out after that what I’m doing is going to badly break something or invalidate some internal assumption the engine makes about when rendering code is run. If there are any rendering gurus or people who really know the renderer internals I’d really appreciate any help. Thanks!


