Back to the referenceMaterials
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
sourcestringThe text of the file.
srcstringWhere 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
sourcestringThe file's text.
srcstringIts path: the extension decides how it is read, and warnings name it.
View source · loaders/shader/parse_shader_source.ts:21#TCreateMaterialtypenacatamalon
TCreateMaterial: (options: TMeshMaterialOptions) => TMeshMaterial
The two ways to call createMaterial: which kind of material comes back follows from shader,
so a model's material can only be handed to a model and a sprite's only to a sprite.
View source · gameobjects/material/create_material.ts:67#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#TMaterialOptionstypenacatamalon
TMaterialOptions: TSpriteMaterialOptions | TMeshMaterialOptions
What createMaterial is asked for. shader decides which of the two you are making.
View source · materials/types/t_material_options.ts:148#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
nameoptionalstringA name, which is what a warning about this material will call it.
fragmentoptionalstringThe fragment hook, in WGSL.
fragmentGlsloptionalstringThe same hook in GLSL, without which the effect is WebGPU only.
vertexoptionalstringThe vertex hook, in WGSL. 3D only: a sprite is a flat square and has nothing to move.
vertexGlsloptionalstringThe same, in GLSL.
uniformsoptionalTUniformValuesThe 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 | stringA 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
idstringtype'material'namestring | nullA name for reading in a warning. Never looked up by: a material is a value, not a resource.
fragmentstring | nullThe fragment hook in WGSL, which is what WebGPU compiles.
fragmentGlslstring | nullThe same hook written again in GLSL, which is what WebGL2 compiles.
vertexstring | nullThe vertex hook in WGSL. Only a 3D material has one: a sprite is a flat square.
vertexGlslstring | nullThe same, in GLSL.
uniformsTUniformValues | nullThe knobs, or null when there is no shader of your own to turn.
uniformSigTUniformSignature | nullWhat kind each knob is. Fixed once, because the compiled shader was built against it.
effectTShader | nullThe 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#TSpriteMaterialOptionstypenacatamalon
TSpriteMaterialOptions: TMaterialShaderOptions & { shader }
What createMaterial is asked for when the material is for flat things.
There is nothing here about a picture or a colour, because those belong to the sprite. This is the
effect and its knobs, and nothing else.
View source · materials/types/t_material_options.ts:134#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