【UnityShader】ステンドグラス #11
前回の成果
LOD、CGPROGRAM、ENDCG、#pragma target、FallBackについて理解しました。
今回やること
今回はステンドグラスのようなシェーダーを実装していきます。
前準備
SceneにPlaneを置き、今回制作したMaterialのinspectorにステンドグラスの画像をアタッチします。
画像はこちらのサイト様よりDLさせて頂きました。
https://pixabay.com/ja/photos/%E3%82%B9%E3%83%86%E3%83%B3%E3%83%89-%E3%82%B0%E3%83%A9%E3%82%B9-%E7%AA%93%E3%81%8B%E3%82%89%E3%81%99-63204/pixabay.com
ソースコード
Shader "Custom/stainedGlass" { Properties { _MainTex("Texture", 2D) = "white" {} } SubShader { Tags { "Queue" = "Transparent" } LOD 200 CGPROGRAM #pragma surface surf Standard alpha:fade #pragma target 3.0 struct Input { float2 uv_MainTex; }; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = ((c.r * 0.3f + c.g * 0.59f + c.b * 0.11f) < 0.2) ? 1 : 0.4f; } ENDCG } FallBack "Diffuse" }
やっていることは、Albedoとアルファ値を変えているだけですが、
o.Alpha = (c.r * 0.3f + c.g * 0.59f + c.b * 0.11f) < 0.2) ? 1 : 0.4f;
これがマジックナンバーの嵐で、アルファ値をどうしたいのかわかりません。
c.r * 0.3f + c.g * 0.59f + c.b * 0.11f
これは何をしているのかを解説していきます。
結論から述べるとこれはグレースケールをする値となります。
なので今回のシェーダーのsurf関数を少しいじると
void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = dot(c.rgb, float3(0.3f, 0.59f, 0.11f)); o.Alpha = 1; }
こんな感じでグレースケールになります。
今回グレースケールを用いる理由
テクスチャの色はtex2Dで取得できます。
しかし、取得できる色はRGBAのカラー情報なので、黒色だったらアルファ値を1にするということができません。
ここでグレースケールにすることによって、明度で明るい色か暗い色かを判定することができるので使用しています。
? 1 : 0.4f
次は
o.Alpha = (c.r * 0.3f + c.g * 0.59f + c.b * 0.11f) < 0.2) ? 1 : 0.4f;
の? 1 : 0.4fについて解説していきます。
これは三項演算子というもので、簡単にいうとif文を短くするものです。
例えば、
int a = 10;
があって、aが10ならaを5に、10でないなら10にしたいとします。
これを普通に書くと、
int a = 10; if (a == 10) { a = 5; } else { a = 10; }
このようになると思います。
しかし、これだと冗長なので、
int a = 10; a = a == 10 ? 5 : 10;
このようにすることで、コードを短くすることができます。
構文はこのようになっています。
条件式 ? true : false
今回の場合ですと、グレースケールした値が0.2以下の場合はアルファ値を1に、0.2より大きい場合は透明度を0.4にしています。
結果
お〜〜〜!ステンドグラスっぽくなってます!
ソースコードにコメント付与
Shader "Custom/stainedGlass" { // プロパティ Properties { // テクスチャのデータ _MainTex("Texture", 2D) = "white" {} } // Shaderの中身の記述 SubShader { // 半透明オブジェクトを一番最後に描画する Tags { "Queue" = "Transparent" } // しきい値 LOD 200 // cg言語記述 CGPROGRAM // 透過させる #pragma surface surf Standard alpha:fade // Shader Model #pragma target 3.0 // input構造体 struct Input { // テクスチャのデータ float2 uv_MainTex; }; // テクスチャのデータ sampler2D _MainTex; // surf関数 void surf (Input IN, inout SurfaceOutputStandard o) { // テクスチャのピクセルの色 fixed4 c = tex2D(_MainTex, IN.uv_MainTex); // ベースカラー o.Albedo = c.rgb; // グレースケールから透明度を決める o.Alpha = ((c.r * 0.3f + c.g * 0.59f + c.b * 0.11f) < 0.2) ? 1 : 0.4f; // グレースケール用 // fixed4 c = tex2D(_MainTex, IN.uv_MainTex); // グレースケールにする // o.Albedo = dot(c.rgb, float3(0.3f, 0.59f, 0.11f)); // o.Alpha = 1; } // Shaderの記述終了 ENDCG } // SubShaderに失敗した時に呼ばれる FallBack "Diffuse" }
今回はこれで終了です。
次回もシェーダーへの理解を深めていこうと思います!