Search Unity

Visualize skining weights with a shader

Discussion in 'Shaders' started by Dzhange, Jul 19, 2020.

  1. Dzhange

    Dzhange

    Joined:
    Jan 19, 2019
    Posts:
    5
    Hi guys,

    I'm new to unity shader and not really knowing if it is possible to do so.
    Here is my question: I have a skinned mesh in unity, and I would like to visualize the skinning weights from each bone for each pixel, with a grayscale image. For example, if the skinned mesh has 8 bones, it would output 8 different grayscale images, each corresponds to a bone, and the value of each pixel represents the skinned weights.

    I really don't know if this could be accomplished with the shader(and how to implement that), could anyone give me some sketch?
    If this is not possible or extremely hard, are there any alternatives?

    Thanks!
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    So you want to see a square texturemap for each bone? Or, more simply, would you just like to visualize the weighting as colors on the actual mesh surface...

    The main issue regardless is that with GPU skinning enabled, Unity is simply using a vertex shader to transform the mesh data and then renders that transformed mesh structure with your material, so the vertex weights aren't seen by your shader. I believe there are some custom GPU skinning assets you could take knowledge from to manually submit and interact with the skinning data instead, otherwise your option is to do that on CPU side or submit the weighting data to a compute shader to generate textures to view.
     
    Last edited: Jul 20, 2020
  3. Dzhange

    Dzhange

    Joined:
    Jan 19, 2019
    Posts:
    5
    Thanks for your reply! Actually I'm considering generating a dataset with unity, so I think doing this on CPU side makes sense. Previously I've been thinking about submitting weighting data to the shader, but I couldn't find any document talking submitting data other than vertex geometry (and uv) to the shader, do you know any method to do so?

    Another way I'm thinking about is to create a texture of skinning weight offline and use that for rendering. but I'm stuck with retrieving the bone weights from the mesh... the GetBoneWeights function always give me an empty list, I'm trying to find out why this is happening, do you have any clue about this?

    Thank you again!
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    It should be working, unless perhaps you're using the "Unlimited" weights mode, in which case you might have to use this newer method:
    https://docs.unity3d.com/ScriptReference/Mesh.GetAllBoneWeights.html

    As for submitting data to shader, yes you could bind a StructuredBuffer to assign the weights to, or even assign the weights as a texture which I've seen done for some stuff before.
     
  5. Dzhange

    Dzhange

    Joined:
    Jan 19, 2019
    Posts:
    5

    Thanks! I kind of solved the bone weight problem, it seems there is something strange that happened in the LeapMotion extension I'm using. I made a texture with bone weights, but the problem is that the texture only contains per-vertex information, and I want it to cover the whole hand, do you have any idea of doing so? I'm looking into the Structured Buffer, maybe I can pass the boneweight to shader as vertex colors.
     
  6. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,550
    It would be more efficient to leave it as per-vertex in the texture, and then in your shader, sample the correct pixel from your texture inside of the vertex program of the shader and assign it to a
    float4
    in your
    v2f
    (vertex to fragment) struct, this value will then get interpolated across the triangle, giving you a whole hand coloring.
    You can get the ID of the vertex your vertex program is currently processing by having
    uint vertID : SV_VertexID;
    in your Input/appdata struct.

    You can use
    tex2Dlod()
    to sample in the vertex program.

    This way you won't need to render a large full UV texture, just a tiny texture that only has as many pixels as there are verts. Much less data to pass around and take up memory.
     
    Last edited: Jul 22, 2020
    Dzhange likes this.