Vertex memory bits. Is there a way to pass 8 bit elements instead of 32 bit float to a shader.

To say i have a value of 255 for rgba i don’t want to hold 4 floating point values per vertex for a color i just want to hold the 8 bit value and let the shader turn that into floats when it reads it in to save memory. I also have this problem for indexs and potentially weights.

Is and if it is possible to drop off the memory requirements like that how do you do it?
Ect… example would be great if its possible.

Specifically problem is the below is obese i want to trim it down.

/// <summary>
/// basically a wide spectrum vertice structure.
/// </summary>
public struct VertexPositionColorNormalTextureTangentWeights : IVertexType
{
    public Vector3 Position;
    public Vector4 Color;
    public Vector2 TextureCoordinate;
    public Vector3 Normal;
    public Vector3 Tangent;
    public Vector3 BiTangent;
    public Vector4 BlendIndices;
    public Vector4 BlendWeights;

    public static VertexDeclaration VertexDeclaration = new VertexDeclaration
    (
          new VertexElement(VertexElementByteOffset.PositionStartOffset(), VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
          new VertexElement(VertexElementByteOffset.OffsetVector4(), VertexElementFormat.Vector4, VertexElementUsage.Color, 0),
          new VertexElement(VertexElementByteOffset.OffsetVector2(), VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0),
          new VertexElement(VertexElementByteOffset.OffsetVector3(), VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
          new VertexElement(VertexElementByteOffset.OffsetVector3(), VertexElementFormat.Vector3, VertexElementUsage.Normal, 1),
          new VertexElement(VertexElementByteOffset.OffsetVector3(), VertexElementFormat.Vector3, VertexElementUsage.Normal, 2),
          new VertexElement(VertexElementByteOffset.OffsetVector4(), VertexElementFormat.Vector4, VertexElementUsage.BlendIndices, 0),
          new VertexElement(VertexElementByteOffset.OffsetVector4(), VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 0)
    );
    VertexDeclaration IVertexType.VertexDeclaration { get { return VertexDeclaration; } }
}

To say for example blend indices only range to 128 or rather thats all i allow typically so by passing a byte per element i could on the gpu then just do this.
float indice = input.BlendIndices.x / 128f;
So basically i want to pass in a byte or assign to a ieee float8. To save memory per vertice so i pass only 32 bits for blendweights indices and color ect but i dunno how to do it.

I think the question is a bit ‘mixed’ but…

I use e.g.

new VertexElement(12, VertexElementFormat.Color, VertexElementUsage.Color, 0),

for colors and only takes 4 bytes in the vertex layout. When reading it from a shader the color is always a float between 0 and 1. Isn’t this what you are asking?

For blendIndices I use VertexElementFormat.Byte4 . Can’t check now but I’m sure it’s not ‘expanded’ to a float between 0 and 1 in the shader.

EDIT: for complete list of VertexElementFormat, https://github.com/MonoGame/MonoGame/blob/6f34eb393aa0ac005888d74c5c4c6ab5615fdc8c/MonoGame.Framework/Graphics/Vertices/VertexElementFormat.cs

Yes this is what im asking about.

So basically use the VertexElementFormat.Color
Can i still mark the VertexElementUsage.BlendIndices
like so.

new VertexElement(VertexElementByteOffset.OffsetColor(), VertexElementFormat.Color, VertexElementUsage.BlendIndices, 0),

Im still not sure how a byte color element is converted to a float on the shader ?
Kind of weird there isn’t a format labeled byte4 or float8 as well.

VertexElementUsage is only relevant for binding the vertex channels. It does not affect the format or conversion. Color format docs state

Four component, packed unsigned byte, mapped to 0 to 1 range.

It maps each byte [0, 255] to [0f, 1f].

There is a Byte4 format:

Four component unsigned byte.

1 Like