みなさんこんにちは!
フリーランスプログラマーのsatoです!
ShaderLabはとは Unity上でシェーダーを記述する言語です。
言語と聞くと、難しそうですが…安心してください!
記述のルールさえ覚えてしまえば、実は非常にシンプルな内容なんです!
言語の書き方自体もC#などと大差ないため、覚えることは非常に少ないです。
ぜひこの記事でその記述のルールを学んでみてください!
それではアジェンダです。
[基本] まずはシェーダーを用意しよう!
[基本] ShaderLabとは?
[基本] シェーダーを書いてみよう!
[応用] 中身を理解しよう!
今回は実際にUnity上でシェーダーを準備し記述までしていきましょう。
もちろん基礎部分の説明もリンクで用意していますので、基礎に不安がある人はそちらを読んで理解しておきましょう。
それではよろしくお願いいたします。
ShaderLabとは?
ShaderLabを一言でいうと「Unity上でシェーダーを記述する言語」です。
先ほども言ったように、非常にシンプルなルールで成り立っているため、一度覚えてしまえば簡単です!
ぜひ今回で基礎部分を学び終えましょう!
そもそもShaderとは?
Shader(シェーダー)を一言で表すと「描画方法を記述したプログラム」と言えるでしょう。
このプログラムがあるからこそ、画面にオブジェクトが表示されるんです。
逆になければ画面には何も表示されません。
「でもそんなの書いた記憶ないよ!」と思う人も多いでしょう。
しかし実はそれは、デフォルトで選択されている「スタンダートシェーダー」が一般的な描画処理を行ってくれているからなんです。
以下の画像は、いつもの四角いCubeオブジェクトです。
この画面の、Inspectorをよく見てください。
スタンダードシェーダーを選択しているのが確認できると思います。
普段意識していなかったかもしれませんが、シェーダーはいつも使用していた機能なんです!
この辺りは以下の記事で詳細を記述していますので、基礎部分がわからない人はぜひ読んでおきましょう。
シェーダーの仕組み
シェーダーの書き方に入る前に、その仕組みを学ぶ必要があります。
最低限「頂点シェーダー」「フラグメントシェーダー」については理解していないと、シェーダーを書くことは難しいでしょう。
そのためまずは以下の記事で、その仕組みを学んでみてください。
シェーダーのファイルを準備しよう
シェーダーを書くために、まずはシェーダーファイルを用意しましょう。
Shaderファイルを作ってみよう!
作り方は簡単です。
「Projectウィンドウ上で右クリック」→「Shader」→「Unlit Shader」を選択しましょう。
また生成時に付ける名前は、今回は「MyShader」という名称にしておきます。
ちゃんと作れましたね!
Shaderファイルをマテリアルに設定しよう!
あとはそれをマテリアルに設定する必要があります。
Custumの項目に、先ほど作ったシェーダーが自動的に追加されているはずなので、そこから選びましょう。
もしくは、いつものようにアイコンを投げ入れる方法でも反映できます。
Shaderスクリプトを開こう!
ここまでうまくいっていれば、マテリアルのinspectorウィンドウの表記は画像のようなに変わっているはずです。
それが確認できたら、スクリプトを一度開いてみましょうか。
先ほど作ったシェーダーファイルをダブルクリックしてエディタ開きましょう!
無事開ければ、ソースコードが表示されるはずです。
シェーダーを書いてみよう!
ではここからは実際に、シェーダーを記述してみましょう!
まずは一番簡単な処理で実行をしてみましょうか。
現在のシェーダープログラムを一度空っぽに削除して、以下のスクリプトを貼り付けてみてください。
このプログラムはシンプルに、モデルを設定した色で表示するシェーダー処理です。
※ただしMyShaderの部分だけ、自分の命名したファイル名に変更しておいてください。
// シェーダーの情報 Shader "Unlit/MyShader" { // Unity上でやり取りをするプロパティ情報 // マテリアルのInspectorウィンドウ上に表示され、スクリプト上からも設定できる Properties { _Color ("Main Color", Color) = (1,1,1,1) // Color プロパティー (デフォルトは白) a____ } // サブシェーダー // シェーダーの主な処理はこの中に記述する // サブシェーダーは複数書くことも可能が、基本は一つ SubShader { // パス // 1つのオブジェクトの1度の描画で行う処理をここに書く // これも基本一つだが、複雑な描画をするときは複数書くことも可能 Pass { CGPROGRAM // プログラムを書き始めるという宣言 // 関数宣言 #pragma vertex vert // "vert" 関数を頂点シェーダー使用する宣言 #pragma fragment frag // "frag" 関数をフラグメントシェーダーと使用する宣言 // 変数宣言 fixed4 _Color; // マテリアルからのカラー a____ // 頂点シェーダー float4 vert (float4 vertex : POSITION) : SV_POSITION { return UnityObjectToClipPos(vertex); } // フラグメントシェーダー fixed4 frag () : SV_Target { return _Color; a____ } ENDCG // プログラムを書き終わるという宣言 } } }
処理を書いて、保存するとモデルにシェーダーが反映されて、画像のように真っ白になるはずです。
そして、以下の画像のようにマテリアルのColorパラメーターを変更することで色が変更できるはずです。
まずは、シェーダーの記述に成功しましたね!
次はこのプログラムの意味を順に見ていきましょう。
シェーダーの基礎の基礎!
非常に長いプログラムだったので、気が引けている人もいるかもしれませんが…
内容はシンプルなので、重要な箇所を一箇所ずつ見ていけば簡単です!
重要な箇所は以下の4箇所です。
・関数宣言
・変数宣言
・頂点シェーダー
・フラグメントシェーダー
一つずつ見ていきます。
プロパティ情報
// Unity上でやり取りをするプロパティ情報 // マテリアルのInspectorウィンドウ上に表示され、スクリプト上からも設定できる Properties { _Color ("Main Color", Color) = (1,1,1,1) // Color プロパティー (デフォルトは白) a____ }
この部分へは、Unity側から送ってほしい情報を書くことになります。
ここに書いた内容は「このシェーダーを保持しているマテリアル」の「Inspectorウィンドウ上」に表示されています。
この部分ですね!
確かにUnity上から色パラメーターを送ることが出来ているようです。
より具体的な処理内容は以下の通りです。
_Color ("Main Color", Color) = (1,1,1,1) // Color プロパティー (デフォルトは白) a____
①第一引数「Main Color」という名称で、
②第二引数「Color型」のデータを取得し、
③のちの変数定義箇所でしている_Color変数へ代入している
取得さえしてしまえば、後はシェーダー内の処理で好きに判定や反映を行えますね!
関数宣言
// 宣言 #pragma vertex vert // "vert" 関数を頂点シェーダー使用する宣言 #pragma fragment frag // "frag" 関数をフラグメントシェーダーと使用する宣言
一行目は「頂点(vertex)シェーダーでは、vertという関数を呼び出してね!」という意味で…
二行目は「フラグメント(fragment)シェーダーでは、fragという関数を呼び出してね!」という意味です。
これを定義することにより、各シェーダー処理が実行される時に、自作した「vert」「frag」関数を呼び出してもらえるんですね!
関数宣言
// 変数定義 fixed4 _Color; // マテリアルからのカラー
_Colorという変数を準備しています。
先ほどのプロパティ情報箇所の指定によって、この変数にUnityから取得してきたデータが入ることになったわけです。
頂点シェーダー
// 頂点シェーダー float4 vert (float4 vertex : POSITION) : SV_POSITION { return UnityObjectToClipPos(vertex); }
頂点シェーダーは先ほど説明で出てきた、頂点情報を操作するシェーダーです。
フラグメントルシェーダー
// フラグメントシェーダー fixed4 frag () : SV_Target { return _Color; a____ }
フラグメントシェーダーは、先ほど説明で出てきたピクセル情報を操作するシェーダーです。
今回覚えておくべきこと
今回はShaderLabでのシェーダーの記述の内容について見てきました。
まずは何が書かれているのかを、把握しておきましょう。
今回見てきた中で、重要な箇所は以下の5箇所です。
関数宣言 ・・・ シェーダー処理で、呼ぶ関数を指定
変数宣言 ・・・ 「Unityからデータをうけとる」などの目的のため、変数を定義
頂点シェーダー ・・・ 頂点シェーダーの処理
フラグメントシェーダー・・・ フラグメントシェーダーの処理
処理内容を簡潔にまとめると以下と言えるでしょう。
②関数宣言で指定した頂点シェーダー・フラグメントシェーダー関数で、実際に行う処理を記述する。
これだけ理解できれば、ネット上に転がっている実例や、Unity公式のサンプルを読み解けると思います。
言語の細かい部分として、型などを勉強しつつ、実装していけそうですね!
まとめ
今回はUnityのShaderの書き方について見てきました。
変数の型の詳細など細かい点までは、まだ見ることが出来ていませんが、大まかな流れは理解してもらえたかと思います。
最後にまとめた内容を、忘れずににShaderを引き続き学んでいきましょう!