shader
実用的な応用:反射モデル
全体の流れ
https://gyazo.com/18a5be15bfdc9e0db2ae021a6e83fbf7
学習リソース
PCのGPUでは固定パイプラインを拡張する目的でリアルタイムシェーダーが利用されるようになり、頂点変換とピクセル色の決定がプログラマブルになった(制限はある。あくまでフィルタのような働き) 本書ではシェーダーとはリアルタイムシェーダーのこと
こういうシェーダーが高級言語でかけるようになったのはDirectX 9.0から
基素.iconMMDはDirectX 9.0
シェーダーの種類はパイプラインのどこを置き換えるかにって分類 など
プログラマから見た描画
1. グラフィクスライブラリを通じて、バッファに以下の情報を与える
必要な情報
頂点列
属性
シェーダー本体
シェーダーへの定数パラメータ
Direct3DでいうConstantBuffer
OpenGLでいうUniform
パイプラインのなかでシェーダーによって頂点列が処理される
実際には多数のシェーダーインスタンスが並列動作する
最も初歩的で多様なプラットフォームで動作するShaderModel 1.0の場合を例に
頂点シェーダーは
最もパイプラインの浅い所に位置
アプリケーションからライブラリを通して入力された頂点について動作
1頂点を1スレッドが処理
1スレッドに対応する頂点の属性がわたる
頂点シェーダーのできること
アプリケーションから渡した定数パラメータを読む
定数は書き換え不可
変換済みの頂点ベクトルと、頂点属性をパイプライン後段に出力
するとビューポート上でのピクセル位置がわかる
位置に応じて、頂点シェーダからの入力のうち頂点座標以外の他の値も補間してピクセルシェーダの入力とする
実例
頂点シェーダがラスタライザに直線を渡してきたとする
(1, 1), k=100
(-1, -1), k=0
ラスタライズされたピクセルに対して動作
1ピクセルを1スレッドが処理
ピクセルシェーダのできること
アプリケーションから渡した定数パラメータ(変更不可)を読む
1つのプログラムからは(概ね)1カラー値を出力
RGBAのカラーを表すベクトル1つ
位置の変更不可
リアルタイムシェーダはプログラマブルとは言っても意外と制約が大きい
ハードウェアパイプラインに割り込む形で実行するため
頂点シェーダー、ラスタライザ、ピクセルシェーダーはそれぞれ用途の決められた専用のレジスタに接続されていると考えよ ストリーミング可能なパラメータはレジスタによって制限がある
構造上CPUのスレッドのようにはできない
シェーダのスレッドはパイプライン中にシェーダーやラスタライザを通じてストリーミング動作する
しかし、定数パラメータはシェーダのバイナリにコードと一緒にリンクされまとめてそれぞれの演算器にアップロードされて終わったら消える
もし定数パラメータをを書き換えられたとしても、他のスレッドからは値が読めない
もし書き換えた定数パラメータを他のスレッドから読めたとしても、シェーダは並列動作するのでその値を同期できない
Q. 制限を外す方法は?
Q. もっとド派手にグニャ〜っとしたりメラメラしたりしたいのですが
A. アプリケーション全体でのサポートが必要
ピクセルシェーダから複数の値が出力できるようになった(Multi Render Target)を使えばShader Modelによっては出力カラーのレジスタを拡張して複数のカラー値を異なるレンダーターゲットに出力する こうした技術を組み合わせて高度な反射モデルやエフェクトを作る
Q. 頂点シェーダは行列演算をするだけでは?
そう。よくある処理をソフトで提供し、ハードウェアの固定パイプライン処理を大幅に削減する これらもする
ボーンスキニングの計算
なので書き換えることはほぼない
table:まとめ
できること できないこと
頂点シェーダ 頂点の変換 定数パラメータの変更
ピクセルシェーダー ポリゴン内のピクセルのRGBAの決定 定数パラメータの変更
テクスチャから任意の位置の値を読む
https://youtu.be/wUx_Y9BgC7k
シェーダを理解しよう 安原 祐二
シェーダプログラムに興味がある、でもどこから始めたらいいのかわからない・・そんな方に、始めの一歩を踏み出してもらうための基礎をお伝えします。また、応用例をベースに、GPUの仕組みについてもお話しします
https://gyazo.com/53f24f631386a390aad8b87277acd217
設定変更可の部分はプログラマブルではなく、厳密にはシェーダーではない
描画とは画素に色付きのdotを打つことを8ステップに分解
step 1
頂点と三角形の情報を準備
頂点ごとに
座標
法線ベクトル
UV(テクスチャ)の座標
三角点列
step 2
step 3
カメラの位置から見たとき、どの座標のpixelを描画するか確定させる
これを使って計算する
step1のモデルの頂点情報
step2のモデル行列
カメラ行列
step 4 処理現象の工夫
面には裏表を定義できる(右回りか左回りか)。裏表を判定する。裏なら描画しない
step 5
描画するべき面(点の集合)を確定する。頂点を繋いだ中の点を描画することにする
GPUの仕事
step 6 処理減少の工夫
step5で決めた描画点を、深度バッファと比較して、手前に描画済みの点があるかを判定する 手前に描画済みの点があるなら描画するだけ時間の無駄
step 7 pixelの色を確定させる
テクスチャ、ライティング、他の物体のシャドウが落ちるか、フォグ
step 8 pixelをうつ
ブレンド関数を指定(アルファの指定ができる)
深度バッファを更新
シェーダーでできないこと
線を引きたい
https://gyazo.com/3e82405b5d4c35ff647b83a5028fbfb6
三角形じゃないのでstep1で対応が必要
半透明の描画がしたい
半透明とは
すでにかいてある後ろの色を拾ってきて
ピクセルシェーダの出力とblendする
つまりstep8でやる
シェーダのBlend関数はプログラマブルではない
https://gyazo.com/be64ccf77d436e23bdf4ada91699fbda
最小のシェーダー
Unityのシェーダーも普通のシェーダーも青い部分は一緒
https://gyazo.com/5f69bb64f9be28226b953107d9b02a87
https://gyazo.com/cfda6e8de895afb0122146794d172115
これがないとGPUはこの値がなんなのかわからない
補完
頂点シェーダはuvを返す
フラグメントシェーダでuvを使ってテクセルをフラグメントシェーダで反映するひろう
実際にはこのuvはGPUが補完した値
頂点シェーダは頂点しか実行していない。その座標を渡しても頂点の間は描画できない
https://gyazo.com/7b2d1c971d69b1253114a328a80de052
Surface shader
シェーダの記述を楽にするもの
解決する課題
ピクセルシェーダーは、大抵複雑になる
しかしいつも同じ定型句がある
影が落ちる
陰影をつける
フォグをかける
https://gyazo.com/2437fec350f807f25198fb43591999da
いきなりSurface shaderを見てもわからないかも