Search Unity

Applying CPU physics to GPU vertex data?

Discussion in 'Shaders' started by TheCelt, Sep 15, 2019.

  1. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    742
    Hello

    I have implemented a fourier algorithm to my mesh which displaces vertices in a shader. This algorithm is too expensive to run CPU side. It is used to simulate water waves.

    But i need to do buoyancy physics which is CPU side.

    What is the correct way to grab vertex height data from vertex shader's manipulations for my physics scripts to use ?

    I've seen plenty people use buoyancy physics for water waves but have no idea how they got the vertex data back. I don't want the fragment data back since that is just a colour - i need the height data from the vertex shader specifically.

    How should i go about this?

    Thanks.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The correct way to do it is to not do this. Do the calculations on the CPU.

    The trick is the CPU side simulation only needs to do the FFT at a few discrete points where your CPU side objects are.
     
  3. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    742
    Thats not an option because the Fourier transform is based on total vertices and resolution. So if you calculate an FFT with a lower total vertex count than on the shader you get a different result for the waves. :(
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Isn't the whole "trick" of FFT is you're pre-computing the expensive parts then using texture lookups to sample the intended position of a vertex?

    You need a copy of that pre-computed data on the CPU.
     
  5. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    742
    The precomputed data is an optimisation but is only the non time dependant data, but the algorithm still runs every frame on delta time as O(nlog(n)) and uses that precomputed data to save performance, since water waves are animated unlike the use of terrain generation you can't really precompute the wave heights. Typically n=512. On the CPU it can just about achieve n=128. But 128 is not near enough for water visuals to look right.

    The CPU side can't generate sufficient wave height quality for water that would run optimally every frame. So i have to do it GPU side.
     
  6. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    505
    Usually most of FFT for water used XYZ coordinates (Height map and displacement), so he cannot get coorect discrete point :(
    And need to do a search a nearest correct point.
    Only way in this case it's todo a heightmap from xyz fft map. Maybe there are more ways?
     
  7. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    742
    Yes this is the problem, i would have to get the displacement map from shader back to CPU every time but its not really going to make sense.
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    I mean, you could render to a low resolution height map and use an async read back, but the time that takes isn’t necessarily known. Could be within the frame if you run it early enough and check in late update, could be the next frame, could be in a couple of frames.

    You could pass a handful of points to the GPU and use a compute shader to find the heights (either from a rendered height map, or searching through the mesh data) and pass back only those. That could be read back relatively quickly in comparison to the full height map.

    But literally ever project I’ve ever seen attack this (not running on a console) solves it by doing the calculations on the CPU in parallel.
     
  9. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    742
    Hm i see, i wonder how they are getting such higher resolution. I can't get above n = 128 and i'm already using threading for it =/