【Unity入門】シェーダーを書いてみよう!ShaderLabの簡単な書き方!

みなさんこんにちは!

フリーランスプログラマーの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公式のサンプルを読み解けると思います。

言語の細かい部分として、型などを勉強しつつ、実装していけそうですね!

まとめ

今回はUnityのShaderの書き方について見てきました。

変数の型の詳細など細かい点までは、まだ見ることが出来ていませんが、大まかな流れは理解してもらえたかと思います。

最後にまとめた内容を、忘れずににShaderを引き続き学んでいきましょう!

この記事を書いた人

【プロフィール】
DX認定取得事業者に選定されている株式会社SAMURAIのマーケティング・コミュニケーション部が運営。「質の高いIT教育を、すべての人に」をミッションに、IT・プログラミングを学び始めた初学者の方に向け記事を執筆。
累計指導者数4万5,000名以上のプログラミングスクール「侍エンジニア」、累計登録者数1万8,000人以上のオンライン学習サービス「侍テラコヤ」で扱う教材開発のノウハウ、2013年の創業から運営で得た知見に基づき、記事の執筆だけでなく編集・監修も担当しています。
【専門分野】
IT/Web開発/AI・ロボット開発/インフラ開発/ゲーム開発/AI/Webデザイン

目次