Summary of objects in WebGPU ShaderMaterial and Babylon-specific WGSL

Edited to correct my errors based on @Evgeni_Popov’s reply

I had a rough time figuring out how to declare Babylon objects and use them within Babylon’s slightly-modified WGSL shader language. This comes from experimentation and (mostly) Babylon.js docs

Document clarification

The note on the color attribute applies only to color, not any other attributes. That is, it doesn’t apply to other VerticesKind values.

Note: if you use the “color” attribute in your shader code, don’t add it to the attributes property passed to the ShaderMaterial constructor! This attribute will be automatically added if a vertex buffer named “color” is attached to the mesh. If you add “color” to the attributes array, you will get an error like “Attribute shader location (1) is used more than once”.

I found for other VerticesKind values:
Both MaterialOptions {attributes: [“KIND”,…],…} and WGSL attribute KIND: TYPE; were required.

without attribute declaration in WGSL:

Error while parsing WGSL: :68:18 error: struct member [name of VertexKind] not found

with only WGSL attribute declaration, (without MaterialOptions {attributes: KIND}), result was:

Vertex attribute slot 1 used in ([ShaderModule “vertex”], [EntryPoint “main”]) is not present in the VertexState.

Declaring objects for Babylon-specific WGSL

I found out (at least one working way) for creating Babylon objects, tying them to ShaderMaterial constructor-specified MaterialOptions, then declaring within Babylon-specific WGSL and finally using/accessing them in Babylon-specific WGSL.

Organized by WGSL object type, here is what I’ve gathered. There are a couple of missing types and functions, such as StorageBuffer, writing to a Texture, TransformFeedback buffer and probably more I’m not aware of. Honestly, it’s not clear to me yet all of the WGSL types available and how/if Babylon tries to preserve some type of compatibility, between GLSL and WGSL or making WGSL easier.

On the Babylon object side, it should be clear from Babylon’s class documentation where to insert the TypedArray data. I don’t address that specifically here, nor do I address updates to data (including whether it’s possible to update data or change the size of data).

PLEASE comment on any corrections or additions!

Attributes (for other than “color”, see the current Babylon guide)

Material {Options}: {attributes: [NAME, …],…}
mesh.setVerticesData(NAME, DATA, UPDATABLE, ARRAY_ELEMENTS_PER_SPAN); // NAME is specified for KIND

WGSL in Babylon
declaration: attribute NAME: TYPE; // applies only in @vertex
read: vertexInputs.NAME

WORLD, VIEW, PROJECTION

Material {Options}: { uniformBuffers: [“Scene”, “Mesh”],…}

WGSL in Babylon
#include<sceneUboDeclaration>
#include<meshUboDeclaration>

read: scene.NAME or mesh.NAME // e.g. scene.viewProjection, mesh.world

SHADER INPUTS/OUTPUTS

Material {Options}: none

WGSL in Babylon
declaration: varying NAME: TYPE; // where used in @vertex and @fragment
write: vertexOutputs.NAME // in @vertex
read: fragmentInputs.NAME // in @fragment

write: fragmentOutputs.NAME // in @fragment

Uniform

Material {Options}: {uniforms:[“NAME”,…],…} // best practice is to use this, though it still might work without.
material.setXXX();

WGSL in Babylon
declaration: uniform NAME TYPE;
read: uniforms.NAME TYPE

UniformBuffer

Material {Options}: {uniformBuffers:[“NAME”,…],…}
new UniformBuffer(); addUniform(); updateXXX(); uniform.update(); material.setUniformBuffer();

WGSL in Babylon
declaration:
struct STRUCT_NAME {NAME: TYPE, …};
var<storage,read_write> STRUCT_VARIABLE : STRUCT_NAME;

read: STRUCT_VARIABLE.NAME;

Texture

Material {Options}: {samplers:[“NAME”,…],…}
new Texture(); material.setTexture();

WGSL in Babylon
declaration: var NAME: TEXTURE_TYPE<VALUE_TYPE>; // TEXTURE_TYPE e.g. texture_2d

read: textureLoad(); // no sampler needed
read: textureSample(); // sampler needed

Sampler

Material {Options}: {samplerObjects:[“NAME”,…],…}
new TextureSampler(); sampler.setParameters(); sampler.samplingMode(); material.setTextureSampler();

WGSL in Babylon
declaration: var NAME: sampler;
read: textureSample();

I’m not sure where the error is in the documentation? It indicates that the “color” attribute should not be added to the list of attributes if it’s used in the shader, but says nothing about the other types of attributes, which means that they must be added to the list.

Don’t hesitate to update the page if something is not clear! You can click the “github icon” located at the bottom of the page to edit the page.

Attributes can only be declared and used in vertex shaders (same in WebGL). If you want to use it in the fragment shader, you must use a varying variable, set a value to it in the vertex shader (vertexOutputs.NAME = ...) and access it in the fragment shader through fragmentInputs.NAME.

You missed the semi-colon:

declaration: varying NAME: TYPE; // where used in @vertex and @fragment

You must pass the list of uniform names through the uniforms parameter of the options object. In some cases, it may work not to declare the name and set a value with material.setXXX, but it’s good practice to always declare the name when constructing a ShaderMaterial instance.

I’m not sure what you mean? The doc says to use setUniformBuffer to set a uniform buffer. You are right regarding the uniform buffer itself: you must create an instance of UniformBuffer, add uniforms to it and set values through the updateXXX methods.

You must declare the name(s) of the uniform buffer(s) you use through the uniformBuffers parameter of the options object.

The declaration of a uniform buffer is something like:

struct STRUCT_NAME {
    NAME: TYPE,
    ...
};
var<storage,read_write> STRUCT_VARIABLE : STRUCT_NAME;

See this section of the doc.

You must declare the name(s) of the texture(s) you use through the samplers parameter of the options object.

You must declare the name(s) of the sampler(s) you use through the samplerObjects parameter of the options object.

It’s a bit unfortunate we used the word sampler instead of texture in the shader material, meaning sampler is not available for the sampler object in WGSL… sampler is the name of the type used in GLSL to reference a texture, that’s why we used it in the first place.

It is:

declaration: var NAME: sampler;

There’s a single type of sampler, which is sampler. What the sampler should do (bilinear, trilinear, etc) is set when the binding group is constructed, according to how the sampler has been configured in javascript.

Note that there are additional information about WGSL in the compute shader documentation page, it this can help.

Thank you!

I’ve edited my post to correct my errors.

Most were just my mistake. When I tested a single uniform and a texture without a sampler (using textureLoad()), the material options property values for .uniforms and .samplers were not needed at all. I’ve added your comment on “best practice” in case anyone runs into the same thing I did.

Thank you for the detailed correction. Looking at my post relative to your original doc, it did help me organize my thoughts, but I’m not sure my succinct listing actually helps anyone else. I’ll leave my corrected post up just in case.

1 Like