夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

ゼロから始めるUnityShader開発 第五章 透明度 半透明なシェーダーを書く

本日はシェーダー学習枠です。

〇不透明なオブジェクトの描画順

描画処理が行われる際は一般的に遠くにあるものから塗りつぶされるように描画が行われています。

 半透明なオブジェクトは不透明なオブジェクトの描画が完了した後に処理が実行されます

 これはRenderDocなどのデバッグツールを使用することで実際に目にすることができます。

 

DrawOpaqueObjectsで不透明なオブジェクトが描画

必ず不透明なオブジェクトの後にDrawTransparentObjectsが描画される

これは不透明なオブジェクトがシェーダーによって計算されたピクセルをそのまま塗りつぶすのに対して、半透明なオブジェクトはシェーダーによって描画される際にすでに描画されているピクセル色の影響を考慮して計算結果が描画される仕組みになっているためです。

 まずは上記の例でDrawTransparentObjectsに含めるようにする必要があります。

〇RenderType Transparent

RenderTypeはShaderLabのTagsブロックで記述できるシェーダーの属性です。

        Tags { "RenderType"="Transparent" }

 上記のように記述することでRender Queueが3000へとデフォルトで指定されるようになりDrawTransparentObjectsのイベントで処理が行われるようになります。

Render Queueは描画順番に関する値ですが、2000番は不透明オブジェクト、3000番は半透明オブジェクトのように値によって描画イベントを変える仕組みがあります。

〇AlphaBlend

 RenderTypeをTransparentに変えるだけでは処理の場所が変わるだけで透明度を扱うことはできません。

 透明度を扱うためにはすでに描画されたピクセルと新たにシェーダーによって計算されたピクセルをどのように合成するかという設定が必要です。

この設定をAlphaBlendと呼びます。

ja.wikipedia.org

UnityではShaderLab内のSubShader内で*Blender 〇〇**のように定義します。

  SubShader
    {
        Tags { "RenderType"="Transparent" }
        LOD 100

        Blend One One//追加
        Pass
        {
      ・・・・
        }

Blendは2つの引数を使用でき、第一引数でBlend操作、第二引数でBlend係数として定義できます。

今回の場合はOneを使用しており、これはシェーダーによって計算した色をそのまま使用することを示します。

これによって半透明なシェーダーが完成します。

今回の場合One Oneのため、DrawOpaqueObjectsで計算されたピクセル色にDrawTransparentObjectsの計算結果を合成しています。

一般的なペイントソフトなどではこの処理をオーバーレイと呼びます。

docs.unity3d.com

〇ソースコード

Shader "Unlit/Transparent"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Transparent" }
        LOD 100

        Blend One One
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = TransformObjectToHClip(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                // sample the texture
                float4 col = tex2D(_MainTex, i.uv);
                col.a = 0.5f;
                return col;
            }
            ENDHLSL
        }
    }
}