| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Mischief.Render.Tutorial.Shaders
Synopsis
2.2. Shaders
This chapter will teach you about writing custom shaders in the Shader monad.
The Shmonad
The shader monad is a state monad in which you build custom shader code which will then be parsed into actual code. When writing shaders, it is recommended to do the following imports:
import Prelude() import Mischief.Materials
Prelude needs to be hidden, as shader code uses its own definition of primitive types and operations. See for instance,
vs Float and Float vs. +.+
Types
When working with shaders, there are 3 primitive types:
Each can be built with a literal. For instance, this is a shader that returns 5:
five ::ShaderaIntfive =pure5
There are vecs of between 2 and 4 elements. Each size having its own constructor: vec2, vec3, vec4.
foo ::Vec3Floatfoo =vec33.4 0.1 (-5)
There are also arrays, which can be of vecs or primitives.
bar ::Array(Vec2Uint) bar =array[vec25 0,vec21 4,vec210 3]
Arrays can be indexed into using !!:
let x = bar !! 2
Finally, there are matrices:
baz ::Mat2 3 baz =mat(vec35 0 4,vec31 1 1)
You can cast between different primitive types, or between vecs of the same size, using .cast
Operations
Algebric operators are defined using a convention inspired by Linear.
Two elements of the same type can be multiplied using *.
let a ::Float= 2*3
A scalar (left) can be multiplied with a vector (right) using *^, and vice versa for ^*.
let a ::Vec2Float= 2*^vec25 2
A matrix (left) can be multiplied with a vector (right) using !*^, or with a scalar (right) using !*. Vice versa
for ^*! and *!.
The same goes for other operators, such as /, +, -, %.
Functions
Shader functions are defined according to the [wgpu standard](https:/www.w3.orgTRWGSL] in Mischief.Shader.Functions.
If a function you need isn't yet defined by Mischief, you can bind it yourself using unsafeCall. For instance, assuming
atan2 wasn't defined, you could call it like this:
let x ::Vec2Float=vec25 2 let y ::Vec2Float=vec21 2 let z ::Vec2Float=unsafeCall"atan2" [Paramx,Paramy]
But be careful! This removes all typechecking. If you call a function with the wrong parameters it will panic.