みなさんはshader、使っていますか?
shaderプログラミングをしたことがありますか?
shaderプログラミングというと、プログラミング言語の中でも特に難しそう…というイメージがあったり、
shaderの勉強にまで手が回らない、なんて思っている人が多いと思います
そんな方のために、今回TECH_SALONでは、Unityを使って学ぶshader勉強会を
株式会社Donutsの場所をお借りして開催しました!
1.勉強会の概要
まずはshaderに関わる知識の解説(例えばポリゴン、モデル、Vertex shader)から始まり、1時間後くらいから実際にUnityを使ったshaderプログラミングを行いました。
UnityにはShaderLabというShaderを簡単に書けるようにUnity側で用意された言語がありますが、今回はそれを使用せずにHLSLというShader言語を使用しました。
2.勉強会の見どころ
○Unityを使用しているため、プログラミングの結果がすぐ分かり、理解しやすい!
今回はゲームエンジンであるUnityを使用しているため、コードを書いて保存すればすぐにScene上で確認が出来ます。
○ShaderLabではなく、HLSL言語を使用しているため、一からShaderプログラミングが学べる!
Unityの言語ではなくHLSL言語のため、Unity以外でも使用でき、より深く勉強することが出来ます。
3.勉強会で学んだこと
まずは、Shaderの基礎の基礎知識として、3Dの描画に必要な
○ポリゴン
○Shader
○Material
○モデル
の4つについて解説して頂きました。
ポリゴン…頂点データ(ただの座標)の集まり。ちなみにポリゴンとモデルを混同する人が多いみたいですが、ポリゴンはモデルではなく、Fbxファイルでもありません。
Shader…頂点の加工(Vertex)と最終的な色の決定(Fragment)をするもの。
Material…Shaderを実体化するもの。
モデル…ポリゴンとMaterialを管理するもの。Fbxファイルもモデルの一つ。
つまり、ポリゴンの頂点データを加工し、最終的な色の決定をするのがShaderで、
そのShaderを実際にモデルに反映させるためにあるのがMaterialです。
そして、そのポリゴンとMaterialを管理しているのがモデルなのです。
Shaderプログラミングの準備
ここからは講義で実際に行ったプログラミングのうちいくつかをソースコードとともに紹介します。
UnityでShaderを書くには、Projectウィンドウ上で右クリックし、
Create > Shader > Standard Surface Shaderを実行し、“test1”と名前を付けます。
その後、そのShaderを右クリックして、Create > Material を実行します。
その後、Cubeを作成してこのMaterialをアタッチしてください。
これで、準備が整ったので、先ほど作成したShaderをダブルクリックしてエディタを起動します。
そして、一度すべてのソースコードを消して、以下のソースコードを記述してください。
1 2 3 4 5 6 7 |
Shader "Custom/Test1" { // 名前を定義。"/"を使用すると階層を切れる SubShader { // shaderの処理を定義。Subとついているがメイン処理 Pass { // Vertex Shader処理とFragment Shader処理を書く } } } |
これで保存して実行してみましょう。
Cubeが真っ白になってしまいました。
これは、最低限の記述しか書いていないため、
UnityデフォルトのMaterialが反映されて白で描画されています。
では、次にこちらを記述してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Shader "Custom/Tech1"{ SubShader{ Pass{ CGPROGRAM // 必ず必要 #pragma vertex vert // Vertex処理を行う関数名を指定 #pragma fragment frag // Fragment処理を行う関数名を指定 // vertex処理の記述。頂点毎に呼ばれ、頂点データを引数でもらえる。 float4 vert(float4 pos : POSITION) : SV_POSITION { return pos; } // fragment処理の記述。ピクセルごとに呼ばれ、ピクセルの色を返す。 float4 frag() : COLOR { return float4 (1,1,1,1); } ENDCG // 必ず必要 } } } |
ShaderにはVertexとFragmentという処理があります。
○Vertex…頂点データの加工を行う。
○Fragment…最終的な色の決定をする。
そして、#pragmaというのは、その処理を行う関数名を指定しています。
今回で言うと、
1 2 |
#pragma vertex vert // Vertex処理を行う関数名を指定 #pragma fragment frag // Fragment処理を行う関数名を指定 |
上記の部分は「vertex処理を行うのは”vert”で、fragment処理は”frag”で行う」
ということになります。
次に、float4 pos : POSITIONの”POSITION”とは
セマンティクスと呼ばれ、その型がどういう属性なのか示すものです。
この文は「引数のposはPOSITION(頂点座標)です」
という意味です。
他にも”NORMAL”はNORMAL情報
SV_POSITIONは加工後の座標を返します。
後半のfragの処理についてですが、
ここにもCOLORというセマンティクスがあります。
このCOLORも最終的な色を返します。
1 |
return float4 (1,1,1,1); |
についてはfloat4でRGBAを表現していて、
UnityではRGBAの値を0~1で表します。
今回はRGBAが全て1のため、白になります。
実行するとこのように失敗してしまいます。
これはvertexで頂点の加工をしていないからです。
ただ、fragmentの処理は正常に動作したため、
白で描画されたけどCubeの形ではない、という描画結果になりました。
Cubeの形になるように修正します。
1 2 3 4 5 6 7 |
// vertex処理の記述。頂点毎に呼ばれ、頂点データを引数でもらえる。 float4 vert(float4 pos : POSITION,float4 normal : NORMAL) : SV_POSITION { float4 world = mul(_Object2World, pos); // ワールド座標変換 float4 view = mul(UNITY_MATRIX_V, world); // ビュー変換 float4 projection = mul(UNITY_MATRIX_P, view); // 射影変換 return projection; } |
しっかり表示されました!
ただ、mul関数を何度も使っていて面倒くさいですよね?
1 2 3 4 |
// vertex処理の記述。頂点毎に呼ばれ、頂点データを引数でもらえる。 float4 vert(float4 pos : POSITION,float4 normal : NORMAL) : SV_POSITION { return mul(UNITY_MATRIX_MVP, pos); } |
Unityならこの一行で済ませることができます。
便利ですね!
色の描画
今の段階では白のため、色を描画出来るようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
Shader "Custom/Tech1"{ SubShader{ Pass{ CGPROGRAM // 必ず必要 #pragma vertex vert // Vertex処理を行う関数名を指定 #pragma fragment frag // Fragment処理を行う関数名を指定 struct v2f { float4 wPos : SV_POSITION; float3 normal : NORMAL; }; // vertex処理の記述。頂点毎に呼ばれ、頂点データを引数でもらえる。 v2f vert(float4 pos : POSITION,float3 normal : NORMAL) { v2f OUT; OUT.wPos = mul(UNITY_MATRIX_MVP, pos); OUT.normal = normal; return OUT; } // fragment処理の記述。ピクセルごとに呼ばれ、ピクセルの色を返す。 float4 frag(v2f input) : COLOR { return float4 (input.normal * 0.5 + 0.5,1); } ENDCG // 必ず必要 } } } |
色が付きました!
このソースコードの解説をしますと、
1 2 3 4 |
struct v2f { float4 wPos : SV_POSITION; float3 normal : NORMAL; }; |
ここは、fragment shaderでNormal情報も受け取れるようにするために
structで定義をし直しました。
ここでfloatの後ろにセマンティクスも定義しているため、その後のVertexとFragmentの部分ではセマンティクスを省略できます!
次に
1 2 3 4 5 6 7 |
// vertex処理の記述。頂点毎に呼ばれ、頂点データを引数でもらえる。 v2f vert(float4 pos : POSITION,float3 normal : NORMAL) { v2f OUT; OUT.wPos = mul(UNITY_MATRIX_MVP, pos); OUT.normal = normal; return OUT; } |
この部分で先ほど定義したv2fに合わせて情報を返すようにしました。
fragmentも
1 2 3 4 |
// fragment処理の記述。ピクセルごとに呼ばれ、ピクセルの色を返す。 float4 frag(v2f input) : COLOR { return float4 (input.normal * 0.5 + 0.5,1); } |
v2fに書き直してあります。
ちなみにreturn float4の部分は
ピクセルごとの色の数値が0を下回らないように計算しています。
これで色を塗ることが出来増した。
でも、一々色をプログラム上で変更するのは面倒くさいですよね?
実は、ShaderのInspecterを自作することが出来ます!
Shaderのプロパティ
プロパティ=MaterialのInspecterから自由に弄れる変数
つまり↑これです!
ではソースコードです!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
Shader "Custom/Tech1"{ // プロパティはここで定義 Properties{ _CubeColor("Cubeのカラー",COLOR) = (1,1,1,1) } SubShader{ Pass{ CGPROGRAM // 必ず必要 #pragma vertex vert // Vertex処理を行う関数名を指定 #pragma fragment frag // Fragment処理を行う関数名を指定 uniform float4 _CubeColor; // プロパティをHLSL内で使えるようにする struct v2f { float4 wPos : SV_POSITION; float3 normal : NORMAL; }; // vertex処理の記述。頂点毎に呼ばれ、頂点データを引数でもらえる。 v2f vert(float4 pos : POSITION,float3 normal : NORMAL) { v2f OUT; OUT.wPos = mul(UNITY_MATRIX_MVP, pos); OUT.normal = normal; return OUT; } // fragment処理の記述。ピクセルごとに呼ばれ、ピクセルの色を返す。 float4 frag(v2f input) : COLOR { return _CubeColor; } ENDCG // 必ず必要 } } } |
変更点としては
1 2 3 4 |
// プロパティはここで定義 Properties{ _CubeColor("Cubeのカラー",COLOR) = (1,1,1,1) } |
SubShaderの前にプロパティを定義し、_CubeColorというプロパティ名を使用することで
Inspecter上でカラーパレットが表示されるようになります。
(1,1,1,1)の部分を変更すれば、カラーパレットの初期色を変更できます。
1 |
uniform float4 _CubeColor; // プロパティをHLSL内で使えるようにする |
uniformとはvertexやfragmentで共通で使えるようにする修飾子です。
1 2 3 4 |
// fragment処理の記述。ピクセルごとに呼ばれ、ピクセルの色を返す。 float4 frag(v2f input) : COLOR { return _CubeColor; } |
最後に、ここで_CubeColorの変更を反映させています。
これを保存して実行すると…
Inspecter上で変更することが出来ました!
4.勉強会の感想
今回、初めてShaderプログラミングをしてみましたが、
解説がとてもわかりやすく初心者でも理解できるような勉強会でした。
Shaderに関する基礎知識だけでなく、ソースコードの解説もとても丁寧で、
プログラミングに自身がない人でも十分理解できるような内容でした。
また、Inspecter上で色が変更できるという点が
Unityらしくもあり非常に便利なのでとてもよかったです!
講師の方がまだまだ基礎の基礎しか講習出来てないとおっしゃっていたので、
是非ともUnity Shader勉強会Vol.2をして頂きたいと思います!
5.企業の紹介
——————————
株式会社Donuts
——————————
「Change the Game」のスローガンの元、100%自己資本で現在急成長中の企業です。
モバイルゲーム事業・Webサービス事業・ASP事業の3つの事業を展開し、
最近ではオリジナルのモバイルゲームであるTokyo 7th シスターズが
アニメーション映像化プロジェクトを発表しています。
採用情報 : http://www.donuts.ne.jp/jobs/
—————————–
TECH_SALON
—————————–
TECH_SALONは「楽しいエンジニアイベントを!」をコンセプトに、
ファーストキャリアを技術職として歩んでいきたい学生のための、
スキルアップ・キャリアアップの機会を提供していくコミュニティです。
これからのIT世界を担っていく若手エンジニアにとって、
成長の機会となるような場を多く用意しています。
これまでに、30回以上の勉強会の開催20社以上のITベンチャー企業とのコラボ、
延べ300名近くの方々にプログラミング教育の場を提供してきております。
Facebook : https://www.facebook.com/techsalon.page/
Twitter : https://twitter.com/SNS_SALON