Materials
Back to the reference

Materials

Surfaces, custom shaders, and the file format shaders are written in.

16 symbols

parseShaderFilefunctionnacatamalon

parseShaderFile(source: string, src: string) => TParsedShader

Reads a shader file: comments that say what it is, and plain shader code that says what it does.

The header is read from the whole file, deliberately outside the language halves. What the file is for and what knobs it has are one fact about the file, and a fact written twice is two facts that can drift apart.

A file stays valid code in its own language, so an editor colours it and a card could compile it with the engine's own preamble in front. That is the point of a comment-based header: nothing here invents a format that only this engine can open.

Parameters

sourcestring

The text of the file.

srcstring

Where it came from, used only so an error can name it.

View source · loaders/shader/parse_shader_file.ts:159

parseShaderSourcefunctionnacatamalon

parseShaderSource(source: string, src: string) => TParsedShader

Reads a shader file with the reader its extension asks for: a .shader is a graph of nodes, as JSON, and anything else is WGSL with a header. Both give the same shape, so nothing after this knows which it was.

It is the loader's own reader, open to tools: an editor that lets a material pick a shader needs the knobs it declares, whichever of the two ways it was written.

Parameters

sourcestring

The file's text.

srcstring

Its path: the extension decides how it is read, and warnings name it.

View source · loaders/shader/parse_shader_source.ts:21

TMaterialtypenacatamalon

TMaterial: TSpriteMaterial | TMeshMaterial

A surface, a shader, or both, that one or many things can be drawn with.

Two shapes and not one with half its fields unused, because a field that means nothing half the time is a field that lies. Which one you have is written on shader, so asking narrows it.

A material is an atomic value: nothing caches it and nothing looks it up by name. Two things share one by being handed the same one.

View source · materials/types/t_material.ts:181

TMaterialShadertypenacatamalon

TMaterialShader: 'sprite2d' | 'mesh3d' | 'post'

Which family of built-in shader a material plugs into, and so what its hooks are handed.

'sprite2d' is handed a colour already sampled and already tinted, and the flat square's place on it. 'mesh3d' is handed a surface and everything the light knew about it, and may also move the corner before any of that happens. 'post' is handed the finished frame.

A screen-wide effect takes the same hooks as a sprite, on purpose: a CRT over one sprite and a CRT over the whole picture are the same arithmetic, so they should be the same file.

View source · materials/types/t_uniforms.ts:15

TMaterialShaderOptionstypenacatamalon

The shader half of what a material can be asked for, which both kinds share.

Writing the source here is the quick way in, for an effect that lives with the scene that uses it. effect is the other way: a file, which several scenes can share and which an editor can open. Giving both is a contradiction, and the file wins.

Properties

nameoptionalstring

A name, which is what a warning about this material will call it.

fragmentoptionalstring

The fragment hook, in WGSL.

fragmentGlsloptionalstring

The same hook in GLSL, without which the effect is WebGPU only.

vertexoptionalstring

The vertex hook, in WGSL. 3D only: a sprite is a flat square and has nothing to move.

vertexGlsloptionalstring

The same, in GLSL.

uniformsoptionalTUniformValues

The knobs, with the values they start at. Their kinds are read off these, and fixed from then on, because how they are packed for the card depends on them.

Kept as given, not copied: the object you pass in is the one the renderer reads, so writing a number into it is read by the next frame. That is how a shader is driven by the game, and it is the same rule a text's style follows.

effectoptionalTShader | string

A file from useLoadShader, or the name one was loaded under.

View source · materials/types/t_material_options.ts:18

TMeshMaterialtypenacatamalon

TMeshMaterial: TShaderHalf & { shader, texture, tint, emissive, specular, shininess, alpha, transparent, smooth, wrap, vertexSnap, affine }

A material for models: a surface, and optionally a shader over it.

Here the surface is the material's, because that is what a hundred crates want to share. They are one shape and one surface and a hundred placements, and a colour per crate would be a parameter nobody asked for.

That is the other half of the split: in three dimensions the material owns the look, in two the object does.

View source · materials/types/t_material.ts:103

TMeshMaterialOptionstypenacatamalon

TMeshMaterialOptions: TMaterialShaderOptions & { shader, texture, key, tint, emissive, specular, shininess, alpha, transparent, smooth, wrap, vertexSnap, affine }

What createMaterial is asked for when the material is for models.

Everything about the surface is optional and defaults to a plain matt white one, so a material that only carries an effect says only that.

View source · materials/types/t_material_options.ts:64

TShaderHalftypenacatamalon

What both kinds of material have: a shader of your own, and the knobs on it.

All four sources are null on a material that only describes a surface, which is every material a game has until it asks for an effect.

Properties

idstring
type'material'
namestring | null

A name for reading in a warning. Never looked up by: a material is a value, not a resource.

fragmentstring | null

The fragment hook in WGSL, which is what WebGPU compiles.

fragmentGlslstring | null

The same hook written again in GLSL, which is what WebGL2 compiles.

vertexstring | null

The vertex hook in WGSL. Only a 3D material has one: a sprite is a flat square.

vertexGlslstring | null

The same, in GLSL.

uniformsTUniformValues | null

The knobs, or null when there is no shader of your own to turn.

uniformSigTUniformSignature | null

What kind each knob is. Fixed once, because the compiled shader was built against it.

effectTShader | null

The file this came from, or null when the source was written inline.

View source · materials/types/t_material.ts:16

TSpriteMaterialtypenacatamalon

TSpriteMaterial: TShaderHalf & { shader }

A material for flat things: a shader and nothing else.

The picture and the colour are not here, and that is the design. A sprite carries its own, and carries them per sprite: they travel in the instance buffer next to its place and its size, so a thousand sprites in one draw can be a thousand different colours. Putting the colour on something shared would mean one of these per sprite to vary it, which is the opposite of what a material is for. A sprite keeps its own texture and its own tint, and its material is only the effect over the top.

View source · materials/types/t_material.ts:67

TTextureWraptypenacatamalon

TTextureWrap: 'repeat' | 'clamp' | 'mirror'

What a model's picture does past its edge.

A model's corners may ask for any part of the plane, not only the picture's own square: a ladder of UVs from 0 to 20 across a field is how one small patch of grass covers a whole hillside, and it is how nearly every level of the era was textured. 'repeat' tiles the picture, 'mirror' tiles it flipped every other time so its seams meet themselves, and 'clamp' stretches its last row and column outwards.

Repeating is the default for a model, as it is in glTF. A sprite and a map never repeat: they read one frame of a sheet, and the next frame over is not theirs to show.

View source · materials/types/t_material.ts:87

TUniformSignaturetypenacatamalon

TUniformSignature: Record<string, TUniformType>

What kind each of those parameters is.

Worked out once from the shape of the first values it was given, and fixed from then on: how the numbers are laid out in memory depends on it, and the shader has already been compiled against that layout.

View source · materials/types/t_uniforms.ts:54

TUniformTypetypenacatamalon

TUniformType: 'f32' | 'vec2<f32>' | 'vec3<f32>' | 'vec4<f32>'

What kind a material's own parameter may be: one number, or two, three or four of them.

A small set on purpose. It covers what an effect is actually tuned with (a strength, a count, a colour, an offset) and leaves out matrices and lists, which bring alignment rules that are all cost and no use here. The one matrix a drawing needs is the one that puts it on screen, and that already travels with the drawing rather than with its surface.

View source · materials/types/t_uniforms.ts:29

TUniformValuestypenacatamalon

TUniformValues: Record<string, number | number[]>

A material's own parameters, by name. One number, or a list of two to four.

Change one and the next frame shows it: the card is handed these again every draw, so animating a strength is an assignment and nothing else.

View source · materials/types/t_uniforms.ts:41