-
-
Notifications
You must be signed in to change notification settings - Fork 14
NZSL Basic syntax
NZSL is a strong typed shading language, inspired by C++ and Rust, with a syntax aimed at being easy to use yet very clear about what it does.
Here's a short example of a fragment/vertex shader which outputs vertex color, first in GLSL then the equivalent NZSL code.
GLSL vertex shader:
#version 450
layout(std140, binding = 0) uniform Matrices
{
mat4 projection;
mat4 view;
mat4 model;
} matrices;
layout(location = 0) in vec3 vertPos;
layout(location = 1) in vec3 vertColor;
layout(location = 0) out vec3 fragColor;
void main()
{
vec4 worldPos = matrices.model * vec4(vertPos, 1.0);
gl_Position = matrices.projection * matrices.view * worldPos;
fragColor = vertColor;
}
GLSL fragment shader:
#version 450
layout(location = 0) in vec3 vertColor;
layout(location = 0) out vec3 outputColor;
void main()
{
outputColor = vertColor;
}
And here's the equivalent NZSL shader:
[nzsl_version("1.0")]
module;
[layout(std140)]
struct Matrices
{
projection: mat4[f32],
view: mat4[f32],
model: mat4[f32]
}
external
{
[binding(0)] matrices: uniform[Matrices]
}
struct VertIn
{
[location(0)] pos: vec3[f32],
[location(1)] color: vec4[f32]
}
struct VertOut
{
[location(0)] color: vec4[f32],
[builtin(position)] pos: vec4[f32]
}
[entry(vert)]
fn main(input: VertIn) -> VertOut
{
let worldPos = matrices.model * vec4[f32](input.pos, 1.0);
let output: VertOut;
output.pos = matrices.projection * matrices.view * worldPos;
output.color = input.color;
return output;
}
struct FragOut
{
[location(0)] color: vec4[f32]
}
[entry(frag)]
fn main(input: VertOut) -> FragOut
{
let output: FragOut;
output.color = input.color;
return output;
}
So if you're familiar with HLSL or GLSL, it should feel familiar yet a bit different.
First of all, it's a bit more verbose than GLSL by choice (vec3[f32]
instead of vec3
for example), but it also has type inference and allows you to define multiple shaders stages inside of the same file (it also has modules which are described on their own page).
-
bool
: boolean value takingtrue
orfalse
-
f32
: 32bits floating-point value (commonly calledfloat
) -
f64
: 64bits floating-point value (commonly calleddouble
) - requires thefloat64
feature (see module declaration) -
i32
: Signed 32bits integer -
u32
: Unsigned 32bits integer -
()
: No type, rarely used
Vector types are made of primitive types, using []
as a type specifier, giving vecN[type]
syntax (with N between 2 and 4), for example:
-
vec3[f32]
is a three components vector made of 32bits floating-point values -
vec2[bool]
is a two components vector made of bool values.
Matrix types are declared using:
-
matNxM[type]
: A matrix with n columns and m rows (examples:mat2x2
,mat4x3
). -
matn[type]
: Common shorthand formatNxN[type]
which is a square matrix with n columns and n rows.
NZSL allows one to tag statements and expressions with attributes with the following form: [attr] statement
or [attr(value)] statement
.
This is used to give important parameters to the compiler, for example to declare the entry point of a shader you would write:
[entry(frag)] //< attribute entry with frag as a parameter
fn main()
{
// ...
}
Modules are the basic compilation unit of NZSL, each module is compiled separately.
The very first statement of a NZSL file should be the module statement, for example:
// You can have comments here
[nzsl_version("1.0")]
module;
This declares an anonymous module.
Module can also be named in the following way:
[nzsl_version("1.0")]
module MyEngine.MyModule; //< a module name can take multiple identifiers separated (or not) by a dot
Naming a module may be useful to import it in another module.
The module statement requires a nzsl_version
attribute, taking a string parameter which much follow the versionning schema of NZSL x.y(.z)
, for now only the 1.0
version is valid. This indicates the NZSL version used to write this module, allowing the language to break retrocompatibility in future update if required without breaking existing shader files (as explained here).
The module statement can also take the following attributes:
-
author
: takes a string, indicates the module author (can only appear once), has no semantic meaning. -
desc
: takes a string, gives the module a description (can only appear once), has no semantic meaning. -
license
: takes a string, indicates the module license (can only appear once), has no semantic meaning. -
feature
: takes aModuleFeature
, enables the usage of an additional feature for this module.
A complete example is:
[nzsl_version("1.0")]
[author("Lynix")]
[desc("A simple example module")]
[license("Public domain")]
[feature(float64), feature(texture1D)]
module Examples.Name;