How can I get a skinned mesh renderer's the vertices and indices into a compute shader?

Hey, I’m struggling to understand how to use the SkinnedMeshRenderer API to append its vertices and indices onto the corresponding buffers. I do not understand how to use the information from this page with my C# script to use the buffer in my compute shader. How do I accomplish this?

private void SetBuffers() {
        _meshObjects.Clear();
        _vertices.Clear();
        _indices.Clear();
        //_debugRays.Clear();

        foreach (var mf in _meshFilters) {
            int firstVertex = _vertices.Count;
            _vertices.AddRange(mf.sharedMesh.vertices);
          
            int firstIndex = _indices.Count;
            var indices = mf.sharedMesh.GetIndices(0);
            _indices.AddRange(indices.Select(index => index + firstVertex));
          
            _meshObjects.Add(new MeshObject() {
                localToWorldMatrix = mf.transform.localToWorldMatrix,
                indices_offset = firstIndex,
                indices_count = indices.Length
            });
        }
      
      
        foreach (var smr in _skinnedMeshRenderers) {
           // How can I get the vertices and indices out and put them on the buffers?
        }

        CreateComputeBuffer(ref _meshObjectBuffer, _meshObjects, 72);
        CreateComputeBuffer(ref _vertexBuffer, _vertices, 12);
        CreateComputeBuffer(ref _indexBuffer, _indices, 4);     
    }

private static void CreateComputeBuffer<T>(ref ComputeBuffer buffer, List<T> data, int stride) 
    where T : struct {
    // Do we already have a compute buffer?
    if (buffer != null) {
        // If no data or buffer doesn't match the given criteria, release it
        if (data.Count == 0 || buffer.count != data.Count || buffer.stride != stride) {
            buffer.Release();
            buffer = null;
        }
    }

    if (data.Count != 0) {
        // If the buffer has been released or wasn't there to
        // begin with, create it
        if (buffer == null) {
            buffer = new ComputeBuffer(data.Count, stride);
        }

        // Set data on the buffer
        buffer.SetData(data);
    }
}

Thanks.

You don’t need to do this anymore, you can directly access the existing vertex buffers.

1 Like

Splendid.

So if I want to send multiple SkinnedMeshRenderers worth of buffers to my compute shader, does that mean I have to have to declare and name a buffer in hlsl for each one? How can I account for an unknown number of SkinnedMeshRenderers. It seems like the ideal setup is to get rid of my vertex and index c# lists and instead use getvertexbuffer to combine all the meshes’ buffers and send it all. But how do I send them all over without the need to declare them individually?

Don’t define a buffer for each, just dispatch a compute for each one.

The compute shader casts rays against all of the geometry in the buffer to generate a depth texture thing. If I do multiple dispatches then I think I will be forced to repeat a lot of lot of raycasts, which sounds bad for performance. I will try multiple dispatches and see how it goes.

If all you need is a depth texture of those specific meshes, it would be better to just bind a texture to their materials and have their fragments shaders output their depth to that texture. It’s already being computed for your regular shaders, so you save on having to calculate it again.

I don’t think I can do that cause each object needs its own individual depth texture, and the game slowed to a crawl when I tried giving every actor its own camera to generate it with.