2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RustでGPUシェーダーが書ける【Rust GPU】

Posted at

はじめに

GPUプログラミングといえば、GLSL、HLSL、WGSLなどの専用シェーダー言語を使うのが一般的です。しかし、これらの言語は大規模なコードベースの管理が難しく、現代的なプログラミング言語と比べると機能面で見劣りします。

Rust GPUは、Rustプログラミング言語を使ってGPUシェーダーを記述できるプロジェクトです。今回は実際にRust GPUをクローンして、サンプルシェーダーを実行してみました。

注意: Rust GPUは現在も活発に開発中の初期段階プロジェクトです。シンプルなシェーダーのコンパイルと実行は機能し、コアライブラリの大部分もコンパイルできますが、まだ実装されていない機能も多くあります。技術的には使用可能ですが、本番環境での使用には適していません。

Rust GPUのクローンと実行

以下の手順でRust GPUをクローンし、サンプルを実行します。

# リポジトリをクローン
git clone https://github.com/Rust-GPU/rust-gpu.git
cd rust-gpu

# サンプルシェーダーを実行
cd examples/runners/wgpu
cargo run -- --shader Sky

Skyシェーダーが実行されると、美しい空のレンダリングが表示されます。

Screenshot 2025-04-12 at 20.05.16.png

他のシェーダーも試してみることができます:

# 最もシンプルなシェーダー
cargo run -- --shader Simplest

Screenshot 2025-04-12 at 20.17.56.png

# マウスインタラクション可能なシェーダー
cargo run -- --shader Mouse

Screenshot 2025-04-12 at 20.05.57.png

サンプルコードを見てみる

最もシンプルなシェーダー

examples/shaders/simplest-shader/src/lib.rs にある最もシンプルなシェーダーのコードを見てみましょう:

#[spirv(fragment)]
pub fn main_fs(output: &mut Vec4) {
    *output = vec4(1.0, 0.0, 0.0, 1.0);
}

#[spirv(vertex)]
pub fn main_vs(
    #[spirv(vertex_index)] vert_id: i32,
    #[spirv(position, invariant)] out_pos: &mut Vec4,
) {
    *out_pos = vec4(
        (vert_id - 1) as f32,
        ((vert_id & 1) * 2 - 1) as f32,
        0.0,
        1.0,
    );
}

このシェーダーは非常にシンプルで、フラグメントシェーダーは赤色の出力を行い、頂点シェーダーは画面全体を覆う三角形を生成します。#[spirv(...)] アトリビュートによって、関数がシェーダーステージとして機能するように指定されています。

空のシェーダー

examples/shaders/sky-shader/src/lib.rs には、より複雑な空のシェーダーが実装されています。

#[spirv(fragment)]
pub fn main_fs(
    #[spirv(frag_coord)] in_frag_coord: Vec4,
    #[spirv(push_constant)] constants: &ShaderConstants,
    output: &mut Vec4,
    // ...
) {
    let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y);
    let mut uv = (frag_coord - 0.5 * vec2(constants.width as f32, constants.height as f32))
        / constants.height as f32;
    uv.y = -uv.y;

    let eye_pos = vec3(0.0, 0.0997, 0.2);
    let sun_pos = vec3(0.0, 75.0, -1000.0);
    let dir = get_ray_dir(uv, eye_pos, sun_pos);

    // Preethamの空モデルを評価
    let color = sky(dir, sun_pos, sun_intensity_extra_spec_const_factor);

    *output = tonemap(color).extend(1.0)
}

このシェーダーはPreethamの空モデルを実装し、リアルな空をレンダリングします。光の散乱とトーンマッピングを計算して美しい空の表現を実現しています。

Rustの強みを活かしたGPUプログラミング

Rust GPUの魅力は、Rustならではの機能をGPUプログラミングに持ち込める点です:

Rustの特徴を活かしたGPUプログラミング

実際のサンプルコードからわかるように、Rust GPUは以下のようなRustの特徴をGPUプログラミングに活かしています:

// マウスシェーダーにおけるトレイトの活用例(examples/shaders/mouse-shader/src/lib.rs)
pub trait Shape: Copy {
    fn distance(self, p: Vec2) -> f32;
    
    fn union<S>(self, other: S) -> Union<Self, S> {
        Union(self, other)
    }
    
    fn intersect<S>(self, other: S) -> Intersect<Self, S> {
        Intersect(self, other)
    }
    
    // ...
}

マウスシェーダーでは、トレイトを使って図形の操作を抽象化しています。これはRustの型システムの強みを活かした実装例です。

また、CPUとGPU間のデータ共有も簡潔に行えます:

// SharedConstantsの例
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ShaderConstants {
    pub width: u32,
    pub height: u32,
    pub time: f32,
    // ...
}

まとめ

プロジェクトはまだ初期段階であり、リポジトリのREADMEにも記載されているように、本番環境での利用は推奨されていませんが、サンプルシェーダーの実行などの実験的な用途には使えることを確認できました。

興味のある方は、ぜひRust GPU公式リポジトリをチェックしてみてください。

参考リンク

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?