#Per entity unique vertex colors ?

1 messages · Page 1 of 1 (latest)

unique spear
#

Has anyone attempted doing this, or anyone have any ideas on whether such a thing is possible with the current Graphics package?

cursive nebula
#

I can only imagine this working by using a shared graphics buffer or texture per n entities (per material) with assigned memory segments per entity. I do a lot of 'per entity data' for voxel stuff in this way.

#

but dealing with that memory assignment is the annoying part 😄

#

if you're using shader graph, you'd access the buffer data in a custom hlsl node

unique spear
#

have you modified the entities graphics package for something similar, or is this using one of the DrawMesh_X methods? I realised after posting this that unique vertex colors in the traditional sense would clash with mesh instancing, but there are some techniques(vertex colors, rendertextures) that work on gameobjects that I am really missing. not using sg for my custom shader, and was looking at how instancing for deformations works wondering if there might be a similar trick for dealing with vert colors.

cursive nebula
#

No package modifications or indirect draw calls. What I'm imaging is a custom shader that will look up a vertex colour from a GraphicsBuffer (StructuredBuffer or ByteAddressBuffer in the shader) in the vert shader. There would be a material property override to inform the shader where in the buffer to start reading the data from, so many objects can share one buffer (as assigning a different buffer would need a new material).

#

So in the C# side you would:

  1. create a new GraphicsBuffer
  2. Material.SetBuffer
  3. Assign segments of the buffer to entities that need custom colours, and write that graphicsBufferStartIndex to the material (with a MaterialProperty attribute on an IComponentData with an int field).

In the vert shader you would :

  1. index = VertexID + GraphicsBufferStartIndex
  2. use that as an index into the StructureBuffer (or ByteAddressBuffer) containing your custom colours.

You could have one colour per triangle (VertexId / 3), or one per vert, or whatever you wanted.

#

You could use a texture instead of a buffer too, but buffers allow for partial updates. You can do partial updates with textures too but it would involve sending a smaller texture and doing a Texture.Copy (I think) on the GPU side to update the sub region of the bigger texture.
Other than this, I'm not sure how to have per entity vertex data.

unique spear
#

thanks for the ideas, kind of a lot for me to unpack but gonna make an attempt at doing some tests for this

unique spear
#

as a very simple test, is this use of graphicsbuffer wrong?

public class VertexColorBehaviour : MonoBehaviour
{
     public  Color          Color;
     public  Material       Material;
     private GraphicsBuffer m_GraphicsBuffer;
     static readonly int k_VertexColorsBuffer = Shader.PropertyToID("_VertexColors");
     private         MeshRenderer m_Renderer;

     public void OnEnable() 
     {
          m_Renderer = GetComponent<MeshRenderer>();
     }
        
     public void Update()
     {
        if (m_Renderer == null)
            return;
            
        var colorsArray       = new NativeArray<float4>(100, Allocator.TempJob);
        CreateGraphicsBufferIfNeeded(ref m_GraphicsBuffer, 100, UnsafeUtility.SizeOf<float4>());
            
        for (int i = 0; i < colorsArray.Length; i++)
        {
            colorsArray[i] = new float4(Color.r, Color.g, Color.b, Color.a);
        }
            
        m_GraphicsBuffer.SetData(colorsArray, 0, 0, colorsArray.Length);
        m_Renderer.material.SetBuffer(k_VertexColorsBuffer, m_GraphicsBuffer);
            
        colorsArray.Dispose();
    }
        
    public void OnDisable()
    {
         m_GraphicsBuffer?.Dispose();
    }
        
    private void CreateGraphicsBufferIfNeeded(ref GraphicsBuffer graphicsBuffer, int length, int stride)
    {
        if (graphicsBuffer != null && graphicsBuffer.count == length && graphicsBuffer.stride == stride)
            return;

        ReleaseGraphicsBuffer(ref graphicsBuffer);
        graphicsBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, length, stride);
            //m_IsDisposed = false;
    }
        
    private void ReleaseGraphicsBuffer(ref GraphicsBuffer graphicsBuffer)
    {
        if (graphicsBuffer != null)
            graphicsBuffer.Release();
       graphicsBuffer = null;
    }
}
#

simple vert color in maya on the right, unity shader on the left(using a simple output.color = input.color which is the mesh's vertex colors. however using output.color = _VertexColors[0] from uniform StructuredBuffer<float4> _VertexColors; is always black regardless of the color chosen in the above script

unique spear
#

well I am an idiot, took me way too long to realise I didnt have ExecuteAlways and was testing outside of playmode