Unity Shader を学ぶための本文
まず、Unity Shader(Surface Shader)を作成します:
Shader "Custom/NewSurfaceShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// 物理ベースのスタンダードライティングモデルで、すべての光源タイプで影を有効にする
#pragma surface surf Standard fullforwardshadows
// より美しいライティングを得るために、シェーダーモデル3.0を使用する
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// このシェーダーにインスタンシングサポートを追加します。シェーダーを使用するマテリアルで「インスタンシングを有効にする」をチェックする必要があります。
// インスタンシングについての詳細は、https://docs.unity3d.com/Manual/GPUInstancing.htmlを参照してください。
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// ここにパーパーティクルごとのプロパティを追加します
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// アルベドは色によって着色されたテクスチャから取得されます
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// メタリックとスムーズネスはスライダー変数から取得されます
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
この Unity Shader コードは、基本的な物理的なプロパティ(色、光沢、金属感など)を持つ表面をレンダリングするためのカスタムの Surface Shader を定義しています。各部分を詳しく説明します:
Shader の宣言#
Shader "Custom/NewSurfaceShader"
この行は新しい Shader を宣言し、それを "Custom/NewSurfaceShader" という名前で命名しています。この名前は Unity のマテリアルエディタで見つけてゲームオブジェクトに適用することができます。
Properties#
このコードブロックは、Shader が外部から受け取るパラメータを定義し、インスペクタパネルで変更できるようにします。
具体的な結果を見るためには、まず新しいマテリアルを作成し、マテリアルのインスペクタパネルで Shader を選択し、先ほど作成した Shader で定義されたプロパティを見ることができます:
Properties の構文を解析してみましょう:
_PropertyName ("Display Name", PropertyType) = DefaultValue
これに対応する Shader コードの宣言は次のとおりです:
Properties {
_Color ("Color", Color) = (1,1,1,1) // デフォルトで白色のカラープロパティを定義します。
_MainTex ("Albedo (RGB)", 2D) = "white" {} // デフォルトで白色のテクスチャを使用する2Dテクスチャプロパティを定義します。
_Glossiness ("Smoothness", Range(0,1)) = 0.5 // 表面の滑らかさを表す0から1までの範囲の浮動小数点数プロパティを定義します。
_Metallic ("Metallic", Range(0,1)) = 0.0 // 材料の金属感を表す0から1までの範囲の浮動小数点数プロパティを定義します。
}
SubShader#
SubShader
ブロックは実際のレンダリングロジックを定義します。Shader に複数の SubShader が含まれている場合、Unity はハードウェアとパフォーマンスに基づいて最適なものを選択します。
Tags { "RenderType"="Opaque" }
:この Shader が不透明なオブジェクトのレンダリングに使用されることを指定します。LOD 200
:Shader の詳細レベル(Level Of Detail)を設定し、レンダリングのパフォーマンスと品質に影響を与えます。
CGPROGRAM#
CGPROGRAM
とENDCG
の間には、実際の Shader コードがあります。これはCg/HLSL
言語で書かれています。
#pragma surface surf Standard fullforwardshadows
この行は、この Shader のスタンダードライティングモデルを物理ベースで実装し、すべての光源タイプで影を有効にすることを宣言しています。
Unity の Shader コードでは、#pragma ディレクティブはコンパイラに特定のコンパイル指示を提供するために使用されます。
#pragma surfaceasdasd
これは Surface Shader 固有のもので、Unity にこれが Surface Shader であることを伝え、この Shader のプロパティと動作を定義し始めます。
surf
は、Shader コードの後ろに自分で定義した関数であり、Unity は各ピクセルのレンダリング時にこの関数を呼び出してさまざまなプロパティを決定します。例えば、光沢、色などです。
standard
は、Unity の PBR(物理ベースレンダリング)モデルを使用することを示しています。これは一般的に使用されるレンダリングモデルです。
fullforwardshadows
はオプションで、前方レンダリングパスでのすべての影の投射を有効にします。これにより、ディレクショナルライト、ポイントライト、スポットライトなど、すべてのタイプの光源が Shader 内で正しく影を計算することができます。これは、ゲームやシーンで複雑な照明と影の効果を実現するために必要です。このオプションを使用しないと、一部の光源で正確な影のレンダリングが得られないか、影の品質が低下する可能性があります。
#pragma target 3.0
:Shader モデル 3.0 を指定し、より美しいライティング効果を得ます。
sampler2D _MainTex;
は、2D テクスチャサンプラーを定義しています。Shader では、テクスチャサンプリングはテクスチャからピクセルデータを読み取るために使用されます。通常、基本的なディフューズマップを格納するために使用されます。
CG では、テクスチャは通常、3 チャンネルまたは 4 チャンネル(A があるかどうかによる、各チャンネル 8 ビット)のメモリです。サンプラーは、各ピクセルと座標の対応関係とオフセットを自動的に計算するのに役立ちます。
input
構造体は、入力データの構造を定義しています。具体的には、input は uv_MainTex(メインテクスチャの UV 座標)が float2 型であることを定義しています。
half _Glossiness
は、half
変数(メモリ使用量が少ない浮動小数点型)を定義しています。この変数は、マテリアルの光沢度を制御するために使用されます。同様に、_Metallic
変数はマテリアルの金属度を制御します。_Color
はfixed4
型(低精度の四元数)であり、マテリアルの基本色を格納するために使用されます。
以下の 2 行は、GPU インスタンス化サポートに関する指示です。
surf
関数は Shader の中核であり、この関数はマテリアルをシェーディングするためにマテリアルの表面のプロパティを計算します。
surf 関数#
Unity の Surface Shader では、surf 関数は視覚的な表面のプロパティを定義するための中核コンポーネントです。この関数は入力を処理し、結果を特定のデータ構造に出力します。この構造体は、オブジェクトの表面が光線とどのように相互作用するかを記述します。
実行プロセス
入力:surf 関数は Input 構造体を引数として受け取ります。この構造体には、UV 座標、法線など、Shader の定義に応じたすべての必要な入力データが含まれています。あなたのコードの例では、Input 構造体には uv_MainTex、つまりメインテクスチャの UV 座標が含まれています。
複数回の呼び出し:レンダリングプロセス中、Unity は各ピクセルまたは各頂点に対して surf 関数を呼び出します。各ピクセルに対して、対応する入力データ(テクスチャ座標やその他の使用可能な頂点データなど)を使用して、表面の出力を計算します。
出力:出力は surf 関数の 2 番目のパラメータを変更することで実現されます。これは書き込み可能な SurfaceOutputStandard 構造体です。この構造体には、ピクセルの最終的な外観を決定するさまざまなプロパティ(アルベド、金属感、光沢、透明度など)が含まれています。これらのプロパティは、物理的な特性に基づいて現実世界のマテリアルの振る舞いをシミュレートするために使用されます。
マテリアルの効果:surf 関数の出力データは Unity のレンダリングエンジンによって使用され、ライティングモデルとシーンの照明条件と組み合わせて、最終的なピクセルの色を計算します。これにより、各ピクセルの色は、その具体的な表面特性とシーンの照明条件に基づいて動的に計算されます。