3Dグラフィックスの基礎知識
概要
シェーダーを書く以前に、どうやって動いているのかの知識がなかったので勉強した。 まだ実際に触っていない知識も多いので間違っているかもしれない。
シェーダーとは何か?
GPUで実行されるプログラム。レンダリングパイプラインの処理の一部。
レンダリングパイプラインとは?
3Dグラフィックスのプログラムが画面の描画(レンダリング)を行う際の、一連の処理のこと。 3D空間上にどのような形状の物が置いてあるか、カメラはどこにあるか、光はどこから当たっているかなどの情報を与えることで、 最終的にモニター画面に表示するような2Dの画面を作ることができる。
レンダリングパイプラインで実行される処理
1. 3Dモデルの情報を用意
入力となる情報を用意する。3Dモデルの情報とは、主に形状(ポリゴンの情報)と、置いてある座標のことを指す。 Unityで言えば〇〇レンダラーというコンポーネントが付いたオブジェクトをヒエラルキー上に配置すること。
2. 頂点処理(頂点シェーダー)
※ここからはGPUが実行する GPUはCPUに比べ、Inputが異なる同じ処理を並列に実行することが得意 これ以降の処理でInputとなる頂点やピクセルへの処理はまさにそのような並列処理だらけなのでGPUで実行 (そもそもGPUはレンダリングでのCPUの不足を補うために作られたので、得意なのは当然)
頂点シェーダーの処理は主に二つある。 1つは座標形をローカル座標系からワールド座標系へと変換すること。(ここの詳細は省略) もう1つは頂点単位の陰影処理を実行すること。 3D空間上には光源となる物体が存在しており、そこから受ける光を表現して明るくしたり影をつける必要がある。 ポリゴンの法線ベクトルを用いて陰影の具合(光がどの程度当たっているか)を計算し、結果をポリゴンの頂点に格納する。 (頂点には自分がどんな色かという情報がもともと入っているため、陰影の具合でそれを加工する)
3. テッセレーション
ポリゴンの分割や形状変更ができる。比較的新しい機能で、ローポリとハイポリを場面によって使い分けるLODシステムに使われる。
4. ジオメトリシェーダー
頂点の増減ができる。ポリゴンは頂点からできているので、ポリゴンを増やすことにもなる。 (1で用意した情報を勝手に変えることができる) 細かい毛など、モデリングが手間なものをシェーダーで作ってしまおうという用途だと思うが、ちゃんとした応用例を調べれていないので詳細は不明。 1つ目のテッセレーションもそうだが、これがなければ動かないというものではない。(PS2時代くらいの昔はなかった)
5. カメラ空間への展開&クリッピング
これまでは3D空間に存在する全てのポリゴンに対して処理を行なったが、実際には画面に表示するのはカメラに写っているのものだけとなる。 そのカメラに映る範囲=カメラ空間であり、カメラの位置や向きから空間内にいるポリゴンの一覧を見つける。(カメラから見て「裏」になっているポリゴンは対象外とする) そのあとは不要なポリゴンの情報は捨て、中途半端なもの(ポリゴンの一部だけが範囲内)はポリゴンを分割する(クリッピング)。
6. ラスタライズ処理
残ったポリゴンが、カメラから見た視点(2D)ではどこに位置するのかを計算する(2Dのピクセル情報に紐づける)。 この処理と5の処理はあまり改善やセッティングの余地がなく、勝手に実行されるイメージ。
7.ピクセルシェーダー
ここが一番処理負荷が大きい部分であり、また色々とカスタマイズ可能な部分。 シェーダーと言った時はたいてい頂点シェーダーかピクセルシェーダーのことを指す、らしい。 主な処理は頂点シェーダーと同じく陰影の処理と、テクスチャの処理。 陰影の処理はピクセル単位のため、頂点シェーダーよりもなだらかな陰影や綺麗なハイライトが出せるらしい。(Per Pixel Lighting)
8. レンダーバックエンド
深度テスト(複数の描画対象物が同じピクセルにいる場合に、どっちを前にするか?を決める)と、 アルファテスト(透明度の判定)を行う。 ポストプロセスもここで実行する。
補足情報
レンダリングパイプラインで実行される処理は世代やGPUによって異なる場合がある。 また最近はここで書いた手法とは異なるレンダリング方法として、レイトレーシングというものが注目されている。 レイトレーシングはより現実に近い光の表現ができるが、処理がとても重いため、ゲームなどのリアルタイム処理ではまだ実用はできていないが、 CG作成などでは使われているらしい。
参考になった本
感想、今後
すごく簡単で全て文のため自分の見直しにしか役に立たなさそうだが、一通り理解できたことを確認できた。 原理が分かってスッキリしたので、今後は実際にどうシェーダープログラムを書くのかを勉強したい。
シェーダー少しだけ触ってみた
背景
slackコミュニティでシェーダー芸というものを知り、簡単そうなので少しだけ触ってみた。 ゲーム製作のためにはある程度は理解しておきたいということもあったので。
やったこと
Unityのシェーダー講座を3種類くらいみた(youtube)
実際にGSLSで波動っぽいシェーダー書いてみた
twiglで公開した(URL消えてしまった。。。)
成果
twiglで作ったもの:
シェーダーグラフを使ったゲーム https://unityroom.com/games/n_block_break
GLSLはC言語に非常に似ている言語だが、一部特殊なものがあった。
Swizzling
ベクトルにアクセスするために使う演算子。
(例)
vec4 someVec; someVec.x + someVec.y;
初めは構造体やクラスにアクセスするのと同じだと思ったが、実は違っていて例えばこんな風にかける
vec4 someVec; someVec.wzyx = vec4(1.0, 2.0, 3.0, 4.0); // Reverses the order. someVec.zx = vec2(3.0, 5.0); // Sets the 3rd component of someVec to 3.0 and the 1st component to 5.0
https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)#Swizzling
ドットの後に続けてメンバ(x,y,z,w)を好きな順番で、1-4の好きな数書くことができる(重複も可能) そして書いた数の次元のベクトルと同じように扱える。上記例ではsomeVecは4次元ベクトルだが、 someVec.zxには2次元ベクトルを代入できる。
今後
もっと色々な表現をできるようにする
URPでシェーダーをかけるようになる(あえてシェーダーグラフを使わない)https://tatsuya-koyama.com/devlog/unity/urp-colorful-shader/
レイマーチング使って表現してみる
SwizzlingみたいなのGLSLの記法をまとめてQiitaに記事を書くのもいいかも
ドメイン駆動設計に入門した
背景
やったこと
- 「ドメイン駆動設計入門」を1冊読み切った
- 一部不明点をネットで調べた情報で補足した
Input↓
成果・感想
ドメイン駆動設計というものを行うための思想や、パターンを理解できた。
本自体は非常に読みやすく、ドメイン駆動設計とは何者なのか、を教えてくれる。
しかし、どういったときに使うべきか、なぜメリットがあるのか、がはっきり分からなかったためそこは上記のスライドがとても参考になった。
得たもの:大まかな思想を理解できた
- 作りたいものを構成する要素をドメインと呼び、それらをプログラム上で忠実に再現する
- そのため、作りたいものへの深い理解が必要となる
- ドメインをシステムに落とし込む(再現する)ための手法=ドメイン駆動設計
-
ドメインは自分が何者なのかコードで語る(システム全体を知らない人が見ても、何を表現しているのか分かる 自己文書化と呼ばれていた)
得たもの:値オブジェクトやエンティティなどのパターンの概要を理解できた
- 値オブジェクト...プリミティブ型の拡張 システム固有な値を表現し、不変
- エンティティ...値を持つオブジェクトで可変 ただし区別ができる
- ライフサイクルを持つものはエンティティを使う サービスのユーザー情報が分かりやすい(値が可変・同じ氏名でも区別できる・登録〜削除のライフサイクルがある)
- ドメイン以外に、それらを使ってユースケースを実現する部分は必要(アプリケーションと呼ぶ)
ドメイン駆動設計を使う目的
-
ドメイン化はモデル化 使用者を巻き込んで一緒に考えて直していく
- 業務で「知りたいこと」「やりたいこと」をドメインの単位にする
-
モデル化したものをそのままソフトウェアに組み込めるように設計する
-
その設計もイテレーション前提に作る モデルは何度も修正される前提
-
やりたいことからブレず、また変更に強いソフトウェアになる ←これが目的