C++幼女先輩

プログラミング成分多め

UNITY URPのお勉強。URP対応の簡単なシェーダー作ってみる

UNITYちゃんを表示

URPのプロジェクトに旧来のUNITYちゃんを表示してみると

f:id:murasame-labo:20210123010041p:plain

シェーダーが対応していないよね
もちろん、シェーダーをURPのものにすれば、とりあえずエラーは解消されるし
URPやHDRPに対応したUNITYちゃんもダウンロード可能なので
そちらを使うのが良いが
ちょうどいいので、これでシェーダーを試してみようと思う

f:id:murasame-labo:20210123010402p:plain

GUI関連もエラーが出ているなあ・・・

簡単なURPシェーダー

先日の調査でURPのパスはDeferredやDepthOnly等複数のパスが存在した

github.com

が、推測ではForwardLitパスだけで、簡単な表示は出来そうだ

テンプレート

UNITYのメニューから、Create->Shader->Unlitでデフォルトのシェーダーを作成し貼り付ける

f:id:murasame-labo:20210123011924p:plain

ライティング無し、テクスチャのみ、半透明に対応してないのでチークは変になってるが
最低限のシェーダーは作れた
影もない

仮に一部のマテリアルをURPのLitに差し替えると

f:id:murasame-labo:20210123013638p:plain

影は表示されている

Templateで生成されたものをみると

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

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

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

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

特に名前のないパスがあるだけで、ShadowCaster等のパスもないので当然

一応?礼儀正しく? Passの名前をちゃんとしていし、動きが同じことを確認

        Pass
        {
            Name "ForwardLit"
            Tags { "LightMode" = "UniversalForward" }

            CGPROGRAM

ShadowCaster Pass

古よりのUNITYのシェーダーパス、ShadowCasterを追加すれば影を落とす事ができる

        Pass {
            Name "ShadowCaster"
            Tags { "LightMode" = "ShadowCaster" }

            ZWrite On ZTest LEqual

            CGPROGRAM
            #pragma target 3.0


            #pragma vertex vertShadowCaster
            #pragma fragment fragShadowCaster


            struct VertexInput {
                float4 vertex : POSITION;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
            };

            VertexOutput vertShadowCaster(VertexInput v) {

                VertexOutput o = (VertexOutput)0;
                o.pos = UnityObjectToClipPos(v.vertex);
                return o;
            }

            float4 fragShadowCaster(VertexOutput i) : SV_TARGET {
                return 0;
            }


            ENDCG

        }

あえて、古いシェーダーを書いている
URPのシェーダーを読んでいると今はCGPROGRAMではなくHLSLPROGRAMを使い
CG言語ではなくHLSLでシェーダーを書くのが主流っぽい?し
GPU Instancing等が入っているが、今回は古のシェーダーで調査だ

f:id:murasame-labo:20210123014902p:plain

このとおり、ShadowCasterはうまくいった(ただし、Shadowを受け取る側はできていないので、床はURPのシェーダーを使っている)

ShadowRecieve

昔のUNITYではShadowRecieveパスがあったような記憶があるけど今はライトのパスで行っている

まずは古のシェーダーで書いてみる

過去に書いた自分の記事の通りに
murasame-labo.hatenablog.com

この通りに書くが影が表示されない

SHADOW_ATTENUATION、LIGHT_ATTENUATIONがきかない(1,1,1) が帰ってきてるようなかんじ
UNITYの質問で同じような事があったので調べる
forum.unity.com

pragma multi_compile _ _MAIN_LIGHT_SHADOWS

pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE

を書けばいいというようなことを書いているが、それでもダメ
色々なフラグを追加してもダメ

該当部分のコードをみてみると

void MainLight_half(float3 WorldPos, out half3 Direction, out half3 Color, out half DistanceAtten, out half ShadowAtten)
{
    #if SHADERGRAPH_PREVIEW
        Direction = half3(0.5, 0.5, 0);
        Color = 1;
        DistanceAtten = 1;
        ShadowAtten = 1;
    #else
        #if SHADOWS_SCREEN
            half4 clipPos = TransformWorldToHClip(WorldPos);
            half4 shadowCoord = ComputeScreenPos(clipPos);
        #else
            half4 shadowCoord = TransformWorldToShadowCoord(WorldPos);
        #endif
            Light mainLight = GetMainLight(shadowCoord);
            Direction = mainLight.direction;
            Color = mainLight.color;
            DistanceAtten = mainLight.distanceAttenuation;
 
        #if !defined(_MAIN_LIGHT_SHADOWS) || defined(_RECEIVE_SHADOWS_OFF)
            ShadowAtten = 1.0h;
        #endif
 
        #if SHADOWS_SCREEN
            ShadowAtten = SampleScreenSpaceShadowmap(shadowCoord);
        #else
            ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
            half shadowStrength = GetMainLightShadowStrength();
            ShadowAtten = SampleShadowmap(shadowCoord, TEXTURE2D_ARGS(_MainLightShadowmapTexture,
            sampler_MainLightShadowmapTexture),
            shadowSamplingData, shadowStrength, false);
        #endif
    #endif
}

該当部分がちゃんと計算されるようなパスになるようにしたつもりだけど上手く動かない

シェーダーをコンパイルすると下記のエラー
f:id:murasame-labo:20210123071916p:plain

'ComputeScreenPos': no matching 1 parameter function
Compiling Vertex program with DIRECTIONAL SHADOWS_SCREEN VERTEXLIGHT_ON _MAIN_LIGHT_SHADOWS_CASCADE
Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_RGBM_ENCODING
Disabled keywords: FOG_LINEAR FOG_EXP FOG_EXP2 LIGHTPROBE_SH SHADOWS_SHADOWMASK DYNAMICLIGHTMAP_ON LIGHTMAP_ON LIGHTMAP_SHADOW_MIXING DIRLIGHTMAP_COMBINED UNITY_NO_DXT5nm UNITY_ENABLE_NATIVE_SHADOW_LOOKUPS UNITY_METAL_SHADOWS_USE_POINT_FILTERING UNITY_NO_SCREENSPACE_SHADOWS UNITY_PBS_USE_BRDF2 UNITY_PBS_USE_BRDF3 UNITY_NO_FULL_STANDARD_SHADER UNITY_HARDWARE_TIER1 UNITY_HARDWARE_TIER2 UNITY_HARDWARE_TIER3 UNITY_COLORSPACE_GAMMA UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS UNITY_LIGHTMAP_DLDR_ENCODING UNITY_LIGHTMAP_FULL_HDR UNITY_VIRTUAL_TEXTURING UNITY_PRETRANSFORM_TO_DISPLAY_ORIENTATION UNITY_ASTC_NORMALMAP_ENCODING SHADER_API_GLES30  
  
invalid subscript 'pos'
Compiling Vertex program with DIRECTIONAL SHADOWS_SCREEN VERTEXLIGHT_ON _MAIN_LIGHT_SHADOWS_CASCADE
Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_RGBM_ENCODING
Disabled keywords: FOG_LINEAR FOG_EXP FOG_EXP2 LIGHTPROBE_SH SHADOWS_SHADOWMASK DYNAMICLIGHTMAP_ON LIGHTMAP_ON LIGHTMAP_SHADOW_MIXING DIRLIGHTMAP_COMBINED UNITY_NO_DXT5nm UNITY_ENABLE_NATIVE_SHADOW_LOOKUPS UNITY_METAL_SHADOWS_USE_POINT_FILTERING UNITY_NO_SCREENSPACE_SHADOWS UNITY_PBS_USE_BRDF2 UNITY_PBS_USE_BRDF3 UNITY_NO_FULL_STANDARD_SHADER UNITY_HARDWARE_TIER1 UNITY_HARDWARE_TIER2 UNITY_HARDWARE_TIER3 UNITY_COLORSPACE_GAMMA UNITY_HALF_PRECISION_FRAGMENT_SHADER_REGISTERS UNITY_LIGHTMAP_DLDR_ENCODING UNITY_LIGHTMAP_FULL_HDR UNITY_VIRTUAL_TEXTURING UNITY_PRETRANSFORM_TO_DISPLAY_ORIENTATION UNITY_ASTC_NORMALMAP_ENCODING SHADER_API_GLES30

ちょっと影関連の計算はURPでは大きく変わってるのかなあ・・・
って事で、後日調査しますか。。