JMS55's Avatar

JMS55

@jms5517.bsky.social

Working on rendering for the Bevy game engine. Long form blog at https://jms55.github.io.

302 Followers  |  28 Following  |  180 Posts  |  Joined: 19.12.2024
Posts Following

Posts by JMS55 (@jms5517.bsky.social)

Video thumbnail

Real-time Rendering with a Neural Irradiance Volume
Delivering fast inference (~1ms/frame), a tiny memory footprint (1-5MB), 10x quality gains over probe-based methods @ equivalent mem budgets, bringing neural rendering within reach of consumer hardware without RT or denoising.
arnocoomans.be/eg2026

27.02.2026 09:32 β€” πŸ‘ 56    πŸ” 15    πŸ’¬ 3    πŸ“Œ 0
Preview
Investigation: Bindless resources Β· Issue #380 Β· gpuweb/gpuweb Currently, in WebGPU, if a draw/dispatch call wants to use a resource, that resource must be part of a pre-baked "bind group" and then associated with the draw call inside the current render/comput...

See the sub-issues here github.com/gpuweb/gpuwe...

27.02.2026 03:14 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

It's being worked on! Details are still being shaked out.

Prerequisites have starting landing in the spec and in dawn (Chrome). E.g. latest Chrome release now supports textures and samplers in let bindings (variables).

Some type of buffer reinterpreting scheme is also being debated.

27.02.2026 03:13 β€” πŸ‘ 0    πŸ” 1    πŸ’¬ 2    πŸ“Œ 0

So... back to the drawing board? Maybe copying what Doom DA did and cluster lights in world-space rather than any sort of RIS-based scheme.

26.02.2026 04:20 β€” πŸ‘ 4    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

No matter what your RIS output is, you have to write it back to the cache. You can't conditionally do that and stay correct.

So scrapping that and trying to think of other schemes, I'm basically just reinventing ReGIR (except I don't want to do ReGIR since it requires many visibility tests).

26.02.2026 04:18 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Update on bsky.app/profile/jms5...:

Turns out my code was bugged, and I never actually wrote to the cache...

Fixing that reveals that the whole scheme was wrong anyways - conditionally replacing cache cells with RIS outputs does not give an unbiased/correct output.

26.02.2026 04:16 β€” πŸ‘ 12    πŸ” 1    πŸ’¬ 1    πŸ“Œ 0

Only thing I'd be worried about is making shader writing _too_ accessible - I don't want people making a million pipeline variations instead of 20 uber-ish shaders.

25.02.2026 01:51 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Thank you - this is very interesting!

I know our users would love if we did this with Rust, so that people don't have to learn WGSL :P

But the basic idea of a general shader skeleton, and then allow users to compose pieces to modify inputs/outputs between stages of the skeleton seems good.

25.02.2026 01:50 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Anyone have examples of Material APIs they like in an engine, or links to good talks on this topic?

Right now Bevy materials let you reuse host code (texture/buffer bindings), but customizing the default material is essentially "go to github and copy paste the entire shader". Not very modular.

24.02.2026 03:40 β€” πŸ‘ 8    πŸ” 2    πŸ’¬ 1    πŸ“Œ 0
Post image

πŸš€ Unleash your creativity with GPU Zen 4!

πŸ“– Dive into cutting-edge techniques from industry experts to tackle complex graphics challenges and elevate your projects.

Available now on Amazon!
πŸ“” Standard Edition: a.co/d/0cvhJuSU
⭐️ Deluxe Edition: a.co/d/07t0MZGz

#GPUZen #GameDev

19.02.2026 23:02 β€” πŸ‘ 22    πŸ” 9    πŸ’¬ 0    πŸ“Œ 0
Preview
bevy/crates/bevy_solari/src/realtime/world_cache_update.wgsl at solari6-light-sampling-wc Β· JMS55/bevy A refreshingly simple data-driven game engine built in Rust - JMS55/bevy

Btw code (minus visibility weighing and alias table building) is open source if you want to try improving it github.com/JMS55/bevy/b...

19.02.2026 02:37 β€” πŸ‘ 4    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

Maybe cache the result of the 32 sample RIS in the cell and use that, so we're not doing the expensive RIS per-pixel?

Message me if you have ideas!

19.02.2026 02:35 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
ReGIR - An advanced implementation for many-lights offline rendering | Tom Clabault Tom Clabault's website

For GI, I don't really have a good idea of where to go next. Perhaps just ReGIR after all? I know Tom Clabault got good results tomclabault.github.io/blog/2025/re..., but it's fairly expensive.

19.02.2026 02:34 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

For ReSTIR DI, I next want to try feeding the traditional froxel-based light clustering into the initial RIS. Could help with many-lights.

19.02.2026 02:33 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

So yeah, total bust. I was hoping to get a good sampling distribution I could feed into ReSTIR DI, and switch the irradiance caching part of the world cache to not store DI, and do NEE per-pixel for GI instead of immediately terminating in the cache - which would massively prevent light leaks.

19.02.2026 02:30 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Post image Post image

Final result... the cache (left) has higher variance than just brute-force 32-sample RIS (right). Complete failure :/

19.02.2026 02:27 β€” πŸ‘ 4    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

5a. If in cache, update weight and estimated visibility
5b. If not in cache, is visible, and contribution larger than one of the 8 lights already in the cache, replace it
6. Generate an alias table of the 8 lights and their final weights to accelerate per-pixel sampling in the rest of the renderer

19.02.2026 02:25 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

1. Do RIS over 8 random lights
2. Separately, do RIS over the up to 8 cached lights
3. Combine the reservoirs of 1. and 2., capping the random reservoir's weight to 25% of the other reservoir's weight
4. Test visibility of the final sample

19.02.2026 02:22 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

With just a few lights, it's not a big deal. With 441 lights like this scene, pure random sampling becomes more of a problem.

My idea is that I would extend my existing spatial world cache structure to also store the 8 best lights it has found so far, in addition to cached irradiance (DI+GI).

19.02.2026 02:19 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Several different parts of Solari (realtime pathtracing) need to sample direct lighting:
* Diffuse GI (which is already cached in world space)
* Specular GI pathtracing (when it can't terminate in the world cache)
* Per-pixel ReSTIR direct light would like a better initial distribution than random

19.02.2026 02:15 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Post image

🧡 I've been experimenting with caching the best lights in world space to improve NEE sampling. Inspired by ReGIR, MegaLights, and www.yiningkarlli.com/projects/cac....

19.02.2026 02:13 β€” πŸ‘ 47    πŸ” 7    πŸ’¬ 1    πŸ“Œ 1

Thank you, kram looks pretty good! I think it's only missing BC6H, but I can add a second library to handle one format, I don't mind that too much.

Agreed on there not really being a great all in one option.

11.02.2026 03:30 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
Preview
Improve CompressedImageSaver Β· Issue #14671 Β· bevyengine/bevy It's time to get serious about texture speed :). Streaming mips can come later, first we need a better system that actually compresses textures (on disk). Old plan (ignore everything under this) Th...

For the Bevy game engine, I've been evaluating different options, and there doesn't seem to be one single tool that can support every platform/SDR + HDR/supercompression/etc. github.com/bevyengine/b...

Do you have any suggestions for what would be good to use?

10.02.2026 03:39 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Really cool to see that AVIF and runtime GPU compression work so well!

Spark is not freely available though, right? (which is totally understandable - it's a ton of work!)

10.02.2026 03:38 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
An Updated Sponza glTF – Ignacio CastaΓ±o

I've put together an updated version of the Sponza scene with uncompressed PNG and compressed AVIF textures. I wrote about the process and compared the results against KTX.

www.ludicon.com/castano/blog...

#webgpu #web3d #sparkjs

10.02.2026 00:29 β€” πŸ‘ 13    πŸ” 2    πŸ’¬ 3    πŸ“Œ 1
Preview
Nanite Tessellation Nanite Tessellation, aka Nanite Dynamic Tessellation, aka Nanite Dynamic Displacement was the next major feature I worked on after Nanite it...

I'm finally writing up how Nanite Tessellation works. The first few blogs posts are up. More will be coming.
graphicrants.blogspot.com/2026/02/nani...

02.02.2026 02:40 β€” πŸ‘ 160    πŸ” 51    πŸ’¬ 1    πŸ“Œ 1
Preview
raytracing

If you're interested in taking things further, I have an open source WGSL PT that uses HW RT as part of the Bevy game engine, and I think your experience would be super valuable. Feel to reach out if you want to chat!

jms55.github.io/tags/raytrac...

30.01.2026 03:03 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

Awesome job! I always love seeing more people experimenting with realtime pathtracing.

30.01.2026 03:03 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Video thumbnail

New post on how to do real-time diffuse global illumination using surfels and #WebGPU: juretriglav.si/surfel-based... #threejs

29.01.2026 12:22 β€” πŸ‘ 164    πŸ” 30    πŸ’¬ 1    πŸ“Œ 2

That's normal - that's just how ReSTIR works.

I compared to Blender, and I think my realtime version is actually more correct, and that my pathtracer is somehow broken...

20.01.2026 23:56 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0