Unity の Shader (ShaderLab) 知識ざっくりメモ
はじめに
普通の書き方をする上で、よく使うことについてメモします。 随時追記予定
事前知識
ShaderLabの概要
ShaderLab は、Cgを用いたUnity独自のShader文法。マテリアルに .shader ファイルを登録します。
突然自作の前に、まずはビルトインのものから
ビルトインシェーダの使い方 http://docs-jp.unity3d.com/Documentation/Components/Built-inShaderGuide.html
Unityビルトインシェーダ(Diffuseとか)のコードが公開されています。実はかなりの物がSurface Shaderの形式で書かれているので、これを使って勉強すると効率よさそう Unity - Download Archive
基本的な構文
まずはここから
Unity公式シェーダリファレンス日本語訳 http://docs-jp.unity3d.com/Documentation/Components/SL-Reference.html
ShaderLabの基本構文 http://docs-jp.unity3d.com/Documentation/Components/SL-Shader.html
Properties{...}
http://docs-jp.unity3d.com/Documentation/Components/SL-Properties.html
Properties{} に入れると、インスペクタから各値を指定できるようになる。
- Range : スライドバー
- Color : 色
- 2D : テクスチャ
等。これらの値は glslの uniform変数的にこのマテリアルが適用されるメッシュの頂点すべてに適用されることになります。
- テクスチャ座標の取得の仕方
// Unity公式のtextureを用いるsurface shaderのサンプルより // http://docs.unity3d.com/Documentation/Components/SL-SurfaceShaderExamples.html Shader "Example/Diffuse Texture" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { // 中略 struct Input { float2 uv_MainTex; }; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) { o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb; } // 後略
という感じで、Propertiesで登録されるテクスチャのテクスチャ座標をシェーダの引数として使いたい場合は、float2 uv_MainTex
と名乗れば、自動で代入してくれて、tex2D関数の引数として使えるようになります。
参考:(2) テクスチャを貼る
Tags{...}
http://docs-jp.unity3d.com/Documentation/Components/SL-SubshaderTags.html
Queueタグ:
アルファテストするかとか、透明化とか、オーバーレイ優先かとか、描画の順番に関わる指定RenderTypeタグ:
とりあえず、"Opaque"(不透明) か"Transparent"(透明)か、を教えてあげるくらいの認識。いくつか試してみたけど、これを指定しなければならないと言うわけではない様子。
Pass{...}
Pass1個で、オブジェクト形状を1回レンダリングする。マルチパスも可能。
メモ:
後述する Surfce Shaderでは、コンパイラがPassを生成するため、Pass{} は存在しない。
ShaderLabのレンダリング設定項目(ステートメント)
http://docs-jp.unity3d.com/Documentation/Components/SL-Pass.html
OpenGLの固定パイプラインで、カリングやります、ブレンドします、アルファテストします、的なglEnable()をやっていきますが、それのイメージ。
- Material,
- Lighting on|off,
- cull Back|Front|off,
- Blend src dst,
的な感じ。固定機能シェーダで使うのが一般的だけど、
ちなみにPassの外(SubShader直下) に書くことも出来て、その場合SubShader内全パス共通設定になる。 (CommonState) この点については、下のページに説明あり。
http://docs-jp.unity3d.com/Documentation/Components/SL-SubShader.html
シェーダの書き方3種
違いは、このページの最下部に分かりやすくまとめてあります
以下、個人的な追記。
固定機能 (fixed function) シェーダ
http://docs-jp.unity3d.com/Documentation/Components/SL-Shader.html
ShaderLab のステートメント「のみ」を用いて記述すると、固定の関数に好みの変数をセットしてシェーダを作り上げることになります。
- マテリアルのDiffuseはこの色で、
- マテリアルのShininess はこのくらいの強さで
- マテリアルのテクスチャはこれを使って
- Alphaテストはこんな式で
- Blending はこんなタイプで
とか何とか、設定していきます。
固定パイプラインのイメージはこのページの上図。
ShaderLabの固定パイプラインの設定項目(ステートメント)はこちらが詳しい
Surface Shader サーフェスシェーダ
ポリゴンに着色するのに特化したシェーダ。Unityのシーン中のライティングも自動で適用される。それだけがしたいなら簡単に書けるぜ、と言う物。(と思った)
概要公式:
http://docs-jp.unity3d.com/Documentation/Components/SL-SurfaceShaders.htmlここも分かりやすい
その3 サーフェイスシェーダサンプルはこちら:
Unity - Surface Shader Examples根本:
#pragma surface func
指定すると、Surface Shader として扱われる
コンパイルして、 Vertex and Fragment Shaderのパス形式に変換してくれる。
(従って、Surface Shaderを書くときは、Pass{}ブロックは無い。)
CGPROGRAMブロック内に#pragma debug
と入れておくと、生成されたVertex and Fragmetn shaderのコードをUnityのインスペクタからみることが出来る最終的にSurfaceOutput をまとめ上げて出力するのが、Surface Shaderの役目。SurfaceOutputの仕様はこちら
http://docs-jp.unity3d.com/Documentation/Components/SL-SurfaceShaders.html
Vertex and Fragment Shader (Programmable Shader)
頂点を変形させたり、色を変化させながら塗ったりしたい場合はこちらを利用。 GLSLに慣れていたら、こっちの方が自然に感じると思われます。1ファイルに全部書いちゃうけど。
公式曰く
Unityのライトで反応しないシェーダについて言及します。(例:スペシャルエフェクト、Image Effects 等)
概要の説明はここ
http://docs-jp.unity3d.com/Documentation/Components/SL-ShaderPrograms.html読みやすいサンプル
http://docs-jp.unity3d.com/Documentation/Components/SL-VertexProgramInputs.htmlスクリーン座標などを用いた、マニアックな(お洒落な)サンプル
http://docs-jp.unity3d.com/Documentation/Components/SL-VertexFragmentShaderExamples.html
詳細な部分
Shaderのinput/output構造体のメンバに付けるセマンティクス
「この変数はシェーダ内では位置を意味するって決まってるよ、だからその値下さい」等とグラボ(パイプライン)に伝達する為の、意味(セマンティック)の指定。Vertex and Fragment Shader で、input や output の構造体を定義する際に利用する。
struct vertexInput { float4 vertex : POSITION; float4 texcoord0 : TEXCOORD0; }; struct fragmentInput{ float4 position : SV_POSITION; float4 texcoord0 : TEXCOORD0; };
COLOR
SV_POSITION
(プロジェクション後の座標)POSITION
(空間中の座標)TEXCOORD
NORMAL
(法線)TANGENT
(接線)WPOS
(Fragmentシェーダで、いま扱っているピクセルの座標)
※ これの正式な一覧が欲しいのだけど見つからない… これで全部ではないかも。
VertexFragmentShader のサンプルをみると、セマンティクスたくさん出てきます。
http://docs-jp.unity3d.com/Documentation/Components/SL-VertexFragmentShaderExamples.html
ShaderLabのビルトイン便利変数・構造体・関数など
のうち、よく使われているとおもう物メモ。
#include UnityCG.cginc
して利用する。
公式のリストはこちら
http://docs-jp.unity3d.com/Documentation/Components/SL-BuiltinValues.html
float4x4 UNITY_MATRIX_MVP
:
一般的な物体描画の時に利用。Unityのシーンから算出される変換行列は、このほかにもたくさん。_ScreenParams
:
現在描き込もうとしているスクリーンの大きさfloat4 _Time
,_SinTime
,_CosTime
,unity_DeltaTime
:
便利な時間関係の値が取得できる。
_SinTime
の使い方がおもしろい。
_SinTime.x
は sin(t/8) を意味する。 以下、 yの時は t/4, z で t/2 w で t
このあたりはこちらで実践的に解説されています
(Cg)シェーダ内で sin の値を使い、時間と共に色を変化させる - 強火で進め
struct appdata_base
,appdata_img
など:一般的によく使われる Vertex Shaderへのインプットとしての頂点構造
http://docs-jp.unity3d.com/Documentation/Components/SL-BuiltinIncludes.htmlstruct v2f_vertex_lit
,v2f_img
:
一般的によく使われる、Fragment Shaderへのインプットとしての構造体
など。UnityCG.cgincを読みましょう、ってことですな。
Cgのよく使う関数群
ShaderLab特有というわけでは無いけど、メモ。abs()
とか clamp()
とか lerp()
とか。便利っす。公式なのはこちらの、Cg Standard Library 参照。
http://developer.download.nvidia.com/cg/Cg_3.1/Cg-3.1_April2012_ReferenceManual.pdf