Use hand motion to influence particle motion We upload the hand motion (position and velocity) and use it to move particles. The area of influence is based on the velocity of the hands: faster moving hands affect a wider area, slower affect a smaller area. This is intended to simulate the wake of the hand in a fluid, and has the bonus effect that when your hands aren't moving they don't affect many particles. The particles are accelerated by mixing their velocity with the hand's velocity, with the weight for that depending on the distance and the velocity of the hand. Using mixing instead of direct accelerating prevents you from accelerating particles faster than your hands move, which simulates the feeling of them being pulled along in a current in the fluid.
Implement compute-shader simulation of particles! This uses a workaround for the previously mentioned shader glitch in order to use the compute shaders successfully. Bjorn notes that reading from an SSBO makes rendering start working properly. In order to *hopefully* make this cheaper, I add a variable to the buffer that's intended for only reading like this, which ends up being sufficient to fix the behavior of the whole buffer. The discussion comment with the workaround: https://github.com/bjornbytes/lovr/issues/211#issuecomment-580985010 > Reading data out of the buffer (print(block:read('value')[1])) after > the compute also fixes it, I suspect maybe because it maps the buffer. For simulation, this updates the positions with the velocity, and applies uniform quadratic drag to the particles.
Add basic compute simulation (disabled) We want to use a compute shader to update the particle states. Unfortunately, they don't want to be updated. If you uncomment the line that runs the compute shader, all the particles turn into a glitchy mess. Committing this code for reproducability's sake.
Add velocities and padding to the particle data For now I'm using 2 vec4 of padding because LÖVR's ShaderBlock API doesn't know about struct types or non-square matrices, and I need a type which can hold 2 vec4, so I just pretend I'm sending a mat4 and receive it as a struct of 4 vec4 on the shader side.
Render lots of particles with SSBOs! We generate particle batch meshes with a fixed chunk of quads at the origin, and then dispatch instances of that batch. The vertex shader fetches from a shader storage buffer of particle info by using the instance ID (between batches) and the vertex ID (within batches), using the batch size. We need to run these in batches because GPUs process instances somewhat serially, so if you have a tiny instance you're wasting a bunch of spare compute instead of running nicely in parallel. Having smaller instances than the full particle size helps with avoiding rendering lots of hidden particles if you're using dynamic particle counts, and also gives smaller data uploads (although that's not particularly significant, since they're static buffers of geometry). The shaders do billboarding based on head position rather than the projection matrices so they don't visibly move when you rotate your head: projection-based billboards look really bad in VR it turns out.
Initial commit, stymied by LÖVR bugs This adds a main test program and a simple (currently broken) sprite billboarding shader. It doesn't have much going on, because I'm running into a LÖVR bug with sending compute ShaderBlock data on Oculus Quest.