グラフィックスプログラマーになる方法
(gpuopen.com)- グラフィックス入門は、唯一の正解があるというより、既存の知識・学習スタイル・ハードウェアによって変わるものであり、AMD Game Engineeringチームは初心者にとってより親切な出発点が必要な場合があると考えている
- グラフィックスプログラミングは、CPU側のC++コードとGPU側のシェーダーコードを一緒に書き、それをDirectX・Vulkan・OpenGLのようなグラフィックスAPIでつなぐ構造
- 2023年時点での主な選択肢は、OpenGL・DirectX 11・WebGLのようなレガシーAPIと、Vulkan・DirectX 12・Metal・WebGPUのような現代的な明示的APIに分かれる
- レガシーAPIは学びやすい一方で、ドライバーとランタイムの複雑性が増しており、現代APIはより多くのコードとGPUへの理解を求める代わりに、より大きな制御権を与える
- 最初はOpenGL・WebGL・ゲームエンジン・Shadertoyのようなシンプルな環境から始めることができ、C++とGPUパイプラインへの理解が十分なら、Vulkan・DirectX 12に直接入ることもできる
グラフィックスプログラミングの基本構造
- グラフィックスプログラマーが主に使う言語についての短い答えはC++
- 実際の作業は、CPUで実行されるホストコードと、GPUで実行されるシェーダーコードを一緒に書く形になる
- ホストCPUコードは通常C++で書かれる
- GPUコードはHLSLまたはGLSLのような高水準シェーディング言語で書かれる
- グラフィックスAPIは、CPUコードがシェーダーと必要なデータ・メタデータを使ってGPUに処理を依頼できるようにする接続点
どのグラフィックスAPIから始めるべきか
- 2023年時点で、PCゲームと3Dアプリケーションでよく使われるAPIは大きく2種類に分かれる
- レガシーAPI: OpenGL, DirectX 11, WebGL
- 現代的な明示的API: Vulkan, DirectX 12, Metal, WebGPU
- OpenGL、DirectX 11、WebGLはGPUをプログラミングする歴史的なアプローチに基づいており、プログラマーの立場ではよりシンプルで学びやすい
- シンプルさにはコストが伴う
- 時間が経つにつれて、ドライバーとランタイムの内部実装が複雑になった
- ホスト側のボトルネックや、GPUベンダーが作成しなければならない複雑なドライバーの負担につながった
- AMDのMantleは2013〜2016年の間にPCで登場し、AMD GPUとEA DICEとの協業を通じて、より低レベルなGPUアクセスと薄い抽象化を提供した
- Metalは2014年にAppleプラットフォームに登場し、DirectX 12とVulkanは2016年に登場して、GPUプログラミングをより低レベルかつ明示的な方法で扱うようになった
やさしいAPIと明示的APIの学習上のトレードオフ
- VulkanとDirectX 12は、プログラマーがGPUに望む処理をより明確に指定する必要があるため、初期の負担が大きい
- その代わり、より多くの制御権を得られ、GPU処理の性能と効率を高める機会も増える
- 最初の三角形を描く例を見るだけでも、API間の違いが見える
- OpenGLまたはDirectX 11では、約10行ほどで最初の三角形を描ける
- VulkanとDirectX 12では、それよりはるかに多くのコードが必要になる
- OpenGLとDirectX 11は多くの詳細を隠して、生産的なグラフィックス作業に素早く近づけてくれるが、GPUの動作が魔法の箱のように見えることがある
- VulkanとDirectX 12は、初期段階から低レベルの知識とGPUへの理解を求める代わりに、各コード行がGPUで起きることをより明確に示す
入門ルートの選択肢
- AMD Game Engineeringチーム内でも、DX12やVulkanで10代や初心者が始めるには厳しいという意見と、条件が合えば可能だという意見が併存している
- OpenGLは最新性や関連性は低くなったが、基礎を学ぶには今でも十分だと評価されている
- WebGLはグラフィックスパイプラインを理解しやすい出発点になり得る
- WebではC++なしでJavaScriptによりリアルタイムグラフィックスを扱える
- WebAssemblyを使えば、ブラウザー上でC++によりグラフィックスを動かすことも可能
- WebGPUは現代のグラフィックスAPIにより近い概念を提供しながらも、低レベルの詳細はそれほど要求しない場合がある
- 複雑なコードを書き始めると、まださまざまな問題に遭遇する可能性がある
- プロトタイピングや学習・教育用APIとしては有望
- ゲームエンジンから先に始める方法も可能
- Unreal EngineはPCゲームで大きな比重を占めている
- Unityも一般的な代替手段
- Godotのような、より小さくシンプルなオープンソースエンジンもある
- Unityで最初のレンダリング授業を行う学校もあるが、学生がなぜ低レベルの知識を学ぶ必要があるのかを理解できないリスクがある
- 明示的APIから始めるなら、現代のグラフィックスパイプラインとGPUハードウェアがそれを実装する大きな流れをよく知っているか、その理解を並行して身につける意志が必要
推奨学習資料と次のステップ
- LearnOpenGL: C++で実際のAPIを使ってグラフィックスプログラミングを学ぶのに適した初心者向けサイト
- Scratchapixel: 多くのコードを書かずに、レイトレーシングのような概念がどのように動作するかに集中できる
- Udemy: 入門者向けの講座を探す場所として活用できる
- Rastertek: OpenGL・DirectX 11チュートリアル
- Ray Tracing in One Weekend: ある程度コーディングできるなら、自分で作りながら学ぶアプローチに適している
- A trip through the graphics pipeline: 2011年の記事なので明示的API以前の資料だが、GPU観点でのハードウェア・ソフトウェア概念は今でも適用できる
- learn wgpu: LearnOpenGLに似たスタイルのWebGPU学習サイトで、まだ作業中という性格がある
- Your first WebGPU app: WebGPU入門資料として見られる
- Shadertoy: グラフィックスAPIを直接扱わずにシェーダーを書けるため、よりシンプルな出発点になる
- Vulkan Tutorial: VulkanやDirectX 12を学ぶ際には、コピー&ペーストを恐れないことも重要だという文脈で一緒に扱われている
- まだ言語やAPIエコシステムを決められていないなら、複数のアプローチを試してみて、自分に合った方法を使い続ければよい
1件のコメント
Hacker News のコメント
初心者は「どのツールを使うか」から始めるより、一歩引いてまず「何を作りたいのか」を問うほうがよい。
学び始めるときも、最終的な成果物を見失ってはいけない。最近のコンピュータグラフィックスには、画面にピクセルを描くまでのさまざまな段階を抽象化してくれるツールがあまりに多いので、最初から低レベルのコードで苦労した末に、自分が進みたい分野では Unity、TouchDesigner、threejs、After Effects だけを使い、C++ はほとんど使わないのだと後から気づくこともある。
もちろん、下の層でどう動いているかを学ぶことには大きな価値があるが、それを最初にやるのは遅いアプローチだと思う。業界に入り、ゲームエンジンやビジュアルプログラミングのような抽象化ツールを通じて内部動作の概念をつかむほうが、学習は速くなる。
C++ と OpenGL を苦労して学ぶのに何年も費やし、ノーコード的なアプローチを受け入れられなくさせたサンクコストと長く戦ってきた立場からの話だ。結局、作りたいものを作る助けにならないなら、この道に時間を浪費しないほうがいい。
Mark Kilgard のように教科書を書いたわけではないが、ドライバレベルから適合性テスト、性能チューニング、ゲームやアプリケーションのコード、主要なデスクトップ・モバイルプラットフォームまで、API のさまざまな層を深く扱ってきた。
ではそれがどこにつながったかというと、実のところあまり遠くへは行かなかった。今では OpenGL を気にするところはほとんどなく、主要 OS ベンダーのうち2社が最終的に見放したことで、事実上死んだ技術に近い。「HN Who's Hiring」で OpenGL を検索してみれば分かる。
Direct3D、Vulkan、Metal のような別のグラフィックス API を学び直すこともできただろうが、低レベルのグラフィックスコードは今やエンジンが抽象化してくれるため、そういう人材を必要とする場所は多くない。低レベルのグラフィックスドライバ人材を必要とする会社も世界中で多くて5〜6社なので、キャリアを制限するニッチになってしまう。
マシンのより小さな部分に集中すればするほど、それをキャリア全体にするには世界的な専門家でなければならない。次の John Carmack になる計画でないなら、深く掘るより広く進むことを勧める。
YouTube には、何か面白いものを作ることに集中するより、技術スタックを次々に学ばせる初心者向けプログラミング動画があふれている。その結果、履歴書を埋めるために、ウェブページに数行のテキストをレンダリングするだけでも、カーゴカルト的に複雑なルーブ・ゴールドバーグ・マシンを作ることになる。
大学時代に1学期だけグラフィックスプログラミングを少しやったが、十分に複雑だったので、「何を作りたいのか」への妥当な答えは「黒い背景に緑の三角形をレンダリングする」くらいだった。そこから四角形、キューブ、球、アニメーションする球、跳ねるボールへ進むのは自然な流れで、目標に集中させてくれる。だから、上の質問に「レイトレーシング照明とサブサーフェス・スキャタリングが入った一人称シューティング」と答えるような間違いも避けるべきだ。
跳ねるボールの最初のバージョンのコードは本当にひどいものになるだろう。それでも問題ない。時間がたつにつれ、最適化して改善する方法が分かってくる。そしてデザインパターンを自分で発見することほどわくわくすることはない。新しいテーマの本を読んでいて、「あれ、これもう自分がやっていることだ!」と感じるようになる。
もちろん、ゲームプレイプログラマーのような別の役割で入り、そこからグラフィックスへ少しずつ移ることもできるし、そのほうが簡単かもしれない。だが最終的にグラフィックスプログラマーの役割には C++ が必要だ。
前で述べられているのは、グラフィックス関連の作業を早く生産的にこなしたい人に近く、グラフィックスプログラミングそのものではない。
ツールは時間がたてば変わるし、経験上、優れたエンジニアは1つだけを深く掘るより、複数のツールをさまざまな熟練度で扱えることが多い。
実際の職場でその仕事をしなくなったとしても、多くの理論知識と複雑なアルゴリズムの訓練を得られる。
グラフィックスは応用数学の経験も多く与えてくれる。数学ができる人を切実に探している分野は本当に多い。以前の職場である CNC 機械ソフトウェアでも、金属ブロックに特定の形を作るためにドリルを制御するのに必要な数学をプログラムできる人が必要だったが、見つけるのが本当に難しかった。一方でクラウド DevOps エンジニアは高価ではあっても比較的簡単に見つけられた。
グラフィックスプログラマーなら、グラフィックスがどのように動くのかについて、全体的にバランスの取れた理解があるほうがよいと思う。単純なプログラミングや API 知識を超えて、良いグラフィックスプログラマーなら回転・ビュー・投影行列、一般的なベクトル数学、シェーダープログラミング、Voronoi・SDF・Perlin のような手続き型プリミティブ、画像合成、フォワードレンダリングとディファードレンダリング、さまざまなサンプリング手法、影と照明の技法を知っているべきだ。
また、アートパイプラインがどのように動き、3D アプリからデータをどう取り出すのか、プロファイラやデバッガを気軽に使う方法、SIGGRAPH 論文を読む能力、空間分割とボリューム階層の技法、簡単なレイトレーサーの実装、スプライト・三角形・n角形といったプリミティブの理解、パーティクルやシミュレーションの経験も必要だ。
モデルが作られるごく基本的な流れ、つまりモデリング → スキニング/リギング → アニメーション → テクスチャリング程度と、それをファイルに書き出す大まかな方法は知っている。だがこの部分は、アーティストと一緒にやらなければまともな実践経験を得るのが特に難しい。
趣味でグラフィックスプログラミングをしていて、ここで挙げられていることの多くを学んできたが、職務経験がないため面接の機会がほとんど来ない。
Pikuma の Graphics From Scratch 講座をおすすめする。最初にやることは SDL を使って
set_pixel関数を書くことで、その後の過程はすべて自分でコードとして実装するすべての 行列演算、すべての頂点変換、すべての三角形ラスタライズまで自分で書き、各ピクセルがどの色であるべきかを計算する
https://pikuma.com/courses/learn-3d-computer-graphics-progra...
https://www.gabrielgambetta.com/computer-graphics-from-scrat...
その後 WebGPU を数日で習得できたが、この講座で得た理解がなければ無理だったと思う
動機づけが必要なら、講座の最後で作るレンダラーを Wasm にコンパイルしたデモを作ってみた: https://rmshin.github.io/3d-renderer-wasm
90年代のように
putpixelスタイルの SDL コードから始めるべきか、それとも Shadertoy から始めるべきか? 基本的な行列数学はもちろん常に重要だ。だが三角形ラスタライズはどう教えるべきだろう? スキャンラインを経ずに同次座標と四分木へ進んでもよいのだろうか?本当に Phong シェーディングを教えるべきなのか、それともすぐに BRDF へ進めるのか? ある部分は有用な技術というより「昔ながらの小技」を教えることになってしまうかもしれない
今日では統計とサンプリングのほうがはるかに重要だ。グラフィックスは年々より数学的になっていると信じている。だから数学を学び、数学を教えるべきだ
その中でもこの GitHub リポジトリは本当に強くおすすめする: https://github.com/ssloy/tinyrenderer/wiki/Lesson-0:-getting...
視覚的に学ぶタイプなら、このチャンネルも宝の山だ: https://www.youtube.com/watch?v=ih20l3pJoeU
Shadertoy でシェーダー作成を通じてグラフィックスを学べる。多くのグラフィックスプログラマーがそこで始めている
少しだけ宣伝すると、VS Code でのシェーダー作成、SDF、レイマーチング、ノイズ関数、フラクタルブラウン運動などを扱うチュートリアルを10本以上作った
https://github.com/suboptimaleng/shader-tutorials
もちろん Inigo Quilez、The Art of Code、SimonDev、Acerola といった巨人たちの肩の上に立っている
DX/VK/OGL から始めなくても、グラフィックスプログラマーになる道は本当にたくさんある。C++ を必ず使う必要もない。3Blue1Brown が Python で作る驚くべき 3D グラフィックスを見ればよい
ゲームエンジンを使いたいなら DirectX や Vulkan を学び、ブラウザーアプリケーションを作りたいなら WebGL を学べばよい
ただし、そうした API は重く、それ自体がグラフィックスについて多くを教えてくれるわけでもない。グラフィックスの概念を学びたいなら、好きな言語でラスタライザーとレイトレーサーの両方を自作してみるのがよい
Vulkan や DirectX を苦労して掘り下げるより、ずっと楽しいグラフィックスライブラリやコーディング環境もたくさんある。Processing は素晴らしいし、Python ベースの PlotDevice.io やその前身の NodeBox、DrawBot も見る価値がある。ShaderToy はシェーダー作成やレンダリングを多く学べる別の場所で、始めやすい。JavaScript にも選択肢やライブラリが多い。こうしたものは初心者にとってはるかに取り組みやすく、動機づけにもなりつつ、好奇心のある学習者が望むだけ深く進めるだけの力と柔軟性を与えてくれる
この記事がトップページに上がっているので、グラフィックスプログラミング業界で実際に使われている資料を載せておく。ちなみに私は著者の一人です: https://raytracing.github.io/
上の記事の “Useful Websites” にも含まれている
グラフィックスはいまやあまりに広く、誰にでも合う単一の学習法はもはや存在しない。グラフィックスを学びたいならメンターを見つけることをおすすめする
ゲーム開発者だが、専門のグラフィックスプログラマーではない。仕事では現代的なグラフィックス API と GLSL シェーダーを使っているが、最近13歳の子どもが Scratch や Python から C++ を学びたがるようになったので、1999年からコンピューターに残っていた古い OpenGL 1.2 DLL を引っ張り出し、
glutとglbegin/glvertex/glend方式の即時モードコードから書かせるのが最善だと判断した現代の API に必要なあらゆる設定に耐えるより、はるかに楽しい。子どもは Voronoi 図のような計算幾何のほうに興味があるので、グラフィックス API は目的のための手段にすぎず、派手なシェーダーやライティングは今は重要ではない。C++ と古い OpenGL の性能は Scratch よりおよそ千倍速いので、今の学習段階に合った良い地点を見つけたように思う
簡素化された OpenGL 1.2 API を使っても、C++ と OpenGL を同時に理解しようとするのはかなり意欲的な学習量なので、その単純さが精神的に扱えるものにしてくれている。今のところ順調で、子どもはそこそこの marching squares デモを作り、私は実行時にパラメーターを調整できる IMgui メニューを付けるのを手伝った。なかなか楽しかった
このWebサイトが正確に何を問うているのか、よく分からない。リギングをしたいのか? テクスチャリング? モデリング? ドライバ作成? GUI制作? Webサイトのアニメーション? グラフィックスツール? シェーダー? 2D写真エンジン? 2Dゲーム? 3Dゲーム? 手続き型スクリプト? グラフィックスコードの最適化?
「コンピュータグラフィックス」の下には何百もの分野がある。だがこのWebサイトは、その中でもごく小さな一角であるグラフィックスSDKプログラミングに焦点を当てている
グラフィックスプログラマーなら、ゲーム、3D、2D、ツール、シェーダー、最適化全般を扱えることが期待される
私もその道の途中にいる。2年前、いくつものチュートリアルやYouTube動画をなぞって、初めての3Dエンジンを作った
とても単純だが、単純なものが好きだ。今はこのエンジンで都市建設ゲームを作っている。行列と外積を使って要素を操作する方法を学ぶのは本当に楽しい
https://www.youtube.com/watch?v=cvyrfPUpyp0