Skip to content

Commit a7caca5

Browse files
committed
Blog about shadertoys
1 parent 542edea commit a7caca5

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed

blog/2025-04-10-shadertoys.md

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
title: "Shadertoys ported to Rust GPU"
3+
authors: [LegNeato]
4+
tags: ["demo"]
5+
---
6+
7+
# Porting Shadertoys to Rust with Rust GPU
8+
9+
We ported a few popular [Shadertoy](https://www.shadertoy.com/) shaders over to Rust
10+
using [Rust GPU](https://github.com/Rust-GPU/rust-gpu/). The process was straightforward
11+
and we want to share some highlights.
12+
13+
<!-- truncate -->
14+
15+
The code is available on [GitHub](https://github.com/Rust-GPU/rust-gpu-shadertoys).
16+
17+
![Shadertoy screenshot](/img/shadertoys.png)
18+
19+
## What is Rust GPU?
20+
21+
[Rust GPU](https://rust-gpu.github.io/) is a project that allows you to write code for
22+
GPUs using the Rust programming language. GPUs are typically programmed using
23+
specialized languages like [WGSL](https://www.w3.org/TR/WGSL/),
24+
[GLSL](https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders),
25+
[MSL](https://developer.apple.com/documentation/metal/performing_calculations_on_a_gpu),
26+
or
27+
[HLSL](https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl).
28+
Rust GPU changes this by letting you use Rust to write GPU programs (often called
29+
"shaders" or "kernels").
30+
31+
These Rust GPU programs are then compiled into [SPIR-V](https://www.khronos.org/spir/),
32+
a low-level format that [most GPUs understand](https://vulkan.gpuinfo.org/). Since
33+
SPIR-V is the format [Vulkan](https://www.vulkan.org/) uses, Rust GPU makes it possible
34+
to integrate Rust-based GPU programs into any Vulkan-compatible workflow.
35+
36+
For more details, check out the [Rust GPU website](http://rust-gpu.github.io/) or the
37+
[GitHub repository](https://github.com/rust-gpu/rust-gpu).
38+
39+
## Shared code between CPU and GPU
40+
41+
Sharing data between the CPU and GPU is common in shader programming. This often
42+
requires special tooling or manual effort. Using Rust on both sides made this seamless:
43+
44+
```rust
45+
#[repr(C)]
46+
#[derive(Copy, Clone, Pod, Zeroable)]
47+
pub struct ShaderConstants {
48+
pub width: u32,
49+
pub height: u32,
50+
pub time: f32,
51+
pub cursor_x: f32,
52+
pub cursor_y: f32,
53+
pub drag_start_x: f32,
54+
pub drag_start_y: f32,
55+
pub drag_end_x: f32,
56+
pub drag_end_y: f32,
57+
pub mouse_left_pressed: u32,
58+
pub mouse_left_clicked: u32,
59+
}
60+
```
61+
62+
Note that on both the CPU and the GPU we are using the
63+
[`bytemuck`](https://github.com/Lokathor/bytemuck) crate for the `Pod` and `Zeroable`
64+
derives. This crate is unmodified and integrated directly from
65+
[crates.io](https://crates.io/crates/bytemuck). Many `no_std` + no `alloc` Rust crates
66+
work on the GPU!
67+
68+
## Traits, generics, and macros
69+
70+
Rust GPU supports traits. We used traits to encapsulate shader-specific operations in
71+
reusable ergonomic abstractions:
72+
73+
```rust
74+
pub trait FloatExt {
75+
fn gl_fract(self) -> Self;
76+
fn rem_euclid(self, rhs: Self) -> Self;
77+
fn gl_sign(self) -> Self;
78+
fn deg_to_radians(self) -> Self;
79+
fn step(self, x: Self) -> Self;
80+
}
81+
```
82+
83+
While there are still some rough edges, generics mostly work as expected. We used them
84+
to support multiple channel types without duplicating logic:
85+
86+
```rust
87+
pub struct State<C0, C1> {
88+
inputs: Inputs<C0, C1>,
89+
cam_point_at: Vec3,
90+
cam_origin: Vec3,
91+
time: f32,
92+
ldir: Vec3,
93+
}
94+
```
95+
96+
Rust macros also function normally. Using macros allowed us to reduce repetitive code
97+
further.
98+
99+
```rust
100+
macro_rules! deriv_impl {
101+
($ty:ty) => {
102+
impl Derivative for $ty {
103+
deriv_fn!(ddx, OpDPdx, false);
104+
deriv_fn!(ddx_fine, OpDPdxFine, true);
105+
deriv_fn!(ddx_coarse, OpDPdxCoarse, true);
106+
deriv_fn!(ddy, OpDPdy, false);
107+
deriv_fn!(ddy_fine, OpDPdyFine, true);
108+
deriv_fn!(ddy_coarse, OpDPdyCoarse, true);
109+
deriv_fn!(fwidth, OpFwidth, false);
110+
deriv_fn!(fwidth_fine, OpFwidthFine, true);
111+
deriv_fn!(fwidth_coarse, OpFwidthCoarse, true);
112+
}
113+
};
114+
}
115+
116+
// Applied easily to multiple types:
117+
deriv_impl!(f32);
118+
deriv_impl!(Vec2);
119+
deriv_impl!(Vec3A);
120+
deriv_impl!(Vec4);
121+
```
122+
123+
## Standard Rust tools
124+
125+
Want to typecheck the shaders? `cargo check`. Build them? `cargo build`. Run in release
126+
mode? `cargo run --release`. Gate code at compile time? Use
127+
[features](https://doc.rust-lang.org/cargo/reference/features.html).
128+
129+
If you run `clippy` on the shaders, you'll see it complains about many things as we
130+
intentionally kept the Rust versions of shaders similar to their original GLSL versions.
131+
132+
This is one of Rust GPU's big advantages: you can use all the Rust tools you're already
133+
familiar with.
134+
135+
## Improving the Rust ecosystem
136+
137+
While porting shaders, we also contributed back to the ecosystem by identifying and
138+
fixing several issues in [`wgpu` and `naga`](https://github.com/gfx-rs/wgpu):
139+
140+
- [Fixed a panic while processing SPIR-V](https://github.com/gfx-rs/wgpu/pull/7397)
141+
- [Fixed incorrect translation of certain shader literals when targeting
142+
Metal](https://github.com/gfx-rs/wgpu/pull/7437)
143+
- [Fixed a regression making it impossible to include raw
144+
SPIR-V](https://github.com/gfx-rs/wgpu/pull/7503)
145+
146+
These fixes help everyone using `wgpu` and `naga`, not just users of Rust GPU.
147+
148+
## Come join us!
149+
150+
While we hit some sharp edges, porting Shadertoy shaders to Rust with Rust GPU was
151+
reasonably straightforward. Rust GPU is definitely ready for shader experimentation.
152+
153+
We're eager to add more users and contributors! We will be working on revamping the
154+
onboarding and documentation soon. To follow along or get involved, check out the
155+
[`rust-gpu` repo on GitHub](https://github.com/rust-gpu/rust-gpu).

static/img/shadertoys.png

2.49 MB
Loading

0 commit comments

Comments
 (0)