More Related Content
More from fumoto kazuhiro
More from fumoto kazuhiro (16)
Kansai cedec 2015_fumoto
- 2. Introduction
• Technical Artist Bootcamp とは
• テクニカルアーティストの能⼒力力を強化するための講座のような
もの
• Bootcampとは「基礎訓練」を意味するが、基礎だけではな
く、応⽤用的な内容なども幅広く取り扱っていく
• 今年年より開催し、賛同者を募りながら、毎年年、継続的に開催し
ていきたい
2
一番最初に、テクニカルアーティストブートキャンプのイントロダクションを紹介させていただきます。
講演の内容はテクニカルアーティストの能力を強化するための講座風プレゼンテーションです。
ブートキャンプという言葉は基礎訓練とう意味ですが、このシリーズは基礎から応用まで幅広く取り扱っていきます。今回は基礎で。初級編と位置付けています。
もともとGDCでも開催されているものですが、CEDECとして今年から開催し、賛同者を募りながら、毎年各地で継続的に開催していきたいと考えていますので、この
セッションがおわって、「自分もできそう・・・」「ネタ持ってるよ」と思われた方は是非ともご一報ください。
講演希望でなくてもTAのコミュニティとしても活動しておりますので、情報交換にも役立てると思います。
- 3. Technical Artist Bootcamp 2015 vol.1
• 前半「ノードベースリアルタイムシェーダ表現学習」
麓 ⼀一博(30分)
• 後半「インスタント・アルベドチャート作成」
久禮禮 義⾂臣(30分)
3
それでは今年最初のCEDEC TABootcampの講演内容は、まず私が初級編としてノードベースリアルタイムシェーダ表現学習を30分。
後半は久禮さんによる、インスタントアルベトチャート作成と題して30分のご講演という流れでいきたいと思います。
- 4. 講演者情報
• 所属チーム
-‐‑‒ 株式会社セガ ソリューション本部 開発技術部 技術開発課 ツールチーム
• 仕事(⾃自分の役割)
-‐‑‒ SoftimageやMayaをベースとしてツール、表現⼿手法、ワークフローのサポート、提案(元デザ
イナーのテクニカルアーティスト)
• 登壇経験など
-‐‑‒ CEDEC2012:バイナリードメインにおけるモーションワークフローの作り⽅方 (CeDiL)
-‐‑‒ 他TAラウンドテーブル、TABootcampコーディネート
• 寄稿「デジタルゲームの技術」「ゲームクリエイターが知るべき97の事」
• Facebook等でTAコミュニティ
4
講演者情報
- 6. アジェンダ
✓ 前置き
✓ 1: 準備「シェーダの表現学習に⾏行行く前に把握しておくこ
と」
✓ 2: 考察「取り扱うデータの種類や関数とノードについて」
✓ 3: 実践
✓ 4: まとめ
6
本日のアジェンダです。
1: 準備「シェーダの表現学習に行く前に把握しておくこと」
2: 考察「取り扱うデータの種類や関数とノードについて」
3: 実践
4: まとめ
という順でご紹介します。今日のキモは実践の部分ですのでそれまでは軽く流していきます。
- 11. 考察「取り扱うデータの種類や関数とノードについて」
• 複雑な関数はノードになっている
• dot Product
• sin, cos, tan
• clamp
• Multiply
• Normalize
• pow
• etc…
11
MS DevNet
組み込み関数 (DirectX HLSL)
ここがシェーダが割と簡単に覚えられるようになっている重要な点ですが、複雑な計算式は関数で呼べるようにになっています。
ShaderFxではこれらがノードという一つの塊になっていて、そこにデータを入れる(オペレーション的にはつなぐ)だけで計算された結果が簡単に得られます。
どの関数がどういう役割を意味しているかは右側のQRコードのサイトを参照してみてください。
関数名とMayaのノード名が違うこともあるのでどれがどれに当たるのかを探すので苦労するかもしれませんが、全体の数はそんなに多くないので覚えてしまえばこっち
のものです。
- 12. 考察「取り扱うデータの種類や関数とノードについて」
• とりあえずシェーダ学習ができるところまで組んでみた
12
World View Prj
Vertex Position
と言ったようなことを念頭に置いて、とりあえずシェーダ学習ができるところの最低限の所まで組んでみました。このほかにもアルファブレンディングの設定をしたいな
ら、State SettingsをPassにつなぐとか色々ありますが、やはりDFTalkさんがやってくれているので細かいところはそういうところを参照してください。
ここからは、PSと書いてあるピクセルシェーダのColorのところへシェーダで求められた結果をピクセル単位の色として戻すことで表現をしていきます。
上段の頂点シェーダの方で計算したほうが処理が軽いとか、最適化を考えると上段の頂点シェーダも使いますが、まずは学習なのでピクセルシェーダで行います。
- 14. 3: 実践
1.内積でランバート〜~応⽤用
2.反射ベクトルとスペキュラー
3.CubeMap
4.マトリクスからのUVで貼るテクスチャ
5.シェーディングマップ
14
さてそれでは、実際にシェーダを組んでどういう仕組みで絵が作られているのか学習していくわけですが、今回は時間が短いのでほんの一部ということで、
内積でランバート∼応用
反射ベクトルとスペキュラー
CubeMap
マトリクスで貼るテクスチャ
トーンマップ
の、5項目を取り上げてみました。
この順で取り組んでみると、ちゃんと1項目前にやったことが生きるという積み上げ型の学習が出来ます。
- 15. 3: 実践
• 内積でランバート〜~応⽤用
• 内積:ベクトルが2〜~3次元の場合⼆二つのベクトルの⽅方
向⾓角度度の違いを1〜~ー1で返す計算式(個⼈人的な解釈)
• N・L = |N||L|cosθ (N=Normalvec, L=Lightvec)
• ↑Dot Productを使う
15
=1 =0 =ー1
まずは何よりも光と影を表現しなければいけません。
ライトが当たるところは明るく、反対側は暗いというシンプルな現象を近似で表現することができて一番長く使われている式が内積でのランバート表現です。
内積でベクトルの解を求めると、二つのベクトルの方向の違いを−1∼1で求めることができ、それを単純に色に置き換えたというのがランバートです。
公式が書いてありますが左側の解にNとLの間にドットが使われています。
そこからも関数名がdotということになり、どのシェーダ言語にも用意されている関数です。
シェーダ言語が変わっても、たとえノードツリー型になっても、まず最初に探すのはdot productという点を覚えておいてください。
- 16. 3: 実践
• 内積でランバート〜~応⽤用
ShaderFxツリー
16
内積 dot(L,N);
早速シェーダツリーで組んでみました。
ShaderFxにもちゃんとDotOpという内積ノードがあるので、その入力へライトベクトルとワールドの法線ベクトルをつなぎ、その結果を色で返した結果が一番単純なラ
ンバートになります。
- 17. 3: 実践
• 内積でランバート〜~応⽤用
動画
17
見た目はつまらない、いつもビューポートで眺めている景色ですが、このシェーディングがちゃんと自分で組んだノードの結果が表示されているという点を意識してく
ださい。
ここにRGBの色を乗算すると、一般的なランバートマテリアルが作成できます。
- 18. 3: 実践
• 内積でランバート〜~応⽤用
• ハーフランバート=光の数が多かったり、⽪皮下散乱など
を簡易易的に表現するために、ランバートの明るい範囲を
拡張したもの
18
=1 =0 =ー1
=1 =0.5 =0
ランバート
ハーフ
ランバート
ランバートの応用例の一つで、ハーフランバートというものがあります。
10年位前ですかね、ネット記事に出てきたのはハーフライフだったような記憶がありますが、通常のランバート計算だとライトが1方向からしか当たっていないような
表現になってしまうのに対して、世の中の光源は一つではないですよね?というのを例に提唱されたのがこの手法でした。
本来は0以下は色的には黒なので0以下をクランプして切り捨てるのですが、ハーフランバートに応用するためにさっきはあえて残しておきました。
図の上の結果を下の結果にするために必要なのは簡単な掛け算足し算で、関数とかは必要ありません。
上の図のランバートの結果に0.5をかけて、0.5を再度足すだけで求められます。
- 19. 3: 実践
• 内積でランバート〜~応⽤用
ハーフランバートShaderFxツリー
19
×0.5
+0.5
ランバートのシェーダツリーの結果にまずMultiplyという掛け算ノードを繋いで0.5をかけて、その結果に足し算ノードを繋いで、0.5を足しています。
0.5という数値ノードは両方で同じ値を使うので、使い回しています。
- 20. 3: 実践
• 内積でランバート〜~応⽤用
ハーフランバート動画
20
ネットでハーフランバートを検索すると、この単純なかけて足す方法と、さらにそのあとに2乗するという方法が出てきます。
2乗するとガンマカーブをいじったような少し黒い部分が広がるイメージのハーフランバートが出来上がりますが、今回は後で使いたいので今は2乗しないものでとどめ
ておきます。
- 21. 3: 実践
• 反射ベクトルとスペキュラー
• 反射ベクトル:⼆二つのベクトルの⼀一⽅方を進⾏行行ベクトルと
した場合、壁で反射した⽅方向を求められる。
• 進⾏行行ベクトルを視線ベクトル、壁と直⾏行行するベクトルを
法線ベクトルとする(計算式省省略略)
• 反射ベクトル=reflect(N,E)
• スペキュラー輝度度はさらに反射ベクトルとライトベクト
ルの内積で求める
21
ランバートの表現が終わったところで次は「キラッと反射」のスペキュラーへ移ります。
スペキュラーの表現は幾つかあるのですが、今回は反射ベクトルを使った方法で表現してみます。
反射ベクトルは進行ベクトルのものが、壁に当たって跳ね返る反射先のベクトルを求めるというもので、進行ベクトルを視線のベクトル。そして壁の表向きを法線ベクト
ルに置き換えて、reflect();という関数をシェーダでは使います。
さらにスペキュラーのライティングはもう一段階あって、ランバート同様に輝度の1∼0値に置き換える必要があります。
ということで反射ベクトルとライトベクトルの内積で求められます。
- 22. 3: 実践
• 反射ベクトルとスペキュラー
ShaderFx
22
反射ベクトル
内積
スペキュラーをノードツリーにしたものがこれです。
視線ベクトルは取得の仕方によりますが、カメラベクトルから取得すると向きが逆なので、反転させて、法線ベクトルとの二つから反射ベクトルを計算しています。
そしてライトが反射してキラッとしているので、反射ベクトルとライトベクトルの内積でスペキュラーの輝度を決定しています。
- 24. 3: 実践
• 反射ベクトルとスペキュラー
ShaderFx
24
また、スペキュラーのサイズを調整する方法は一番簡単な「べき乗」を使います。
内積の結果にpowノードをつなぎ、べき乗する値を設定します。
左の60という値に対して、右側が結果のスペキュラー光沢のサイズになります。
物理ベースでいうとこの状態は表面がツルツルになって行き、反射率が高くなってきているということですね。
ライトの形がそのまま反射すると、小さい点になっていくという近似値の考え方です。
- 25. 3: 実践
• Cubemap
• 9枚のテクスチャ(1つのdds)を使って反射を表現する
• texCube(cubemap, uvw) →ノード名は「Texture
Sampler」
• uvwに法線ベクトルを⼊入れるとDiffuse、反射ベクトル
をいれるとSpeculerの反射になる
25
ここまでのものは従来のマテリアルで、真っ黒い空間にライトが焚かれているだけというものの近似表現でした。
実際の空間には周りにいろんなものが置いてあって、それらの影響を受けていろんな色が表面に写り込んでいる、究極がイメージベースドライティングということになり
ますが、それの基礎表現に用いられるものがCubemapです。
そもそもテクスチャの解説を省略していますが、口頭でいうとテクスチャをオブジェクトに貼るには、ピクセルの情報と、オブジェクトのUV値が必要なのですが、
Cubemapではモデル製作者がUVを決めるわけではありません。
UV値には今まで求めたそれぞれのベクトルを使用し、法線ベクトルを使うとDiffuseで、反射ベクトルを入れるとSpeculerということになります。
シェーダ言語などで使われる関数はtexCubeというものですが、ShaderFxではTexture Samplerとちょっと名前が違うノードが用意されています。
- 26. 3: 実践
• Cubemap
ShaderFx
26
Texture
Component
Texture Sampler
Texture Type
シェーダツリーは反射ベクトルを使う場合です。もともとこのツリーにも法線ベクトルがすでにあるので、Diffuseを見たい場合は繋ぎ直してください。
テクスチャのつなぎ方は、シェーダ言語のお約束の範囲なので少々癖があります。
まずTexture Componentというノードを使い、テクスチャファイルを取得します。
テクスチャの画像情報をSamplerStateを通して、TextureSamplerノートへとつなぎます。
これらのノードのテクスチャタイプはTextureTypeノードを繋げて設定します。
最後にTexture SamplerノードのUV Texcoordsのポートにスペキュラーで求めた反射ベクトルが接続されていることにご注目ください。
- 27. 3: 実践
• Cubemap
動画
27
例によって見慣れたキューブマップの様子ができあがります、動画を御覧ください。
上から見たらちゃんと空が、下から見たらちゃんと地面が反射しています。
そして、反射ベクトルが繋がっているポートに法線ベクトルをつなぎ直すと、今度は拡散反射用のキューブマップへ変化します。
- 28. 3: 実践
• シェーディングマップ
• シェーディング表現にテクスチャを使う
• tex2D(texturemap, uv) →ノード名は「Texture
Sampler」
• uvにハーフランバートを適⽤用することで、シェーディ
ングをUVとしたテクスチャが貼られる。
28
またさらに、途中段階を省略していますが、シェーディングマップというのをご存知でしょうか?
トゥーンシェーディングなど、陰影のシェーディング階調をテクスチャで持ちたい(アーティスティックにコントロールしたい)という場合によく用いられる手法で、ノ
ンフォトの基本中の基本のようなものです。
前に紹介したハーフランバートを活用します。
例えばキューブマップはベクトルをテクスチャ展開に使うことで動的にテクスチャを貼っていたのですが、次はこのハーフランバートの結果をUV展開に使うことで、テ
クスチャの画像座標の0がハーフランバートの0、1もそのまま1として貼り付けられます。
この場合は二次元としてテクスチャを展開するだけなので、tex2D関数をつかいますがそのままの名前のノードがShaderFxにはありません。
Cubemap同様にTexture Samplerという名前のノードを使います。
- 29. 3: 実践
• シェーディングマップ ShaderFx
29
ハーフランバート
Texture Sampler
Type=2D
ツリーが大きくなってだんだん苦しくなってきました。
ハーフランバートの結果をUVのU値にしてTexture SamplerのUVへつなぎます。
テクスチャファイルからTexture Samplerまでの流れはCubemapと一緒ですが、TextureTypeの指定はTexture2Dとしておきます。
テクスチャの座標は左が0で右が1ですが、ハーフランバートそのままだと逆に明るい方が1で暗い方が0となってしまいますので、計算結果を1から引いて、明暗の方
向を反転させています。
そうすることで、テクスチャの左側が明るい色、右側が暗い色という自然な流れでグラデーションをかけるようになります。
- 30. 3: 実践
• シェーディングマップ Texture Space
30
UV=0 U=1
UV=1V=1
ちなみにテクスチャスペースは左下がUV0位置で右上がUV1の位置という点を覚えておくと、ただのグラデーションマップよりも表現力を上げることができるかもしれま
せん。
Mayaの標準UV値と同じ設定なので間違えることは無いとは思います。
- 31. 3: 実践
• シェーディングマップ
動画
31
結果、テクスチャの緑の方がライトの方向で明るい側、赤い部分が暗い側という表現になります。
テクスチャをそれっぽい白黒グラデーションに変えると、普通のランバートっぽくなりますし、水彩階調っぽく描いたものに変えることで、カートゥーン表現も出来るよ
うになります。
- 32. 4: まとめ
• 表現の仕組みがわかると次への応⽤用が⾒見見えて来る
• ⾃自分で特殊な表現の実験ができる
• どういうリソースを⽤用意すればいいかを知ることができる
• 結果、⾼高い表現に効率率率の良良いワークフローを構築できる
32
時間の関係で今回紹介する方法はこれだけですが、一つ一つ表現方法の仕組みがわかるだけで、ほかの表現の応用を思いついたり、どうやって動いているのかが見えて
来るのが伝わりましたか?
また、自分でシェーダが組めるようになると、あの表現はどうだろう。こういう表現がしたい。等プログラマの手を煩わせる前に自分で実験をすることができるように
なり、うまくシナプスが繋がっていい表現ができたらそれにどういうリソースが必要かを知ることができます。
結果として自分がやりたかった表現に効率の良いワークフローを構築することができるようになりますので、テクニカルアーティストの皆さんは是非とも簡単なシェーダ
だけでも自分で作れるようになっておくことをお勧めします。