unity シェーダのお勉強③ 草をはやすシェーダに学ぶ
*目次
Thank you Eric!
ざっとしてか見れてないけど、素敵なチュートリアルがあったので紹介。
roystan.net
今回はこの中でも「草をはやす」シェーダを見ていきます。
You will learn・・・
You will learn to write a geometry shader to generate blades of grass from an input mesh's vertices, and use tessellation to control the density of the grass.
roystan.net
このページを見ることで、草について学ぶことができる(雑魚雑魚翻訳)
とまぁ、チュートリアルを終えると風になびく葉っぱを理解できるぜ。ってことらしい。
まぁ、とりあえず。Grass.shaderを開いてごらん。
はしょりにはしょりますが。
頂点シェーダの後に「CGINCLUDE」のブロックがあるのがわかりますか。
CGINCLUDE #include "UnityCG.cginc" #include "Autolight.cginc" #include "Shaders/CustomTessellation.cginc"
ここですね。これは後で役立つよ。というような感じで順を追って説明してくれているようす。
問題は私の基礎力が足りなさ過ぎて異次元の解釈になってしまっているのでこれ以上記事に言及するのはやめようとおもう。
ということで適当に抽出する。
git上にソースコードは公開されているが、チュートリアルの関係からか、
草をはやすシェーダ部分以外もモリモリの森である。ので、とりあえず必要そうな部分を引っ張ると
構成はこうなる
・Grass.shader
・CustomTessellation.cginc(Grassが参照してた)
・TessellationExample.shader(Grassが参照してた)
とりあえずそのままUnityにぶち込んでみる。
バージョンは4.28f1
gyazo.com
D&Dで放り込む
gyazo.com
そのまま放り込むとIncludeに失敗する。ディレクトリの構成がおかしいから(もともとShadersにあるものを引っ張り出してる)
gyazo.com
まずはGrassを調整する
・ "Roystan/Grass" ⇒ Grassに変更。(たぶんこれしなくても動くかも。
・#include "Shaders/CustomTessellation.cginc" ⇒ #include "CustomTessellation.cginc"
こんな感じ。これでもう一回Unityを見てみる。
Errorが変わっていることがわかる。調整がたりない。
gyazo.com
212行目。normalがねーぜ。と言われているが・・・
float4 frag (geometryOutput i, fixed facing : VFACE) : SV_Target { float3 normal = facing > 0 ? i.normal : -i.normal; float shadow = SHADOW_ATTENUATION(i); float NdotL = saturate(saturate(dot(normal, _WorldSpaceLightPos0)) + _TranslucentGain) * shadow; float3 ambient = ShadeSH9(float4(normal, 1)); float4 lightIntensity = NdotL * _LightColor0 + float4(ambient, 1); float4 col = lerp(_BottomColor, _TopColor * lightIntensity, i.uv.y); return col; }
あるよね。float3 での宣言そのものはあっているだろうから、同一行の「i.normal」が怪しそう。
ということでgeometryOutput の定義を見てみる。
struct geometryOutput { float4 pos : SV_POSITION; #if UNITY_PASS_FORWARDBASE float3 normal : NORMAL; float2 uv : TEXCOORD0; // unityShadowCoord4 is defined as a float4 in UnityShadowLibrary.cginc. unityShadowCoord4 _ShadowCoord : TEXCOORD1; #endif };
normalの宣言の部分がdefineチックなIFで囲まれている。たぶんここだろう。
「UNITY_PASS_FORWARDBASE」がなんなのか軽くググってもわからず。環境依存くさいけど。とりあえずエラーになってるから外してみる。
gyazo.com
いっぺんに全部出してほしいぜ・・・
とりあえず該当コードを見てみる。
geometryOutput VertexOutput(float3 pos, float3 normal, float2 uv) { geometryOutput o; o.pos = UnityObjectToClipPos(pos); #if UNITY_PASS_FORWARDBASE o.normal = UnityObjectToWorldNormal(normal); o.uv = uv; // Shadows are sampled from a screen-space shadow map texture. o._ShadowCoord = ComputeScreenPos(o.pos); #elif UNITY_PASS_SHADOWCASTER // Applying the bias prevents artifacts from appearing on the surface. o.pos = UnityApplyLinearShadowBias(o.pos); #endif return o; }
また例の定数があるなぁ。とりあえずdefine周りは外してみる。
gyazo.com
イエス。buildしてみたらなんだかよくわからないけどうまくいった。あとは適当なPlaneにマテリアルつけて使ってみる。
gyazo.com
gyazo.com
デフォルトの設定だと寂しい感じになる。Tessellation UniFormを調整するといい感じ茂ってくれる。
tessellation(10)
gyazo.com
他にも設定がるようなので、参考にされたし。
おわり
Windのところをちょちょいといじると風にもなびく。すげい。
gyazo.com