Open9

wgpuに入門する (地形チャンクの可視化)

ぺるきぺるき

概要

巨大な地形データを表示するとき、チャンクやタイル (ここでは呼称をチャンクに統一) に分けておいて、視野にあるものから抽出してレンダリングする手法がよく用いられる
(Minecraftが代表例、またJSの地図ライブラリにも見られる)

これを自力で実装するきっかけができたので、作ってみようと考えている
それも以前、Three.jsで作ったことがある:

https://x.com/PerukiFUN/status/1815010577213018173

一方でThree.jsだと、グラフィックスを扱うのにJS/TSを使い続けなければならない
空間系の計算ライブラリの数や並列処理の環境など、不足が多く、これ以上続けるのはパフォーマンス的にも開発効率的にもしんどい

そこで、RustでWebGPUを扱える良さげなものを見つけた

https://wgpu.rs/

目標

wgpuを用いて、チャンクベースの地形データ表示 & 拡張の基盤を実装
パーリンノイズで試す
(表示は最低限で十分、ワイヤーフレームで構わない)

ぺるきぺるき
use winit::{
    event::*,
    event_loop::EventLoop,
    keyboard::{KeyCode, PhysicalKey},
    window::WindowBuilder,
};

fn main() {
    env_logger::init();
    let event_loop = EventLoop::new().unwrap();
    let window = WindowBuilder::new().build(&event_loop).unwrap();

    let _ = event_loop.run(move |event, control_flow| match event {
        Event::WindowEvent {
            ref event,
            window_id,
        } if window_id == window.id() => match event {
            WindowEvent::CloseRequested
            | WindowEvent::KeyboardInput {
                event:
                    KeyEvent {
                        state: ElementState::Pressed,
                        physical_key: PhysicalKey::Code(KeyCode::Escape),
                        ..
                    },
                ..
            } => control_flow.exit(),
            _ => {}
        },
        _ => {}
    });
}

チュートリアル通りやってみたが、Windowが作られない

ぺるきぺるき

実行環境をデスクトップPCに変更した場合うまく行った
ラップトップでも開発したいので、後々調査の必要あり

追記

原因はX11とWaylandの環境差異だった

Note: Windows don’t appear on Wayland until you draw/present to them.

http://rust-windowing.github.io/winit/winit/platform/wayland/index.html

Waylandではなにか描画しないとウインドウも表示されないのが仕様のよう。ちょっと罠感ある

ぺるきぺるき
[dependencies]
log = "0.4.22"
env_logger = "0.11.4"
winit = "0.29.15"
wgpu = "22.0.0"

dependenciesは以上の通り

https://sotrh.github.io/learn-wgpu/beginner/tutorial1-window/#what-crates-are-we-using

Note that we are using version 0.29 of winit. This is not the most recent version. The reason for this is version 0.30 and beyond include breaking changes that will require a lot of code changes.

winit0.30でAPIが大きく変更されたとのことで、今は0.29で進め、適宜読み替える

ぺるきぺるき

fn render(&mut self)

  • 描画に用いるSurfaceTextureをSurfaceから取得
  • SurfaceTextureからTextureView`を作成
    • WIP: なぜこれを挟むかはまだ理解できていない
  • CommandEncoderを通してGPUに与えるコマンドを作成
    • ここではbegin_render_passから、画面全体を単色で描画する内容を読み込む
  • Queueにコマンドを投げ実行
  • SurfaceTextureを更新し描画

ここにきてWaylandでも動くようになった