Fluid Renderer: opaque shading mode + per-particle size – looking for API feedback

Hi @Evgeni_Popov, hi all :waving_hand:

This is my first topic so first of all want to say thanks everyone for supporting Babylon.js comunity! Hope it keeps growing and becoming more popular.

I used FluidRenderer to build a foam effect (particles poured from a bottle) for a commercial project, and ran into two small limitations that I worked around locally. I’d like to upstream them properly if there’s interest.

Playground demo: Babylon.js Playground – shows both patches applied at runtime via ShaderStore/prototype patching.

  1. Per-particle size – right now every particle in a fluid render pass uses the same global size, even when the particle system already has its own per-particle size (e.g. shrinking over lifetime). Would be nice to support that.
  2. Opaque shading mode – fluid rendering always does glassy refraction. An option for a simple opaque, lit look would open it up for foam, milk, paint, lava, etc., not just water.

Would love your thoughts on whether these fit, before I put together a PR. Will be happy to make some contribution :backhand_index_pointing_right: :backhand_index_pointing_left:

2 Likes

Sounds good to me, bear with us while @Evgeni_Popov is out, he ll be back really soon :slight_smile:

1 Like

Sure! I’d be really happy if my work proves useful) There’s more on the way :wink:

1 Like

Hi @tini2n,

Thanks for the proposal and the Playground!

Regarding per-particle size, please go ahead and create a PR. The feature should be opt-in for the fluid rendering system as a whole. Please add a static boolean—disabled by default—to enable the use of the particles’ size vertex attribute. We can finalize the property name while reviewing your PR. Reading an additional vertex attribute is not free, and custom particle buffers will need to provide a size attribute when the option is enabled. The current behavior must remain the default.

Regarding opaque shading, I don’t think we should add a dedicated opaque mode to core. The final fluid shader can already be customized through PostProcess.RegisterShaderCodeProcessing, which also supports adding and binding custom uniforms and samplers. This is more generic and can support opaque, emissive, stylized, or any other custom shading without adding specialized modes to FluidRenderingTargetRenderer.

I made an updated version of your Playground demonstrating this approach:

It retains your per-particle-size prototype patch, but implements the opaque appearance through RegisterShaderCodeProcessing("FluidRendering", ...), without requiring any core changes for the shading part.

1 Like

Hi :waving_hand:
it’s an honour to speak with you :slightly_smiling_face:
Thanks so much for the review and the guidance – really appreciate you taking the time.

Especially pointing me at RegisterShaderCodeProcessing. I wasn’t sure about that, but your comment clarifies a lot.

I’ve opened a PR for the per-particle size flag: Fluid renderer: add opt-in per-particle size support
I’ll keep an eye on the checks and fix anything needed to get it right.

1 Like

Uhu! First contribution! :partying_face:
@Evgeni_Popov thank you for guiding me)

If you have any suggestions for what I should watch next, I’d appreciate it.
Otherwise, I’ll look for something myself.

Have a nice day :slightly_smiling_face:

3 Likes

Quick update on this.

Per-particle size landed in #18863 (v9.25): BABYLON.FluidRenderingObject.UsePerParticleSizeAttribute = true, works with ParticleSystem and custom particles (a size buffer with width/height per particle).

However, while adding GPUParticleSystem support I ran into a bug that is not related to the flag: the GPU sprite quad uses centered offsets (-0.5..0.5) while the fluid shaders expect 0..1, so GPU particles come out shifted by half a particle and only a quarter of each sphere survives the discard. You can see it on the current release here: https://playground.babylonjs.com/#M9FSIH#2. Both the GPU support and the offset fix are in #18888 (in review).

One more thing I noticed but did not touch: with addParticleSystem(gpuPs, false) (no diffuse texture) GPU particles never emit, because the emission bookkeeping lives in GPUParticleSystem.render(), which the fluid object replaces with a no-op. Happy to look at it if that is wanted.

For the opaque look I went with RegisterShaderCodeProcessing as @Evgeni_Popov suggested, no core changes. Foam example with an animated brightness uniform: https://playground.babylonjs.com/#OX4D4N#0

Docs PR for all of this: Fluid renderer: document per-particle size and custom shading by tini2n · Pull Request #1619 · BabylonJS/Documentation · GitHub