メインコンテンツまでスキップ

WGSL Vertex and Fragment Shaders

This page covers the WGSL constructs that are specific to vertex and fragment shaders: attributes, varyings, and fragment outputs.

For resources that are shared across all shader stages — uniforms, textures, and storage buffers, declared with the simplified syntax and reflected into bind groups automatically — see WGSL Reflection.

Attributes

Attributes define per-vertex input data, and can only be used in the vertex shader. They must be declared using the following syntax:

attribute aUv0: vec2f;

Internally, a VertexInput struct is automatically created and populated with all the attributes. Attributes can be accessed from the structure passed to the main function, but also in the global scope.

attribute aUv0: vec2f;

@vertex fn vertexMain(input: VertexInput) -> VertexOutput {

// access it using input passed to the main function
var myUv1 = input.aUv0;

// but also as a global variable (particularly useful inside other functions)
var myUv2 = aUv0;
}

As part of the VertexInput structure, and also in the global scope, these built-in attributes are automatically available:

vertexIndex: @builtin(vertex_index)
instanceIndex: @builtin(instance_index)

The attribute names must match the names specified in the attributes property when creating the ShaderMaterial.

Varyings

Varyings are used to pass values from the vertex shader to the fragment shader. Declare them in both vertex and fragment shader using this simplified syntax:

varying texCoord: vec2f;

Internally, those are parsed, and stored in VertexOutput structure in the vertex shader, as well as in FragmentInput structure in the fragment shader.

Vertex Shader

As part of the VertexOutput structure these built-in variables are automatically available:

position: @builtin(position)

Example:

varying texCoord: vec2f;

@vertex fn vertexMain(input: VertexInput) -> VertexOutput {
var output: VertexOutput;
output.position = uniform.matrix_viewProjection * pos;
output.texCoord = vec2f(0.0, 1.0);
return output;
}

Fragment Shader

As part of the FragmentInput structure these built-in variables are automatically available:

position: @builtin(position) // interpolated fragment position
frontFacing: @builtin(front_facing) // front-facing
sampleIndex: @builtin(sample_index) // sample index for MSAA
primitiveIndex: @builtin(primitive_index) // primitive index (when supported)

These built-ins are also available in the global scope using these names:

pcPosition
pcFrontFacing
pcSampleIndex
pcPrimitiveIndex // when supported
注記

The primitiveIndex / pcPrimitiveIndex built-in is only available when device.supportsPrimitiveIndex is true. This feature is WebGPU-only (not available on WebGL2). See WGSL language extensions for enable primitive_index; and CAPS_PRIMITIVE_INDEX.

Example:

varying texCoord: vec2f;

@fragment
fn fragmentMain(input: FragmentInput) -> FragmentOutput {
var output: FragmentOutput;
output.color = vec4f(1.0);
return output;
}

Fragment Shader Outputs

The fragment shader is responsible for producing one or more color outputs, which are written to the render targets (color attachments) of the framebuffer.

The engine automatically provides a FragmentOutput structure, which includes a predefined set of vec4f fields: color, color1, color2 and so on, covering all possible color attachments, up to the limit defined by GraphicsDevice.maxColorAttachments.

As part of the FragmentOutput structure these built-in variables are automatically available:

fragDepth: @builtin(frag_depth)

Example:

@fragment fn fragmentMain(input: FragmentInput) -> FragmentOutput {
var output: FragmentOutput;
output.color = vec4f(1.0);
output.color1 = vec4f(0.5);
output.fragDepth = 0.2;
return output;
}
注記

Support for rendering to integer textures (output format other than vec4f) is not available yet, and will be added in the future.