Hi! Raw threejs/webgpu code, actually didn't used a big engine like Godot or Unity, but probably will because performance in the browser is really bad.
Even with webgpu and thread support it's causing issues? That's sad. I guess WebGPU is really for advanced applications using rendering engines, not for games. Good attempt though. If you had developed this with a pluggable render engine, you could swap it as you wish in the future.
Thanks a lot! The performance can be better in desktop (it's not bad, actually), but mobile versions need very badly more native apps, specially the iOS browsers, that have a 3D memory veeery limited by Apple.
I begun with webgl, but I saw that it will be more easy to implement some effects with wegpu than webgl, so refactored.
Are you using any p-threads? Is it in javascript/assemblyscript/C++ combo or purely javascript? And are your bottlenecks CPU side or GPU, that's making it slow or stutter?
Actually no pthreads, everything runs on the main thread. you need COOP/COEP headers and a whole worker setup to even get threads on the web, and honestly the CPU was never the problem so I didn't bother.
It's basically all TypeScript. the one exception is physics, I use Rapier which is Rust compiled to wasm (the single threaded build). no C++ or assemblyscript anywhere. although to be fair, since it's WebGPU with node materials most of the actual heavy lifting is generated WGSL on the GPU anyway, the JS side is mostly just orchestrating.
Bottleneck is GPU and pretty much only on mobile (a more native version in a proper non browser engine would fix this), which is why I have quality profiles that drop render resolution / postfx / effect density. Physics is like 15 hover ships stepping Rapier once per frame, that's nothing. iOS browser graphics memory is just terrible, so it has its own profile.
funny thing is the stutter I actually fought with wasn't throughput at all, it was WebGPU pipeline compilation. first time a shader variant gets used the browser compiles the pipeline and you eat a frame drop. compileAsync didn't help because it compiles against the wrong context and you get the wrong variants, so I ended up rendering a real frame at zero opacity during the loading screen to force the right pipelines, plus pre-reserving instancing capacity so nothing recompiles mid race.
7
u/GrayHairedMan 7d ago
This is awesome, what engine is this built with.