HLSL vs GLSL vs WGSL vs Metal: shader languages compared
Shader languages look different on the surface and think the same underneath. They all describe a function that runs on the GPU for every pixel (or vertex), and they all have vectors, matrices and a handful of math functions in common. Once you know one, the others are a matter of vocabulary. Here is how they compare, and which one to start with.
Which language runs where
| Language | Where you meet it |
|---|---|
| HLSL | Unity (Built-in and URP), Unreal Engine, DirectX, most console and PC game engines |
| GLSL | OpenGL, WebGL, Shadertoy, three.js, GameMaker, LÖVE, Vulkan (via SPIR-V) |
| Godot shading language | Godot Engine (it is GLSL-like with its own built-ins) |
| Metal Shading Language | iOS, iPadOS, macOS and Apple's other platforms |
| WGSL | WebGPU in the browser, and engines such as Bevy |
The same idea in four syntaxes
Blend two colors by a factor t, in each language:
// HLSL (Unity, Unreal) float3 c = lerp(a, b, t); // GLSL (WebGL, Shadertoy, three.js) vec3 c = mix(a, b, t); // Metal float3 c = mix(a, b, t); // WGSL (WebGPU, Bevy) let c = mix(a, b, t);
Vocabulary that changes
| Idea | HLSL | GLSL | Metal | WGSL |
|---|---|---|---|---|
| Vector of 3 | float3 | vec3 | float3 | vec3f |
| Blend | lerp | mix | mix | mix |
| Fractional part | frac | fract | fract | fract |
| Clamp to 0..1 | saturate | clamp(x, 0.0, 1.0) | saturate | saturate |
| Remainder | fmod | mod (always positive) | fmod | % |
| Matrix times vector | mul(M, v) | M * v | M * v | M * v |
| A function | float f(float x) | float f(float x) | float f(float x) | fn f(x: f32) -> f32 |
Two differences cause the most surprises. First, remainder of a negative number: HLSL's fmod(-1.0, 2.0) is -1, while GLSL's mod(-1.0, 2.0) is 1, so a pattern can flip when you move code between languages. Second, WGSL is much stricter: it has no ? : operator (you write select), you cannot assign to two components at once, and integers and floats never mix silently.
Which one should you learn first?
- You use Unity or Unreal: HLSL.
- You want to make shader art or work on the web: GLSL (and Shadertoy), then WGSL when you move to WebGPU.
- You use Godot: the Godot shading language; skills from GLSL carry over almost one to one.
- You build for Apple devices: Metal.
The honest answer is that the language matters far less than the concepts: positions, distance fields, noise, lighting, ray marching. That is why ShaderBattle teaches each lesson once and shows it in all eleven targets. Switch languages with the picker in the top bar, and the lessons, hints, starter code and export all follow. For a first lesson on the shared ideas, try Vectors & swizzling and Rotation & matrices.
Keep reading
- What is a fragment shader? A plain explanation with code
- How to learn shader programming: a step-by-step roadmap
- What is ray marching? Distance fields explained simply
- Noise in shaders: value noise, fBm and what they are for
- How to make an ocean shader: waves, Fresnel and foam