夜風のMixedReality

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

ゼロから始めるUnityShader開発 第五章 ShaderLabの記述 URP用のシェーダーを書く

本日は昨日に引き続きShader枠です。

昨日に引き続き先日筆者の所属している会社で行ったShader勉強会の内容をまとめていきます。

redhologerbera.hatenablog.com

redhologerbera.hatenablog.com

〇URPとは?

URPはUnityの比較的新しいグラフィックシステムを指します。

 従来はUnityで構築されたレンダーパイプライン(レンダリングを行う処理フロー)は固定されており、開発者はいじることはできませんでした。

 Unity2018以降にこのレンダーパイプラインをC#スクリプトで操作可能なパイプラインとしてScriptableRenderPipeline(SRP)が登場しました。

 これはデータをどのように扱うかをUnityが提供しているものから独自にカスタマイズできるようになったと言い換えることもでき、例えば光の強さの単位は通常ではIntensityという単位がデフォルトで使用されていますが、カスタマイズすることで現実の物理単位であるルクスやカンデラを用いるといったこともできます。

当然ですが、カスタマイズの方法によってはハイスペックPCをもってしても処理が重くなるということも起こりえます。

 またいきなりすべてをカスタマイズをすることもハードルは高いです。

 このためUnityではSRPのテンプレートとして2種類のものを提供しています。

 一つがハイエンドPC向けのHDRP、そしてもう一つがモバイルからハイスペックPCまで幅広く対応しており、従来のビルドインに置き換わる予定のUniversalRenderPipelineです。

docs.unity3d.com

URPではSurfaceShaderなど一部のシェーダーが使用できません。

これによって従来のシェーダーの一部がエラーを吐いてしまい使用できなくなることがあります。

URPでは従来通りUnityCG.cgincを使用することもできますが、URP用にHLSLファイルが提供されておりこの機能を使用することでよりURP用のシェーダーを構築することができます。

〇Core.hlslへの置き換え

先日までの次のシェーダーをURPの提供するhlslファイルに置き換えていきます。

Shader "Unlit/TutorialShader"
{
    Properties
    {
        _MainColor("Color" ,color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
            };

            float4 _MainColor;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = _MainColor;
                return col;
            }
            ENDCG
        }
    }
}

Core.hlslPackages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlslにあります。

URPを導入している場合必ず導入されます。

まずはCGPROGRAM~ENDCGをHLSLPROGRAM~ENDCG、UnityCG.cgincをCore.hlslに置き換えます。

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

この状態では当然ですがエラーを吐いてしまいます。

理由としてはUnityCG.cgincとCore.hlslでは関数名に互換がないためです。

そのため対応していない型や関数をCore.hlslへ置き換えます。

対応していない関数は次の二点です。

・UnityObjectToClipPos()

・fixed4型

〇TransformToHClip()

UnityObjectToClipPos()はUnityの座標軸に頂点を配置する関数ですがCore.hlslではTransformObjectToHClip()が使用されます。

 o.vertex = TransformObjectToHClip(v.vertex);

UnityCG.cgincで座標変換系の関数はUnity○○To○○の名前が多く使用されますがCore.hlslではTransform○○To○○の形になります。

fixed4型はUnityCG.cgincで定義されている型のため使用できないのでfloat4型を使用します。

  float4 frag (v2f i) : SV_Target
            {
                float4 col = _MainColor;
                return col;
            }

以上でURP用にシェーダーの置き換えが完了しました。

今回のシェーダーではさほど問題はないですが、特にライトを扱うシェーダーの多くはURPに対応していないため今回のような変換のポイントを押さえておくことは重要です。