Search Unity

Writing the vertex positions into a texture on GPU

Discussion in 'Shaders' started by flogelz, Nov 10, 2020.

  1. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    I'm trying to do a shader effect only at parts, where the skinned mesh is moving. I would determine those parts by subtracting the old from the new vertex position. (This would result in everything, that's not currently moving to be 0, while moving parts show a difference.)

    Does somebody has an idea on how to get every old vertex position of a mesh to the shader?

    After looking into it, I'd say that arrays are not ideal, as the mesh could end up with 10.000 points updating every frame as well as skinning would probably make it harder to get these on cpu.
    So I thought of rendering the mesh again, but using the data from the vertex shader (so on the gpu which should be faster) to write each vertex position to one pixel inside the texture. But Graphics.Blit that uses a shader can't take in a mesh, while if'd draw the mesh with a replacement shader, i can't map the vertex point to the correct pixel on the rendertexture...
     
    bb8_1 likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    For skinned meshes this data is already available ... sort of. You can get the skinned mesh's previous skinned object space position when this is added to the vertex shader:
    Code (csharp):
    1. float3 oldPos : TEXCOORD4;
    Unity also keeps track of the previous frame's model transform and view projection matrix, which it passes in for the motion vector pass, but which you'll have to track and assign to the material yourself to use.
     
  3. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    @bgolus Oh, I didn't know there was such data available- Thx for the answer!

    About the code snippet itself, I tried calling it in a vertex shader, but it returns just an empty texcoord channel with the uvs. Is there something i have to activate somewhere for this to work? Also with previous skinned obj space position, do you mean the previous frame position or the position as if the mesh wasnt deformed at all?

    And do you have a ressource on how or a hint where I could save out the matrix?
     
  4. flogelz

    flogelz

    Joined:
    Aug 10, 2018
    Posts:
    142
    Oh wait, I think I got it! The change was just so small that I had to bump the speed up a lot to see a difference! Gonna try around and gonna come back to this later. Let's see if it everythings working!
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    For the matrix, you’ll need to attach a script to the renderer component’s game object that saves off the .localToWorldMatrix. Explicitly the one on the skinned mesh renderer component itself, not the transform, and pass the previous frame’s matrix to the material (probably with a material property block). The camera component already has a .previousViewProjectionMatrix you can grab and assign as a global matrix.

    I’ve not looked at exactly what’s needed to enable motion vector data on the skinned mesh itself, or in what situations it might break. There’s a setting on the skinned mesh component to enable it, and it’s possible motion vectors need to be enabled on the camera at least once for it to work too. Once I’ve gotten it working, in the limited testing I’ve done disabling the post processing that enabled motion vectors doesn’t seem to disable the last frame data on the mesh. But I’ve not looked too hard.
     
    flogelz likes this.