Amazonで商品を見るセール会場へ

Unityのアニメーション用シェーダー:加算・Cutout・Alphaマスクの選び方

Unityのアニメーション演出で使うShaderを、加算・両面表示・Cutout・別画像のAlphaマスク・深度表示の5用途に分けて整理します。最初に描画方式(Built-in/URP/HDRP)と対象(MeshRenderer/Particle System/uGUI)を確認してください。同じ「透明」という目的でも必要なShaderの構成は異なります。

現行仕様の参照はUnity 6.3 LTS、旧AlphaTestの説明はUnity 2018.4です。掲載コードは元記事の資料を保持しており、今回Unityでコンパイル・描画・性能測定を行ったコードではありません。旧固定機能Shaderや不足するファイルを、現在の全環境で使える完成例としては扱いません。

目次

目的とレンダーパイプラインから選ぶ

項目・症状選び方・確認先
粒子や光を明るく重ねたい加算ブレンド。背景の色、頂点色とAlpha、深度書き込みを確認。通常の透過画像とは別の見た目になる。
薄い板の裏側も表示したいカリング設定。Cull Offは裏面を除外しないが、ライティングや影の処理まで同時に対応させる指定ではない。
境界を動かして画像や文字を出したいAlpha Cutout/Alpha Clipping。素材のAlphaとThresholdを使う。基本設定はCutout記事、書き順の素材は文字記事へ。
カラー画像を別の白黒画像で隠したいマスクを読むチャンネル・UV・元Alphaとの合成方法を決める。本文の旧コードはマスクのRへAlphaを置き換える。
カメラの深度を画像として見たいBuilt-inのDepth Texture/OnRenderImageとSRPの方式を分ける。本文のC#だけでは深度表示Shaderも保存処理も揃わない。

URPのQuadで輪郭を抜く場合はURP UnlitのAlpha Clippingが候補です。Canvas上のImageで使う場合はStencil、RectMask2D、頂点色、UI描画なども確認する必要があるため、uGUI用Shaderの記事へ進んでください。Mesh向けMaterialをImageへ指定しただけで同じマスク動作になるとは限りません。

1.加算と通常のAlphaブレンドを使い分ける

次の2つはBlendなどの設定断片です。Properties、頂点処理、フラグメント処理を含む完全なShaderファイルではありません。加算の指定はソース色をソースAlphaで重み付けして背景へ足すため、暗い背景と明るい背景で見た目が変わります。

Blend SrcAlpha One
Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }

通常のAlphaブレンドは背景側にも1−ソースAlphaの重みを使います。下の指定は、RGBにAlphaを事前乗算していない出力を想定した基本形です。事前乗算の出力に同じBlend指定を重ねると、期待と異なる濃さになることがあります。

Blend SrcAlpha OneMinusSrcAlpha
Cull Off Lighting Off ZWrite Off

Unity公式のBlend説明を参照し、黒/灰/白の背景でAlpha 0・中間・1を比較してください。ZWrite Offは透明度を作る指定ではなく、深度バッファへ書き込むかを決めます。描画順やオブジェクトの重なりも別に確認します。

旧Mobile/Particles/Additiveの配布例

keijiro氏の加算Shader Gistは2015年作成のBuilt-in用資料です。取得したファイルにはv2fの座標名がpositionなのにFog用の呼び出しでo.vertexを参照する不整合が見られました。使用版と該当マクロを照合して修正・コンパイルする必要があり、保存して適用するだけで動く例としては案内しません。

Shaderの行数だけでは負荷を比較できません。Pass数、テクスチャ参照、描画面積、重なり、GPU、コンパイル結果を揃えた測定が必要です。「通常版より行数が多くても差は小さい」「Mobile版なら必ず速い」という判断はここでは行いません。

2.板の裏側も描画する:Cullの確認

Cull Offは背面カリングを無効にする指定です。次の旧ShaderはPass内にCull Offを持ち、AlphaTestで残す領域を選びます。AlphatestとSetTextureを使う固定機能の旧例なので、URP/HDRPへそのまま移植する手順ではありません。

Shader "Custom/Transparent_Cutout_DoubleSide" {
    Properties {
        _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader {
        Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
        Pass {
            Cull Off
            Lighting Off
            Alphatest Greater [_Cutoff]
            SetTexture [_MainTex] { combine texture }
        }
    }
}

この例のAlphatest GreaterはAlphaがCutoffより大きい領域を残します。Cutoffと同じ値を残すclip(alpha−cutoff)の条件とは区別してください。詳細は2018.4のAlpha testingを参照します。

確認には表裏を見分けられるQuadを1枚置き、カメラ位置を反対側へ変えます。手前の面が見えない場合は、対象ShaderのCull、対象の向き、CameraのLayerを順に確認します。Cullの公式資料は描画面の選択を説明しており、両面化だけで表裏の照明や影を同じにするとは説明していません。

3.Cutoutに色や加算を加える場合

元記事のTint設定画像は旧例の資料です。下に保持する加算Cutoutコードには_TintColorのプロパティも乗算処理もありません。画像にTint欄があることだけを根拠に、掲載コードで色変更まで実装済みとはしません。

TintColor付きカットアウトシェーダー

次のコードはBlend SrcAlpha Oneと旧AlphaTestを組み合わせています。Cull Offは含まれていないため、前の両面例の性質を引き継ぐとは限りません。Cutoutなら半透明を使わないという基本説明も、加算Blendを追加したこの派生例へ無条件には適用しません。

Shader "Unlit/Transparent Cutout Additive" {
    Properties {
        _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
        _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader {
        Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
        LOD 100
        Blend SrcAlpha One
        Pass {
            Lighting Off
            Alphatest Greater [_Cutoff]
            SetTexture [_MainTex] { combine texture }
        }
    }
}

旧記事で紹介した加算CutoutのPastebinには_TintColor、雲テクスチャ2枚、スクロール、Soft Particlesなどを含む別のSurface Shaderがあり、上の短いコードと同一ではありません。取得時に全文は確認できましたが、更新履歴・作者の利用許諾・現在の動作版は確定していません。現行URPの完成品として配布し直すことはせず、旧参照先として示します。

高機能カットアウトシェーダー

まず輪郭だけを制御したいなら、加算やSoft Particlesを足す前に、素材のAlphaとThresholdの組み合わせを確認してください。

4.カラー画像と別のAlphaマスクを使う

旧Unlitテンプレートから作った例は、カラーを_MainTex、マスクを_AlphaTexから読みます。元記事のテンプレート画面は現在のUnityで作成した検証画像ではありません。

Unlitシェーダーの作成
  1. RGBを持つカラー画像と、Rにマスク値を持つ画像を別に用意します。マスクの黒は0、白は1です。マスクのAlphaチャンネルを読むコードではありません。
  2. 旧Shaderを調べる場合は名前Unlit/Transparent_AlphaMaskの完全コードを.shaderへ保存し、そのShaderを指定した専用Materialへ両Textureを割り当てます。Built-in系のUnityCG.cgincを使う例として扱い、URPへ名前だけ変更して使いません。
  3. このコードは2枚へ同じUVを使用し、_MainTex_STの変換だけを適用します。2画像の配置・縦横比を揃え、マスクだけ別のTiling/Offsetが必要ならUV処理も変更する必要があります。
  4. まず白と黒のマスクを切り替え、次にグラデーションを指定して、中間の透過と重なりを比較します。元画像に透明な余白を持つ画像でも確認してください。
Alpha maskプロパティの追加
Shader "Unlit/Transparent_AlphaMask"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _AlphaTex ("Alpha mask (R)", 2D) = "white" {}
    }
    SubShader
    {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha
    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"

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

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

        sampler2D _MainTex;
        sampler2D _AlphaTex;
        float4 _MainTex_ST;

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

        fixed4 frag (v2f i) : SV_Target
        {
            fixed4 col = tex2D(_MainTex, i.uv);
            fixed4 col2 = tex2D(_AlphaTex, i.uv);
            return fixed4(col.r, col.g, col.b, col2.r);
        }
        ENDCG
    }
}
}

fragが返すAlphaはcol2.rで、カラー画像col.aとの乗算ではありません。元画像の透明な余白でもマスクRが1ならAlphaは1になります。元の輪郭も残したい場合は、元Alphaとマスクを乗算するなど、目的に合わせた合成へ変更して検証する必要があります。ここでは元のコード自体は書き換えていません。

また、この旧例はBlendを指定する一方、ZWrite Offを明示していません。透明部分が深度を書き込んで後ろの描画を遮るなど、重なりに問題がないか確認が必要です。ZWriteの既定と透明描画の説明を参照し、前後のQuadを入れ替えた比較も行ってください。旧結果画像は現行版での検証結果ではありません。

マスク付きUnlitシェーダーの結果

数値を読むマスクTextureのsRGBはTexture Import設定を確認します。カラー画像と同じ扱いにせず、圧縮・Mip Map・Filterによる階調の変化も切り分けます。白黒画像を保存しただけでは、Shaderが必要とするチャンネルへ入ったことにはなりません。

5.深度表示の旧C#:不足するものを確認する

次のPostProcessDepthGrayscaleはCameraのDepth Textureを要求し、OnRenderImageでMaterialを指定してGraphics.Blitするコードです。深度をグレースケールへ変換するShaderの本体と、PNGなどへ保存する処理は含まれていません。Custom/DepthGrayscaleという名前だけでShaderを作成することもできません。

using UnityEngine;
[ExecuteInEditMode]
public class PostProcessDepthGrayscale : MonoBehaviour
{
public Material mat;
void Start()
{
    GetComponent<Camera>().depthTextureMode = DepthTextureMode.Depth;
}

void OnRenderImage(RenderTexture source, RenderTexture destination)
{
    Graphics.Blit(source, destination, mat);
}
}

OnRenderImageの公式説明によると、このコールバックはBuilt-in向けで、Scriptable Render Pipelineでは利用できません。URPのScriptableRenderPassやHDRPのFullScreen Custom Passは別の実装になります。

  1. 旧例を調べる前にレンダーパイプラインを確認します。URP/HDRPでコールバックが呼ばれない問題を、Materialの未指定だけで解決しようとしません。
  2. Built-inでも、このクラスを置く同じGameObjectにCameraが必要です。ファイル名をPostProcessDepthGrayscale.csへ合わせ、Material matへ対応する完全なShaderのMaterialを指定する必要があります。本文と既存配布フォルダーだけでは深度変換Shaderは揃いません。
  3. 深度Textureへ含まれる対象を確認します。Built-inのDepth Texture説明には、ShaderのShadowCaster PassやOpaqueの描画範囲などの条件があります。すべての透過オブジェクトが深度へ含まれる前提にしません。
  4. カメラの近・遠クリップ、深度の線形化、対応APIを決めた完全な深度表示Shaderを別に用意してから、手前/奥を比較します。ファイル保存が目的ならReadback、画像エンコード、保存先なども別処理として実装・検証します。

元記事の深度画像を保存しますが、このC#だけで生成・書き出しを再現できる証拠にはしません。Depth of Field用の素材を自動で作れる手順としての説明も外しています。

デプスシェーダーの結果

表示がおかしいときの確認順

項目・症状選び方・確認先
Materialがピンクになる使用パイプライン・Shaderの完全性・Consoleのコンパイルエラーを先に確認。旧固定機能/Surface Shader/UnityCGの例をSRP対応とみなさない。
裏からだけ見えないCullとオブジェクトの向き。両面化は照明・影の対応とは別。
透明なのに後ろの物が消えるZWrite、Queue、ZTest、描画順を確認。Alpha値だけでは深度の扱いは決まらない。
別マスクで元の透明余白が埋まる旧AlphaMaskは元Alphaを無視してRへ置換。目的に合う合成処理とUVを確認。
Cutoffで端まで消えないImport後のAlpha最大値、比較演算、Filter・圧縮・Mip Mapを確認。0/1の見た目を全Shader共通としない。
深度が表示・保存されないBuilt-inか、CameraとMaterialが揃うか、深度変換Shaderがあるか。C#に保存処理はない。

配布ファイルと参照資料

既存のコード保存先は01.hlsl=両面の旧Cutout、02.hlsl=旧加算Cutout、03.hlsl=AlphaMask、04.cs=深度表示用C#です。.hlslという拡張子でも先頭がShader宣言のファイルは、ShaderLabとして扱う際に.shaderで保存する必要があります。Blend設定断片や深度変換Shaderまで全部配布されているフォルダーではありません。リポジトリのMIT許諾を、外部Gist/Pastebinのコードへ自動で拡張しないでください。

輪郭の出し方はCutoutの素材・Import・Threshold設定、書き順を持つ文字は手書き文字アニメーションへ進んでください。画面全体を透かすUI演出はCanvasGroup/RenderTextureの用途を分けて確認できます。

アニメーションと演出の記事は、ほかにもあります。

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

Unityのおすすめ書籍

開発PCの選び方

周辺機器の優先度

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次