初心者が始めるMR技術所

主にUnityのMR記事を書いていきたい

Shaderの基本編<俺もよくわからないので詳しく見ていくよ!>

この記事では基本的にUnityShaderについて扱っていきます

筆者は全くの初心者なので間違い等があればコメントで教えていただけると嬉しいです

 

Shaderの基本

 

まずUnityのShaderについて

 

使用する言語はNVIDIAがCをベースに開発したCg言語とShaderLabが一般的なようです

そしてUnityのShaderには3種類の種類があるみたい

 

・ Fixed Function Shaders (固定機能シェーダ)
Surface Shaders (サーフェイスシェーダ)
・ Vertex and Fragment Shaders (頂点/フラグメントシェーダ)

 

調べた感じしばらくは Surface Shaders (サーフェイスシェーダ)をいじっていくことになるかな。

とういのもFixed Function Shaders (固定機能シェーダ)はできることが少ないっぽいです

 

Vertex and Fragment Shaders (頂点/フラグメントシェーダ)はゴリゴリプログラムを書いていくとの最初は厳しいと判断したのであとまわし!

たぶんShaderから変形させたりはこっちなのかな?たぶんサンプル見つけたらこっちのが面白いのでやってみたいですね

 

最小限の Surface Shader コード

C言語でいうところの

#include<stdio.h>

void main{

     return 0;
}

ってやつですね
以下がそれ

Shader "Custom/testShader" {

	Properties{
	    // プロパティ インスペクタに表示される
	}

	SubShader{
		CGPROGRAM

		#pragma surface surf Lambert

		struct Input {

	        };

	        void surf(Input IN, inout SurfaceOutput o) {

	        }

	        ENDCG
	}
}

長いね ちゃんと少しづつ見ていくよ!

Shader "Custom/testShader" {

これはshaderがカスタムshaderのtestShaderであるってこと
C++C#でいうとこのクラス名みたいなものかな?

プロパティ構造
Properties{
	// プロパティ インスペクタに表示される	
}

ここではカラーやベクトル、テクスチャとかを記述するところ

例えば

Properties{
   _MainColor("Color", Color) = (1,1,1)
}

とかね。これやっても実際に色が変わるわけじゃないから
インスペクタからアクセスできる変数宣言できるものみたいな感覚だと思うかな!

ちなみに _MainColor("Color", Color) = (1,1,1) の""で囲まれていないほうのColorが変数名みたいものらしい
だから _TestColor("White", Color) = (1,1,1) でもエラーは出ない

プロパティの変数は全部で 7種類 あるっぽいね

name("display name", Range( min, max)) = number
floatプロパティを定義し、インスペクタ上でスライドバーが minから maxとして表現。
name("display name", Color) = ( number, number, number, number)
colorプロパティを定義。
name("display name", 2D) = "name" { options}
2Dテクスチャプロパティを定義。
name("display name", Rect) = "name" { options}
長方形(2のべき乗でない)テクスチャのプロパティを定義。
name("display name", Cube) = "name" { options}
キューブマップテクスチャのプロパティを定義。
name("display name", Float) = number
floatプロパティを定義
name("display name", Vector) = ( number, number, number, number)
4コンポーネント ベクトルのプロパティを定義。
      

http://unitech.hatenablog.com/entry/2015/03/11/001953より引用


さてこのPropertiesで宣言したものをどうやって使うのか

SubShader
SubShader{
		CGPROGRAM

		#pragma surface surf Lambert

		struct Input {

	        };

	        void surf(Input IN, inout SurfaceOutput o) {

	        }

	        ENDCG
	}

ここがC言語でいうとこのメイン文的なとこ
このSubaShaderの中で先ほどのPropertiesで宣言したものを使えるようにする

解説から

SubShader{
		CGPROGRAM

		#pragma surface surf Lambert

		struct Input {

	        };

	        void surf(Input IN, inout SurfaceOutput o) {

	        }

	        ENDCG
	}


CGPROGRAM
..
ENDCG

はその中でCg言語を使います的なやつかな

#pragma surface surf Lambert

この文はSurface Shaderのコンパイル方法についてっぽい
surfを入れたことで後述のsurf関数から始まるのかな
そのあとの Lambert は詳しくわからないのでとりあえずスルーしておこうかなw

Input構造&surf関数
   struct Input {

   };

   void surf(Input IN, inout SurfaceOutput o) {

   }

この2つは一気に行くぞ
Inputで実際に使用する変数を宣言
surfでそれを実行するぞ!

たとえば先ほどPropertiesでん宣言した

 _MainColor("Color", Color) = (1,1,1)

を使いたい場合SubShaderの中で同様の宣言が必要になる

SubShader{
		CGPROGRAM

		#pragma surface surf Lambert

		struct Input {

	        };


        float4 _MainColor;

	        void surf(Input IN, inout SurfaceOutput o) {

	        }

	        ENDCG
	}

プロパティ変数を見てみるとColorは4つのfloat型なのでfloat4型となる
そして

struct Input {

};

にはshaderに与える情報を宣言しなきゃいけないみたい

struct Input {
    float4 color : COLOR;
};

これで色を変更する準備は完了! このInputについては自分も詳しく理解できてないからしらべたら更新します

最後に値を更新したら色が変わるぞ!

void surf(Input IN, inout SurfaceOutput o) {
     o.Albedo = _MainColor.rgb * half3(1, 0.5, 0.5);
}

出力される o のアルベド値を変更すれば色が変わる

ちなみにSurfaceOutputには6種類の値を持っている

struct SurfaceOutput {
    half3 Albedo;    // 拡散反射光(=Diffuse)
    half3 Normal;    // 法線ベクトル
    half3 Emission;  // エミッション
    half Specular;   // スペキュラ
    half Gloss;      // 輝き
    half Alpha;      // 透過度
};

とりあえず今回はここまで
理解できていないところちょっとよくわからんのだよな
とくにInput構造のfloat4 color : COLOR;ってとこ
必要なのはなんとなくわかるけど..

わかる人いたらコメントください!