Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Question LinearBlendSkinning node & Graphics.DrawMesh?

Discussion in 'DOTS Animation' started by QuebecDev, Jan 8, 2022.

  1. QuebecDev

    QuebecDev

    Joined:
    May 9, 2020
    Posts:
    37
    Hi,

    I have a dumb question :/

    Is there a way to combine Graphics.DrawMesh() and Linear blend skinning node?

    Linear blend skinning documentation says "You must provide skinned matrices in the _SkinMatrices buffer. The node uses the _SkinMatrixIndex property to calculate where the matrices associated with the current mesh are located in the _SkinMatrices buffer."

    Is it possible to call Graphics.DrawMesh(), and feed in the SkinMatrices?
    Code (CSharp):
    1. public static void DrawMesh(
    2. Mesh mesh,
    3. Vector3 position,
    4. Quaternion rotation,
    5. Material material /*Use a LinearBlendSkinning material*/,
    6. int layer,
    7. Camera camera = null,
    8. int submeshIndex = 0,
    9. MaterialPropertyBlock properties = null /*Provide SkinMatrices somehow??*/,
    10. bool castShadows = true,
    11. bool receiveShadows = true,
    12. bool useLightProbes = true
    13. );
    14.  
     
  2. QuebecDev

    QuebecDev

    Joined:
    May 9, 2020
    Posts:
    37
    Do not answer all at the same time!? :D
     
  3. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,269
    The skin matrices are stored in a global compute buffer and the shader uses a hybrid instanced property to index the buffer.

    May I ask why you are trying to use DrawMesh for a DOTS skinned mesh?
     
  4. QuebecDev

    QuebecDev

    Joined:
    May 9, 2020
    Posts:
    37
    Just to experiment.

    Does that mean it is possible to animate mesh called from DrawMesh()? If so, can you tell me in theory how would it work?
     
  5. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,269
    I have no idea if this is possible, but if it is, here is what you need to do:
    First, you need to fill a ComputeBuffer with the skin matrices of your bones in the format the shader expects. This is likely a float3x4 but you should probably check your version to make sure. Assign that buffer to the global _SkinMatrices property.
    Second, you need to set the _SkinMatrixIndex property to be the first index of your skeleton. That may or may not be possible since normally this is a DOTS instanced property.
     
  6. QuebecDev

    QuebecDev

    Joined:
    May 9, 2020
    Posts:
    37
    Hi,

    I just tested it, did not work. My character stays T pose.

    Unless I have made some mistakes? See code below.

    Code (CSharp):
    1.     private void Start()
    2.     {
    3.         propetyBlock = new MaterialPropertyBlock();
    4.  
    5.         computeBuffer = new ComputeBuffer(skinMatrix.Count, sizeof(float) * 12, ComputeBufferType.Constant);
    6.         computeBuffer.SetData<float3x4>(skinMatrix);
    7.  
    8.         propetyBlock.SetInt("_SkinMatrixIndex", 0);
    9.         propetyBlock.SetBuffer("_SkinMatrices", computeBuffer);
    10.     }
    11.  
    12.     private void Update()
    13.     {
    14.         Graphics.DrawMeshInstanced(
    15.             mesh,
    16.             0,
    17.             material,
    18.             new Matrix4x4[] {Matrix4x4.TRS(new Vector3(0,0,0), Quaternion.identity, new Vector3(0.01f, 0.01f, 0.01f))},
    19.             1,
    20.             propetyBlock
    21.             );
    22.     }
    List<float3x4> skinMatrix that I provided in computeBuffer.SetData() is a running pose... but he stays in T pose.

    propetyBlock.SetInt("_SkinMatrixIndex", 0); this should alway be 0 right? because index 0 is my root bone.
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,269
    What you are feeding in seems correct. But the API you are using to feed in the data must not be correct, which is the issue I suspected you may run into.

    Unfortunately I can't really tell you the right way to set the data. Personally, I let the Hybrid Renderer populate _SkinMatrixIndex and use Shader.SetGlobalBuffer for _SkinMatrices (actually I use the Compute Deformation equivalents). I also disabled Hybrid Renderer's built-in skinning so that it doesn't overwrite the buffer assignments.
     
  8. QuebecDev

    QuebecDev

    Joined:
    May 9, 2020
    Posts:
    37
    Thanks for your help, maybe someone else will be able to tell me the right way to do it?