知識0からのUnityShader勉強

知識0からのUnityShader勉強

UnityのShaderをメインとして、0から学んでいくブログです。

【UnityShader】Tagブロック #4

前回の成果

f:id:soramamenatan:20190602151549p:plain

inspectorから色の変更が出来るようになった

soramamenatan.hatenablog.com


今回やること

3Dオブジェクトの透明度を変更させます!
いよいよシェーダーっぽくなってきましたね。

今回もおもちゃラボ様を参考にします。

nn-hokuson.hatenablog.com


ソースコード

Shader "Custom/translucent"
{
    SubShader {
        Tags { "Queue" = "Transparent"}
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard alpha:fade
        #pragma target 3.0

        struct Input{
            float2 uv_MainTex;
        };

        void surf(Input IN, inout SurfaceOutputStandard o){
            o.Albedo = fixed4(0.6f,0.7f,0.4f,1);
            o.Alpha = 0.6f;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

やっていることは単純そうで、

  • ベースカラーを変更している
  • アルファ値を変えている

の2つのようです。

しかし前回、前々回で書いてきたものと異なる点が他にあることにお気付きでしょうか。

// 今まで
Tags { "RenderType"="Opaque" }

// 今回
Tags { "Queue" = "Transparent"}

このtagブロックと

// 今まで
#pragma surface surf Standard fullforwardshadows

// 今回
#pragma surface surf Standard alpha:fade

#pragma宣言、この2つが今までと今回で変わっています。

なので、今回は今まで触れていなかった部分に触れていこうと思っています。


Tagブロック

Tagブロックの中に"Queue"と記述があります。
これはレンダリングの順序を指定することができるものです。
今回の場合だとTransparentを指定しているので、他のオブジェクト全てを描画してからTransparentを描画します。

Transparentってなんだ

わかるそれな

Queueタグにはすでに定義済みのものがあるので、それについて説明します。

Queue名 用途 番号
Background 背景 1000
Geometry 不透明なオブジェクト 2000(デフォルト)
AlphaTest アルファテストするもの 2450
Transparent アルファブレンディングするもの 3000
Overlay 最後にレンダリングするもの 4000

このQueueタグに定義されているものの1つがTransparentです。

docs.unity3d.com


アルファブレンディングとは

専門用語を専門用語で説明するなってやつですね。

アルファブレンディングとは、コンピュータグラフィックスの描画技法の一種で、ある画像にアルファ値を掛け合わせることで半透明な画像を重ねる技法のことである。 アルファブレンディングとは何? Weblio辞書:より引用

噛み砕いて説明すると、半透明オブジェクトのことです。

話は逸れますが、アルファテストとOverlayの最後にレンダリングするものの例は、また別で説明します。


なんでTransparentを指定してんの?

Tagブロックの中に"Queue"と記述があります。
これはレンダリングの順序を指定することができるものです。
今回の場合だとTransparentを指定しているので、他のオブジェクト全てを描画してからTransparentを描画します。

と前述しました。

なぜ、そうしないといけないのかはZバッファが関係しています。

このサイト様の解説がとてもわかりやすいのですが、念の為自分の言葉でも解説しておきます。 ch.nicovideo.jp


Zバッファの仕組み

f:id:soramamenatan:20190520193202j:plain

15-06-06《半透明ポリゴンの描画順問題[接触篇]》:習慣 不沈空母をつくる - ブロマガ:より引用

描画を行う際に、最初に描画されるAとピクセル毎の距離が記録されます。
A以外の部分は何も描画されていないのでそのままとなります。
次のBを描画する際にピクセル毎にZバッファに記録されているAの距離と、まだ記録されていないBとの距離を比較します。
比較した値のZバッファの方がカメラに近ければ(今回の場合はAが描画されている領域)、すでにBよりカメラに近いポリゴンが描画されていると判断して、Bの描画がスキップされます。
それと同時にBの距離がZバッファに記録されます。
これによって、描画順に関係なく、AとBとの前後関係が正確に描画されます。


描画順を変えてみる

Aから描画した場合

f:id:soramamenatan:20190520193557j:plain

15-06-06《半透明ポリゴンの描画順問題[接触篇]》:習慣 不沈空母をつくる - ブロマガ:より引用

まずAがZバッファに記録されてからBが記録されます。

Bから描画した場合

f:id:soramamenatan:20190520193757j:plain

15-06-06《半透明ポリゴンの描画順問題[接触篇]》:習慣 不沈空母をつくる - ブロマガ:より引用

まずBがZバッファに記録されてからAが記録されます。

これで何が言いたいのかというと、
両方とも不透明の場合、見た目上影響は出ません

半透明の場合どうなるん

f:id:soramamenatan:20190521100354j:plain

15-06-06《半透明ポリゴンの描画順問題[接触篇]》:習慣 不沈空母をつくる - ブロマガ:より引用

※Aは半透明

左がBを先に描画してからA、
右がAを先に描画してからBです。

理想としている描画方法は『左』です。

なんでこうなるの?

先ほど、長々と説明したZバッファの仕組みが関係してきます。

次のBを描画する際にピクセル毎にZバッファに記録されているAの距離と、まだ記録されていないBとの距離を比較します。 比較した値のZバッファの方がカメラに近ければ(今回の場合はAが描画されている領域)、すでにBよりカメラに近いポリゴンが描画されていると判断して、Bの描画がスキップされます。

ここの部分ですね。
自分なりにまとめると、

  1. Aを描画する
  2. Bを描画しようとする
  3. AとBが重なっている部分があるのを確認する
  4. Aの方がカメラに近いのでBを描画しない

という理由から描画されないということになります。

ちなみに、

f:id:soramamenatan:20190521110009j:plain 15-06-06《半透明ポリゴンの描画順問題[接触篇]》:習慣 不沈空母をつくる - ブロマガ:より引用

アルファマスクで完全に透明な部分はZバッファに記録されないので描画順は気にしなくて良さそうです。

今回は長くなりすぎたので次に回します