GPGPU Birds example - Using half float to store position

Hello everyone, over the past few days I’ve been writting a gpu particle system, and hit a common problem regarding precision and device support. My system uses textures to store positions, and on each frame I would update that texture with new positions based on velocity or whatnot, but it seems that IOS only supports HalfFloat texture types. Now, for storing positions I started to have precision issues, as expected, and tried a few things like mapping an area in the range [-20…20] to [0…1] to pack and unpack the position before updating it, but I kept having problems regardless of the amount of tricks I tried to use to improve the precision.

So, I decided to take a look at the gpu birds example, and they also seem to be storing the position in a half float texture for the ios case, but I wonder how they got around the precisions issue since the birds seem to be moving over a large area. I didn’t look carefully line by line at what the code is doing, because maybe someone here already has come up with a problem like mine.

So, in a nutshell, how do you deal with having to store positions (and updating them) on a half float render target?

Cheers

I’ve run into this problem before. You can see a solution I had to use here: GPGPUComputationRenderer

Plus, here’s a longer discussion @jagracar and I had about that in this thread: Problem with GPU computation on mobile devices maybe it can provide some answers!

2 Likes

thanks @marquizzo ! unfortunately I coulnd’t find a solution there. My problems arise not from sending data from the cpu>gpu, but from updating values on the gpu by ping-pong’ing textures.

On each frame I’m adding a 0.01 value to the position’s Y coordinate to move slowly the particles up. Over the first…say, 4 or 5 units it works as expected, but then it starts to reduce its speed until it halts at around a Y value of 20-30. If I use a bigger value like 0.1 then it keeps going without halting (though I guess it will halt eventually).

Hmm… do you have a working example of this? Maybe you could post one to https://jsfiddle.net/ so it can be easily compared between desktop and mobile.

yeah I was thinking about making a working example. Right now the code is buried inside a framework built on top of threejs, but I will try to make a clean version of this so everyone can try it

@marquizzo Sorry for the delay, here is the jsfiddle:

https://jsfiddle.net/ramiro_fages/te8Lj2k4/2/

Sorry for the messy code, I just tried to cut a lot of the generic and reusable code to make the snippet shorter and easier to follow.

In the example you will see a red cube and a green cube. They both move at the same speed, but after a few seconds you will notice that the red cube will start to slow down. The red cube is moved by the gpu reading from a RT that gets updated with a new position each frame. If you go to line 74 and change the texture type from HalfFloatType to FloatType you will see that now they both will go at the same speed.

This, for me, is a precision issue that I wasn’t able to solve yet. I would be happy with having a space of 20-30 units to work with, but none of my compression tricks worked so far.

Hi! As @marquizzo mentioned, this seems to be the same problem that I have with some of my simulation examples. I also update the position and velocities in the GPU and the problem seems to be related with the render target type. The following example should work in desktops (where the used type is FloatType) and produces weird results on some mobiles (that use HalfFloatType):

https://webgl-shaders.com/debug-example.html

I spent some days trying to solve the problem with no luck and I decided to give up. You can see more examples in this page under the “Simulation examples” section:

https://webgl-shaders.com/

Some of them work well on mobiles, and some don’t :disappointed: