Custom Vertex Data Not Working

I have created a custom Mesh and a ShaderMaterial in Babylon.js. When I pass a custom vertex data named red to the mesh, the red attribute does not work at all.

I have carefully read the official documentation about customMesh, but I couldn’t find any content related to custom vertex attributes. I also searched on Google and found a related thread where someone achieved this by using mesh.setVertexData(), but the same code doesn’t work in my project.

Could anyone tell me what I should do? Thanks so much for your help!

    const material = new BABYLON.ShaderMaterial(
        "heatmap-material",
        scene,
        {
            vertexSource: `
in vec2 position;
in float red;
varying float vred;
void main()
{
    vred = red;
    gl_Position = vec4(position.xy, 0.0, 1.0);
}
        `,
            fragmentSource: `
varying float vred;
void main(){
    gl_FragColor = vec4(vred,0.0,0.0,1.0);
}
`,
            attributes: ["position", "red"],
        },
    );

    const mesh = new BABYLON.Mesh("heatmap", scene);
    mesh.material = material;
    const vertexData = new BABYLON.VertexData();
    let position = new Float32Array([
        -1, 1, 0,
        -1, -1, 0,
        1, -1, 0,
        1, 1, 0,
    ]);
    let indices = new Uint16Array([0, 1, 2, 0, 2, 3]);
    vertexData.positions = position;
    vertexData.indices = indices;
    vertexData.applyToMesh(mesh);
    let red = new Float32Array([1, 1, 1, 1])
    mesh.setVerticesData("red", red, false, 1);

:package: Resources

Hello and welcome!

Here is the working example - https://playground.babylonjs.com/#5RWYDU#4

Your shader declares:

in vec2 position;

But your mesh provides:

vertexData.positions = position; // this is vec3 (x, y, z)

In Babylon.js, the built-in “position” attribute is always vec3, not vec2.

Because of this mismatch, your vertex shader is invalid, and as a result, your custom attribute (red) never gets used.

The second thing is that your shader is rendering in clip space directly. One needs to transform it to uniform mat4 worldViewProjection; otherwise it will fill the entire screen.

4 Likes