⚠ Archived v1 docs (raylib-only). These are the original docs for the raylib-only release. The current multi-backend docs (Mibo.Core + Mibo.Raylib + Mibo.MonoGame) live at the site root.
Shaders
Shaders are GPU programs that transform vertices and determine pixel colors. They run on the graphics card in parallel, making them efficient for complex visual effects.
What They Are
- Vertex shaders transform 3D model vertices into screen space
- Fragment shaders (also called pixel shaders) determine the final color of each pixel
- Shaders (in raylib terminology) package vertex+fragment pairs with parameters
Why Use Them
Use shaders when you need visual effects beyond what built-in rendering provides:
- Custom lighting models (toon shading, stylized PBR)
- Post-processing effects (bloom, tone mapping, color grading)
- Special effects (holograms, distortion, pixelation)
- Optimized rendering for specific art styles
When to Write Them
You don't need custom shaders to start. Mibo.Raylib's built-in renderers work without them:
- 2D games: Use
Graphics2Dwith standard raylib drawing (no shaders required) - 3D games: Use
Graphics3Dwith standard raylib model rendering (works without custom shaders)
Write shaders when: - You have specific visual requirements - You need performance optimizations for your target hardware - You're building advanced rendering features
Loading Shaders
Shaders are GLSL strings loaded at runtime using Raylib.LoadShaderFromMemory or Raylib.LoadShader. There is no content pipeline — shaders are plain .fs/.vs files or embedded strings.
open Raylib_cs
// Load from file
let myShader = Raylib.LoadShader("shaders/vertex.vs", "shaders/fragment.fs")
// Or load from memory (GLSL strings)
let fragCode = """
#version 330
in vec2 fragTexCoord;
in vec4 fragColor;
out vec4 finalColor;
uniform vec4 tint;
void main() {
vec4 texel = texture(texture0, fragTexCoord);
finalColor = texel * tint;
}
"""
let myShader = Raylib.LoadShaderFromMemory(null, fragCode)
Setting Parameters
Set shader parameters using Raylib.SetShaderValue:
open System.Numerics
open System.Runtime.InteropServices
open Raylib_cs
// Set a float uniform
let loc = Raylib.GetShaderLocation(myShader, "tint")
let mutable value = 1.0f
use p = fixed &value
Raylib.SetShaderValue(myShader, loc, NativePtr.toVoidPtr p, ShaderUniformDataType.Float)
// Set a matrix uniform (no fixed needed)
let world = Matrix4x4.Identity
let matLoc = Raylib.GetShaderLocation(myShader, "world")
Raylib.SetShaderValueMatrix(myShader, matLoc, world)
Uniform Type |
|
|---|---|
|
|
|
|
|
|
|
|
|
|
_IMPORTANT_: The project uses
[<DisableRuntimeMarshalling>]. This affects howSetShaderValueworks — see the critical warning below.
DisableRuntimeMarshalling and SetShaderValue
Because the project uses [<DisableRuntimeMarshalling>], you must use fixed + NativePtr.toVoidPtr when passing scalar, vector, or struct values to SetShaderValue. Passing raw values directly as void* arguments causes the runtime to treat the value itself as a memory address, leading to access violations.
DO NOT do this:
// WRONG — runtime treats the int value as a pointer address
Raylib.SetShaderValue(shader, loc, 1, ShaderUniformDataType.Int)
// WRONG — runtime treats the float value as a pointer address
Raylib.SetShaderValue(shader, loc, 0.5f, ShaderUniformDataType.Float)
// WRONG — runtime treats the Vector3 as a pointer address
Raylib.SetShaderValue(shader, loc, Vector3.One, ShaderUniformDataType.Vec3)
ALWAYS pin the value and pass a pointer:
open System.Runtime.InteropServices
let setShaderInt (shader: Shader) (loc: int) (value: int) =
use p = fixed &value
Raylib.SetShaderValue(shader, loc, NativePtr.toVoidPtr p, ShaderUniformDataType.Int)
let setShaderFloat (shader: Shader) (loc: int) (value: float32) =
use p = fixed &value
Raylib.SetShaderValue(shader, loc, NativePtr.toVoidPtr p, ShaderUniformDataType.Float)
let setShaderVec3 (shader: Shader) (loc: int) (value: Vector3) =
use p = fixed &value
Raylib.SetShaderValue(shader, loc, NativePtr.toVoidPtr p, ShaderUniformDataType.Vec3)
let setShaderVec4 (shader: Shader) (loc: int) (value: Vector4) =
use p = fixed &value
Raylib.SetShaderValue(shader, loc, NativePtr.toVoidPtr p, ShaderUniformDataType.Vec4)
Exceptions:
SetShaderValueMatrixtakesMatrix4x4directly (notvoid*) — this works correctly withoutfixed.Rlgl.SetUniform(raw rlgl) also requiresfixed + NativePtr.toVoidPtr.
Where to Learn More
Shader binding contracts (what parameters each shader type expects) are documented in the rendering sections:
- 2D rendering shaders: See Rendering 2D overview for shader contracts
See also: raylib shaders documentation
[<Struct>] type Matrix4x4 = new: value: Matrix3x2 -> unit + 1 overload member Equals: other: Matrix4x4 -> bool + 1 overload member GetDeterminant: unit -> float32 member GetElement: row: int * column: int -> float32 member GetHashCode: unit -> int member GetRow: index: int -> Vector4 member ToString: unit -> string member WithElement: row: int * column: int * value: float32 -> Matrix4x4 member WithRow: index: int * value: Vector4 -> Matrix4x4 static member ( * ) : value1: Matrix4x4 * value2: Matrix4x4 -> Matrix4x4 + 1 overload ...
<summary>Represents a 4x4 matrix.</summary>
--------------------
Matrix4x4 ()
Matrix4x4(value: Matrix3x2) : Matrix4x4
Matrix4x4(m11: float32, m12: float32, m13: float32, m14: float32, m21: float32, m22: float32, m23: float32, m24: float32, m31: float32, m32: float32, m33: float32, m34: float32, m41: float32, m42: float32, m43: float32, m44: float32) : Matrix4x4
<summary>Gets the multiplicative identity matrix.</summary>
<returns>Gets the multiplicative identity matrix.</returns>
[<Struct>] type Vector3 = new: value: Vector2 * z: float32 -> unit + 3 overloads member CopyTo: array: float32 array -> unit + 2 overloads member Equals: other: Vector3 -> bool + 2 overloads member GetHashCode: unit -> int member Length: unit -> float32 member LengthSquared: unit -> float32 member ToString: unit -> string + 2 overloads member TryCopyTo: destination: Span<float32> -> bool static member (&&&) : left: Vector3 * right: Vector3 -> Vector3 static member ( * ) : left: Vector3 * right: Vector3 -> Vector3 + 2 overloads ...
<summary>Represents a vector with three single-precision floating-point values.</summary>
--------------------
Vector3 ()
Vector3(value: float32) : Vector3
Vector3(values: System.ReadOnlySpan<float32>) : Vector3
Vector3(value: Vector2, z: float32) : Vector3
Vector3(x: float32, y: float32, z: float32) : Vector3
<summary>Gets a vector whose 3 elements are equal to one.</summary>
<returns>A vector whose three elements are equal to one (that is, it returns the vector <code data-dev-comment-type="c">(1,1,1)</code>).</returns>
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val float32: value: 'T -> float32 (requires member op_Explicit)
--------------------
type float32 = System.Single
--------------------
type float32<'Measure> = float32
[<Struct>] type Vector4 = new: value: Vector2 * z: float32 * w: float32 -> unit + 4 overloads member CopyTo: array: float32 array -> unit + 2 overloads member Equals: other: Vector4 -> bool + 2 overloads member GetHashCode: unit -> int member Length: unit -> float32 member LengthSquared: unit -> float32 member ToString: unit -> string + 2 overloads member TryCopyTo: destination: Span<float32> -> bool static member (&&&) : left: Vector4 * right: Vector4 -> Vector4 static member ( * ) : left: Vector4 * right: Vector4 -> Vector4 + 2 overloads ...
<summary>Represents a vector with four single-precision floating-point values.</summary>
--------------------
Vector4 ()
Vector4(value: float32) : Vector4
Vector4(values: System.ReadOnlySpan<float32>) : Vector4
Vector4(value: Vector3, w: float32) : Vector4
Vector4(value: Vector2, z: float32, w: float32) : Vector4
Vector4(x: float32, y: float32, z: float32, w: float32) : Vector4
Mibo