2 ポイント 投稿者 GN⁺ 2 시간 전 | 1件のコメント | WhatsAppで共有
  • OpenGL・Vulkan・Metal・DirectXの内部動作を理解するため、外部グラフィックライブラリなしでソフトウェアレンダラーをゼロから実装する
  • 三角形メッシュとテクスチャで構成された3Dモデルを画像に変換し、GUIやGPUアプリケーションの実装は扱わない
  • 完成コードは約500行で、学生は通常10〜20時間かけて動作するレンダラーを作り始める
  • RGB・RGBA・グレースケールをサポートするTGA処理クラスと単一ピクセルの設定機能だけが与えられ、線分や三角形の描画は自分で実装する必要がある
  • 完成コードをコピーするのではなく自分で書くことで、レンダリングの概念を理解し、3Dライブラリの内部動作も把握できる

レンダリングパイプラインを自分で作るプロセス

  • 最新の3Dグラフィックライブラリの構造を緩やかになぞりながら、レンダリングパイプラインの動作原理を学ぶ
    • GPUアプリケーションの書き方ではなく、ソフトウェアレンダラーで内部動作を再現する
    • 入力は三角形メッシュとテクスチャで構成された3Dモデルで、出力はレンダリングされた画像
    • グラフィックインターフェースなしに、プログラムが画像ファイルを生成する
  • 外部依存を減らすため、シンプルな画像形式であるTGAを使用する
    • 最初に提供される機能は、画像の読み込み・保存とピクセル1つの色設定だけ
    • 線分や三角形を描く組み込み関数はなく、すべて自分で書く必要がある
  • 最初の例では、64x64のRGBフレームバッファを作成し、3つの座標のピクセルを白に設定してからframebuffer.tgaとして保存する
    • 色の値はBGRA順で指定する

コードのビルドと実行

git clone https://github.com/ssloy/tinyrenderer.git &&
cd tinyrenderer &&
cmake -Bbuild &&
cmake --build build -j &&
build/tinyrenderer obj/diablo3_pose/diablo3_pose.obj obj/floor.obj
  • 実行結果は**framebuffer.tga**に保存される
  • 完成コードは約500行だが、自分で実装するプロセスが概念理解に不可欠なため、提供コードをそのまま使う方法は推奨されない

1件のコメント

 
GN⁺ 2 시간 전
Hacker News のコメント
  • 数か月前、Rustで ソフトウェアレンダラー をLLMなしで自力実装し、簡単なゲームやピクセル化シェーダー、懐中電灯の縁の色収差効果まで追加した
    https://github.com/kshitijl/tinyrenderer-rs
    リポジトリには、開発過程や笑える視覚的バグを収めたスクリーンショットが多い。レンダリングの原理だけでなく、現代のCPUは非常に高速で、シングルスレッドCPUレンダラー でも派手な特殊効果のあるインタラクティブな3Dゲームを動かせるという点を大いに学んだ
    • ソフトウェアレンダラーなのに、なぜ wgpu に依存しているのか気になる
    • Rustでゲームロジックを書くとき、ECS まで追加する必要があるのか気になる
  • この資料とJohn Vinceの Mathematics for Computer Graphics は、私の ソフトウェアレンダラー を作るうえで不可欠だった
    LLM以前だったので少なくとも2か月かかり、その大半はコンピュータグラフィックスの数学を理解し、Cのセグメンテーションフォルトを追跡することに費やした
    • 数か月の間、1日に何時間くらい作業していたのか気になる
  • FoleyとVan Damの本は、今でもこの分野の代表的な参考書なのか気になる。2013年に改訂されたが、私は2D中心の 1982年版 のほうになじみがあり、当時はコンピュータグラフィックスの定番のような本だった
    • 長いこと開き直しておらず、私にとっては歴史的価値のある独特な 百科事典 に近い
      このGitHubの講義ノートのほうが、概念を復習するにはよかった。リポジトリのコードスタイルは好みではなく、旧式のラスタライザーも過度に単純で非効率だが、それでもFoleyの本よりは読みやすいと思う
    • 私も第2版で学び、2013年の最新版も持っているが、無難な内容だ
      版が変わるにつれて使用言語もPascalからC、CとC++へと発展し、最新版にはC#も少し入っている。新しい概念はいくつも抜けているが、それでも 価値ある内容 は多いと思う
  • ソフトウェアレンダラーのチュートリアルのどれか一つくらいは、三角形クリッピング をきちんと扱ってほしい。実用的なレンダラーなら、基本的なシーンでもジオメトリがビュー錐台と交差するときは必ず処理しなければならないが、個人的には最も難しい部分だ
    • このトピックを丸ごと1章で扱っている: https://gabrielgambetta.com/computer-graphics-from-scratch/11-clipping.html
    • 非常に大きな三角形の属性補間が重要な場合にだけ三角形クリッピングが必要で、素早く破棄する方法と プリミティブを合成 する方法の2つがある
      錐台クリッピングはローカルタイル内の点選択で処理でき、プリミティブ合成は逆変換したクリッピング矩形を重心座標系で扱うほうが簡単だ。倍精度や固定小数点で丸め誤差を制御でき、核心となる難点は新しい頂点のZと1/Zの値を再生成することだ。遅延属性合成ラスタライザーなら、残りは自然にパイプラインを通過し、OpenSWR.orgのオープンソース実装で例を見ることができる
    • 私もいつも「クリッピングを実装しなければならない」という段階で詰まっていたが、結局それほど苦労せず動くコードを書き、後になってそれが Sutherland–Hodgmanアルゴリズム を独自に再発見したものだと分かった
      最大の心理的障壁は、射影空間と同次座標になじみがないことだ。クリップ空間の6つの平面は x = ±wy = ±wz = ±w と単純で、各多角形の辺を順にたどりながら両端点の内外を判定し、境界との交点の位置と頂点属性を線形補間すればよい。この処理をすべての平面に順番に適用すると、三角形は最大9頂点の凸多角形になり、簡単に再三角形分割できる。アウトコード(outcode) を事前計算すれば、完全に内側または外側にある三角形のクリッピングをスキップできる
      論文: https://dl.acm.org/doi/10.1145/360767.360802
  • 現代の環境には、実質的に 純粋なC++ というものは存在しない。1980年代のコンピューターのようにレジスターやVRAMへ直接書き込んで映像を出力することはできず、結局は分厚いAPI・ドライバー・ファームウェア層の上で大量のコードに依存することになる
  • 1990年代へのノスタルジーからソフトウェアレンダリングに再挑戦しており、2D風の CLUTバンク と、現代的な区間分類三角形・重心座標の手法を混ぜている
    固定パイプライン形式を保てば、かなり単純な描画関数でも驚くほど多くの三角形を処理できる
  • macOSの OpenMP処理バグ を見つけ、このリポジトリに本当に久しぶりの初PRを提出した