Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Skinning in Vertex Shader vs Compute Shader?

Discussion in 'Shaders' started by VictorKs, Jan 27, 2023.

  1. VictorKs

    VictorKs

    Joined:
    Jun 2, 2013
    Posts:
    242
    Which would be more efficient: character skinning directly in the Vertex shaders and streaming out the skinned data for reuse in shadows or just using a Compute Shader?

    I believe Compute shader path to be faster since its newer than Stream-Out but since I will be drawing hundreds of skinned characters together using instancing I guess I will need an extra buffer to store the skinned vertices for each instance. Is there a smarter way?
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Compute is more ideal since you're not invoking the whole raster pipeline just to update a buffer. And makes it much easier if you want to add other shader passes since the data will simply exist already in its modified form.

    You can access the Mesh's vertex buffers directly on the GPU, so you don't need to double-buffer it.

    https://github.com/Unity-Technologies/MeshApiExamples

    Just modify the mesh buffer directly and now the meshes will automatically be rendering with those updated values.
     
    VictorKs likes this.
  3. VictorKs

    VictorKs

    Joined:
    Jun 2, 2013
    Posts:
    242
    Hmmm I know I can modify the vertex Buffers directly, but won't there be some problems over time due to precision issues? Otherwise you're right it will be faster to just dispatch a compute shader and directly modify. Btw after studying more I realize that stream-out is a somewhat obsolete method after DX11 Compute shaders and RWBuffers. So I guess I won't be using it
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    If you're continuously changing the shape there could be some divergence in shape overtime yes, in which case you would want to either double buffer it, or simply store the original vertex positions into an unused UV channel (or vertex colors) which your compute shader can then use as the starting point each time you modify.
     
    Last edited: Feb 23, 2023
    VictorKs likes this.
  5. VictorKs

    VictorKs

    Joined:
    Jun 2, 2013
    Posts:
    242
    That is a good idea never thought of storing in the UVs, but since I need to store Normals and Tangents too I am thinking of storing them in a separate buffer, mesh data don't take that much memory anyway and I don't have that many characters.
     
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Well, you do have 8 UV channels of which you're likely only using 1 or 2 for character stuff :p

    But yeah whichever you feel like!
     
  7. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Unity's SkinnedMeshRenderer uses separate streams, and then only binds the relevant ones, to improve vertex cache usage. A skinned mesh has essentially 5 buffers of vertex data...

    A: Original vertex position/normal/tangent
    B: Transformed position/normal/tangent
    C: Previous frame position/normal/tangent (for motion vectors and stuff)
    D: Bone weights and indices
    E: UVs (and vertex colors if it needs them)

    Then it binds what it needs for each pass. So A and D are only bound for the skinning stage and not used during rendering.
     
  8. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,495
    Oh right I completely blanked they said character... in which case yeah just use Unity's own pre-skinning buffer haha