【Unity/ShaderLab】ShaderLabでビルボードを実装する【URP】

ネコニウム研究所

PCを利用したモノづくりに関連する情報や超個人的なナレッジを掲載するブログ

【Unity/ShaderLab】ShaderLabでビルボードを実装する【URP】

UnityのShaderLabでビルボードを実装したい!URPに対応させつつ!

概要

この記事では、UnityのShaderLabでURPに対応させつつビルボードを実装する手順を掲載する。

ビルボードとは、簡単に描くと常にカメラの方を向く板ポリゴンのこと。

左がビルボード無し、中央がスクリプトのビルボード、右が今回のShaderLabのビルボード。
スクリプトのビルボードはY軸のみのビルボードなので、若干歪んで見える。
ShaderLabのビルボードはZ軸にもビルボードの効果が出てて、近づいても歪まない。

仕様書

環境

  • Unity 2022.2.4f1

手順書

下記のシェーダーを作成して、任意のマテリアルに設定して、SpriteRenderなどに設定する。

Shader "URP/BillboardShader"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float fogFactor : TEXCOORD1;
                float4 vertex : SV_POSITION;
                float3 normal : NORMAL;
            };

            CBUFFER_START(UnityPerMaterial)
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _Cutoff;
            CBUFFER_END

            v2f vert(appdata v)
            {
                float4 objScale = float4(
                    length(float3(UNITY_MATRIX_M[0].x, UNITY_MATRIX_M[1].x, UNITY_MATRIX_M[2].x)),
                    length(float3(UNITY_MATRIX_M[0].y, UNITY_MATRIX_M[1].y, UNITY_MATRIX_M[2].y)),
                    length(float3(UNITY_MATRIX_M[0].z, UNITY_MATRIX_M[1].z, UNITY_MATRIX_M[2].z)),
                    0
                );

                v2f o;

                o.vertex = TransformObjectToHClip(
                    TransformWorldToObject(
                        (mul(UNITY_MATRIX_I_V, v.vertex * objScale) + (mul(unity_ObjectToWorld, float4(0, 0, 0, 1)))).xyz
                    )
                );
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.fogFactor = ComputeFogFactor(o.vertex.z);
                o.normal = TransformObjectToWorldNormal(v.normal);
                return o;
            }

            float4 frag(v2f i) : SV_Target
            {
                float4 col = tex2D(_MainTex, i.uv);
                clip(col.a - _Cutoff);
                col.rgb = MixFog(col.rgb, i.fogFactor);
                return col;
            }
            ENDHLSL
        }
    }
}

まとめ(感想文)

スクリプトを使ったY軸ビルボードとは違って、このShaderLabを使ったビルボードではZ軸に対してもビルボード的な表現になるので、カメラに近づいても板感が無い。

板感や歪みはないんだけども、これは私のスキルの問題でShaderLabのビルボードではアルファ値を考慮したリアルタイムな影を描写できなかった。

この丸影は非表示の球体の影。
あと、このスプライト自体も光や他の影の影響を描写させることが出来なかった。

ここいらも描写させたい場合は後述の参考にさせていただいた記事のとおりにShader Graphで実装させた方が簡単。

3D的な影を使わないケースや3D空間上に表示するGUIなんかの用途には、このShaderLabのビルボードが使えそう。

参考文献・引用

下記の記事のShader Graphを参考にさせて頂きました。
とても勉強になりました。ありがとうございました。