Render mesh using vertex color

I have created a custom mesh using VertexPositionNormalColor for the vertices. However, I cannot figure out how to get the mesh to draw using the color attribute. I have associated a material to the model containing the mesh and tried playing around with the various options. Unfortunately, most of the drop downs show “None”. The mesh renders fine if I switch over to using VertexPositionNormalTexture and use the “Diffuse material” asset template to setup my material. Can someone point me in the right direction? I am using 3.1.0.1 beta02 0532. Thanks.

Just realised this is an issue for me as well on the latest beta… if you can be bothered, do make an issue on the Xenko github: https://github.com/xenko3d/xenko/issues

It’ll help!

Issue has been created. Thanks.

I was able to come up with the following material by digging around in the Xenko source. It renders the mesh using the color attributes, however the colors look washed out using just an ambient light. Color.Brown looks almost pink. Anyway, it’s a start.

return Material.New(GraphicsDevice, new MaterialDescriptor
{
    Attributes =
    {
        DiffuseModel = new MaterialDiffuseLambertModelFeature(),
        Diffuse = new MaterialDiffuseMapFeature(new ComputeVertexStreamColor())
    }
});
1 Like

You might want to poke around with light strength and also look at the postfx stuff in the compositor, (like the tonemapping etc.)

If I create a material with a constant color value and render my mesh it looks as I would expect. However, if I render the mesh using the vertex color stream using the exact same color, the mesh comes out lighter for some reason. The following image demonstrates the problem.

image

Both quads are rendered using the same color. The one on the left passes the color to the shader as a constant and the one on the right passes the color through the vertex information. Is this behavior expected? Thanks.

Sample Script

public class SampleStartupScript : StartupScript
{
    private static Color color = new Color(55, 27, 7, 255);

    public override void Start()
    {
        Material constantColorMaterial = Material.New(GraphicsDevice, new MaterialDescriptor
        {
            Attributes = new MaterialAttributes
            {
                Diffuse = new MaterialDiffuseMapFeature(new ComputeColor(color.ToColor4())),
                DiffuseModel = new MaterialDiffuseLambertModelFeature(),
                CullMode = CullMode.None,
            },
        });

        Material vertexColorMaterial = Material.New(GraphicsDevice, new MaterialDescriptor
        {
            Attributes = new MaterialAttributes
            {
                Diffuse = new MaterialDiffuseMapFeature(new ComputeVertexStreamColor()),
                DiffuseModel = new MaterialDiffuseLambertModelFeature(),
                CullMode = CullMode.None,
            },
        });

        Entity faceEntity = new Entity("Face");
        SceneSystem.SceneInstance.RootScene.Entities.Add(faceEntity);

        Model model = new Model();
        faceEntity.GetOrCreate<ModelComponent>().Model = model;
        model.Materials.Add(constantColorMaterial);
        model.Materials.Add(vertexColorMaterial);

        Mesh constantColorMesh = CreateMesh(new Vector3(-0.5f, 0, -5), 0);
        Mesh vertexColorMesh = CreateMesh(new Vector3(0.5f, 0, -5), 1);
       
        model.Meshes.Add(constantColorMesh);
        model.Meshes.Add(vertexColorMesh);
    }

    private Mesh CreateMesh(Vector3 offset, int materialIndex)
    {
        Vector3 normal = new Vector3(0, 0, 1);

        VertexPositionNormalColor[] vertices = new[]
        {
            new VertexPositionNormalColor(new Vector3(-0.5f, 0.5f, 0.5f) + offset, normal, color),
            new VertexPositionNormalColor(new Vector3(0.5f, 0.5f, 0.5f) + offset, normal, color),
            new VertexPositionNormalColor(new Vector3(0.5f, -0.5f, 0.5f) + offset, normal, color),
            new VertexPositionNormalColor(new Vector3(-0.5f, -0.5f, 0.5f) + offset, normal, color),
        };

        ushort[] indices = new ushort[] { 0, 1, 2, 0, 2, 3 };

        MeshDraw meshDraw = new MeshDraw
        {
            StartLocation = 0,
            VertexBuffers = new[] { new VertexBufferBinding(Buffer.Vertex.New(GraphicsDevice, vertices), VertexPositionNormalColor.Layout, 4) },
            IndexBuffer = new IndexBufferBinding(Buffer.Index.New(GraphicsDevice, indices), false, 6),
            DrawCount = 6,
            PrimitiveType = PrimitiveType.TriangleList,
        };

        return new Mesh
        {
            Draw = meshDraw,
            MaterialIndex = materialIndex,
        };
    }
}

Hello!
That looks like same color if vertex color was converted with GraphicsDevice.ColorSpace.

    // ...
    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    public struct MyVertex
    {
        public Vector3 Position;
        public Vector3 Normal;
        public Color4 Color;
        
        public static readonly VertexDeclaration Layout =
            new VertexDeclaration(VertexElement.Position<Vector3>(), VertexElement.Normal<Vector3>(), VertexElement.Color<Color4>());
    }
    // ...

        // ...
        var vertexColor = color.ToColor4().ToColorSpace(GraphicsDevice.ColorSpace);
        
        MyVertex[] vertices = new[]
        {
            new MyVertex{ Position = new Vector3(-0.5f, 0.5f, 0.5f) + offset, Normal = normal, Color = vertexColor },
            new MyVertex{ Position = new Vector3(0.5f, 0.5f, 0.5f) + offset, Normal = normal, Color = vertexColor },
            new MyVertex{ Position = new Vector3(0.5f, -0.5f, 0.5f) + offset, Normal = normal, Color = vertexColor },
            new MyVertex{ Position = new Vector3(-0.5f, -0.5f, 0.5f) + offset, Normal = normal, Color = vertexColor },
        };
        // ...

            // ...
            VertexBuffers = new[] { new VertexBufferBinding(Buffer.Vertex.New(GraphicsDevice, vertices), MyVertex.Layout, 4), },
            // ...
2 Likes

It now renders as I would expect. Is there any documentation that talks about why this is required? Thanks for your help!

Sorry, I’m not sure about documentation and details.:cry:
I thought that ComputeColor converts given color with ToColorSpace().

No worries. Thanks again for the help.

There was a bug in VertexPositionNormalColor that exacerbated the washed out color problem. That structure used “Color”, when it should be using “Color4” instead. A fix is on my branch:

Thanks! I ended up making my own vertex structure that uses Color4.