C++幼女先輩

プログラミング成分多め

【UNITY 2020.2.6f1】New Input System(1.0.2)を使ってみる

New Input Systemについて

新しい入力が出来ました
引き続き旧来の入力方法を使う事が出来ますが
これを期にInputSystemを覚えようと思います

旧来の方法

旧来のInputではInputManagerのAxes
下記のように入力を取得していました

h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
j = Input.GetButton("Jump");

New Input Systemを使う

細かいことはほかの人のブログで・・

まず、PackageManagerからInputSystemをInstallします
メニューのWindows PackageManagerから PackageManagerを起動し
左上のリストから、Packages: Unity Registryを選び、 Input Systemを検索
今回は最新の1.0.2 を選択しInstallします
ちなみに、Samplesからサンプルのパッケージをインストールする事もできます

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

インストールを終えたら、New Input Systemを使うように変更します
ProjectSettingsのPlayerSettingから、Active Input Handlingを Input System Package(New)に変更します
そうするとUNITYエディタが再起動します

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

これで、InputSystemが有効になり、旧来の入力が効かなくなります

InputSystemを設定する

InputSystemの設定は少し面倒です

まず、右クリックから Create-InputActionを行い、InputActionAssetを作成する
ダブルクリックを行い、ActionMaps、Actionsと、入力キーのぶんだけ作成します
例えば、移動はxzの2軸なのでMoveという名前で Vector2で作成します
キーボードだとWASDと矢印キーにそれぞれUp、Down、Left、Rightを設定
他にもGamePad、Touch、Joystick、XRも設定する
FireはActionTypeはButtonで、マウス左クリックやゲームパッドの右トリガーなどに割り当てる
そのほか使うボタンを登録します

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

そしてそれを登録すればよいのですが
めんどくさいので UNITYが用意したものを使います

PlayerInputコンポーネント

動かしたいオブジェクトに、AddComponentから PlayerInput を追加します
すでに基本的なキー入力のAssetが設定されているので、非常に手抜きができます
DefaultMapをPlayerにし、BehaviorをSendMessagesにする

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

実際に値を取得する時は下記のようになる

    public void OnMove(InputValue value) => move = value.Get<Vector2>();
    public void OnLook(InputValue value) => look = value.Get<Vector2>();
    public void OnFire(InputValue value) => fire = value.Get<float>() > 0;
    public void OnJump(InputValue value) => jump = value.Get<float>() > 0;

このように、Onアクション名 というCallbackで指定したアクションが取れます
コールバックで処理するのが面倒だなー、従来のようなポーリングで取りたい場合は
上記のようにコールバックで値を変数に保存してもいいですが
PlayerInputには、ポーリングをするインタフェースも用意されてます

    // InputActionを定義
    Private InputAction move, jump;

    void Start()
    {
        PlayerInput playerInput = GetComponent<PlayerInput>();

        // 各アクションの参照を取得
        move = playerInput.actions["Move"];
        jump = playerInput.actions["Jump"];
    }

    void Update()
    {
        Vector2 m = move.ReadValue<Vector2>();  // 2軸の値はVector2で取得
        bool j = jump.ReadValue<float>() > 0;  // bool値はfloat値で 0より大きいかで判断する
    {

これで、ポーリングでもイベントでも取得が可能です

AWSの操作をするSlackBotを作りたいのである

作りたいもの

クラウドを本格的に使う際に色々心配事もあるし、結局仕事でも使うでしょ?
例えば今月の利用金額を調べたり、Metrixを表示したり、起動中のインスタンス表示したり落としたり
これがPCでログインしたりせず、Slack上でコメントするだけで制御できることがどれだけ便利か

以前のプロジェクト

github.com

以前、Go言語の勉強用にGOSICKという名前で作った
これは当初、Goの色々な機能を使いたくてPluginを使いたかったりしたのでGoにした

ところが、この程度のBotであればデプロイを行わず、サーバレスにすべきなので
Serverless Frameworkで作り直そうとしていた
当初はAzureのBizSparkに入ってたりでAzureCSharpで作ろうとしていたが
SlackBot程度の処理負荷の低いものであればNodeがベストではないかと思い
AWS Nodeで作り直そうと思う

使用フレームワーク

サーバレスは実際は直接AWS上にコード書いてもいいが、ローカルでテストしたりするために
ServerlessFrameworkや AWS SAMといったものを使うと便利
その2者が有名なのでどちらを使おうかな・・

権限

権限をつける等は将来的には必要だろう
例えば社員誰でも請求額見れるとか問題がある会社も多いだろう
ユーザー単位でAPIに権限をつけるか、チャンネル単位か等の設計などは後回しで
まずは全員フル権限にする

コマンド形式(仮

メンションにするか、@なしで反応するかは後程考えるとして
まずは文字で単純に解析したいな
xxx をコマンド名として下記のようなコマンドを想定
また、; で複数コマンドを同時に出来るようにしようかな?

xxx ec2 list  
xxx ec2 down インスタンス名  
xxx ec2 list; lambda list; ...  

使用言語

Nodeで動かす。Typescriptにしたい

WSL2のポートをlocalhostに公開する

WSL2で開発する時、Dockerなどを使わなくともポートをWindows側から叩くことができる
これでWeb開発がよりスムーズになる
また、WSL2に使うメモリやプロセッサ数、Swapなども細かく設定し、PCリソースを管理することも可能

devblogs.microsoft.com

URP10.2.2 URPシェーダーをShaderLabで書いてみる

URPのシェーダーを作ろうとすると、UNITYからは全部ShaderGraphになる
ので、テキストエディタでShaderを書く事は推奨されていないようだし
実際に仕事でも、アーティストと会話するために、ノードエディタのShaderGraphを使う方が良いと思うが
勉強のためにあえてShaderLabで書いてみる

URP UnlitShaderを調査

まずは、最も簡単なはずのUnlitから書いてみる
テンプレートからはShaderLabは作れないので、ShaderGraphのUnlitを新規で作成します

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

床に適用してみた。テクスチャも影もなくなった
f:id:murasame-labo:20210205123921p:plain

作成されたUnlitShaderGraphからShaderLabのコードを取得するには、Inspectorから ViewGeneratedShader を選択するとコードが表示される
f:id:murasame-labo:20210205123528p:plain

パスは、通常パス、ShadowCaster、DepthOnlyの3つで、それがTransparent、Opaqueの両方あるので合計6個のパスがあります
おそらく、SRP Batchingのために、TransparentとOpaqueの両方のシェーダをまとめているんだと思う

Feature関連

                // Pragmas
                #pragma target 2.0
                #pragma only_renderers gles gles3 glcore
                #pragma multi_compile_instancing
                #pragma multi_compile_fog
                #pragma vertex vert
                #pragma fragment frag
    
                // DotsInstancingOptions: <None>
                // HybridV1InjectedBuiltinProperties: <None>
    
                // Keywords
                #pragma multi_compile _ LIGHTMAP_ON
                #pragma multi_compile _ DIRLIGHTMAP_COMBINED
                #pragma shader_feature _ _SAMPLE_GI
                // GraphKeywords: <None>
    
                // Defines
                #define ATTRIBUTES_NEED_NORMAL
                #define ATTRIBUTES_NEED_TANGENT
                #define FEATURES_GRAPH_VERTEX
                /* WARNING: $splice Could not find named fragment 'PassInstancing' */
                #define SHADERPASS SHADERPASS_UNLIT
                /* WARNING: $splice Could not find named fragment 'DotsInstancingVars' */

色々と書いてあるが、おおざっぱに
Instancing、Fog、dots instancing、ライトマップ系、アトリビュート、そしてshaderpass unlit
等設定しています
dots instancingとか、最近のUNITYの高速化、Data-Oriented Technology Stackの事でしょう
今度ちゃんと調べてみたいです

Includes

      #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
        #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl"
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"

これらのコードをIncludeしています
BuiltIn-Shaderではなく、URPのシェーダーを見に行ってますね

入出力

      struct Attributes
        {
            float3 positionOS : POSITION;
            float3 normalOS : NORMAL;
            float4 tangentOS : TANGENT;
            #if UNITY_ANY_INSTANCING_ENABLED
            uint instanceID : INSTANCEID_SEMANTIC;
            #endif
        };
        struct Varyings
        {
            float4 positionCS : SV_POSITION;
            #if UNITY_ANY_INSTANCING_ENABLED
            uint instanceID : CUSTOM_INSTANCE_ID;
            #endif
            #if (defined(UNITY_STEREO_MULTIVIEW_ENABLED)) || (defined(UNITY_STEREO_INSTANCING_ENABLED) && (defined(SHADER_API_GLES3) || defined(SHADER_API_GLCORE)))
            uint stereoTargetEyeIndexAsBlendIdx0 : BLENDINDICES0;
            #endif
            #if (defined(UNITY_STEREO_INSTANCING_ENABLED))
            uint stereoTargetEyeIndexAsRTArrayIdx : SV_RenderTargetArrayIndex;
            #endif
            #if defined(SHADER_STAGE_FRAGMENT) && defined(VARYINGS_NEED_CULLFACE)
            FRONT_FACE_TYPE cullFace : FRONT_FACE_SEMANTIC;
            #endif
        };

おそらく入力パラメータAttributesは #defineで有効にしたものが入ってくるのだろう
それにInstancing用のID

Varyingsは、InstancingやVR等で条件コンパイルされてるが、ポジション程度しかない

それらの入力値を使い、データを抽象化しているのか、シェーダーライブラリ内で使う構造体に変換しているのだと思われる
SurfaceDescriptionInputs、VertexDescriptionInputs、PackedVaryingsと変換関数がある

実際の処理

          #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/ShaderPass.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/Varyings.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Editor/ShaderGraph/Includes/UnlitPass.hlsl"

実際の処理はシェーダーライブラリの中だ
その中でも実際にシェーダーの中身は下記になる

PackedVaryings vert(Attributes input)
{
    Varyings output = (Varyings)0;
    output = BuildVaryings(input);
    PackedVaryings packedOutput = PackVaryings(output);
    return packedOutput;
}

half4 frag(PackedVaryings packedInput) : SV_TARGET 
{    
    Varyings unpacked = UnpackVaryings(packedInput);
    UNITY_SETUP_INSTANCE_ID(unpacked);
    UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(unpacked);

    SurfaceDescriptionInputs surfaceDescriptionInputs = BuildSurfaceDescriptionInputs(unpacked);
    SurfaceDescription surfaceDescription = SurfaceDescriptionFunction(surfaceDescriptionInputs);

    #if _AlphaClip
        half alpha = surfaceDescription.Alpha;
        clip(alpha - surfaceDescription.AlphaClipThreshold);
    #elif _SURFACE_TYPE_TRANSPARENT
        half alpha = surfaceDescription.Alpha;
    #else
        half alpha = 1;
    #endif

#ifdef _ALPHAPREMULTIPLY_ON
    surfaceDescription.BaseColor *= surfaceDescription.Alpha;
#endif

    return half4(surfaceDescription.BaseColor, alpha);
}

まあ、ここだけ見ると単純です

シンプルなUnlitシェーダー

白く塗りつぶすだけの非常に簡単なシェーダーを作った

Shader "MyShader/URPUnlit"
{
    SubShader
    {
        Tags
        {
            "RenderPipeline" = "UniversalPipeline"
            "RenderType" = "Opaque"
            "UniversalMaterialType" = "Unlit"
            "Queue" = "Geometry"
        }
        Pass
        {
            Name "Pass"

            // Render State
            Cull Back
            Blend One Zero
            ZTest LEqual
            ZWrite On

            HLSLPROGRAM

            // Pragmas
            #pragma target 4.5
            #pragma exclude_renderers gles gles3 glcore
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl"

            struct Attributes
            {
                float3 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float4 tangentOS : TANGENT;
            };
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
            };

            
            float3 TransformObjectToWorld(float3 positionOS)
            {
                return mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz;
            }

            float4 TransformWorldToHClip(float3 positionWS)
            {
                return mul(unity_MatrixVP, float4(positionWS, 1.0));
            }

            Varyings vert(Attributes input)
            {
                Varyings output = (Varyings)0;
                output.positionCS = TransformWorldToHClip(TransformObjectToWorld(input.positionOS));
                return output;
            }

            half4 frag(Varyings input) : SV_TARGET
            {
                return half4(1,1,1,1);
            }
            ENDHLSL
        }
    }
}

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

includeは2個あるが、UNITYのシェーダーのCORE的なものと、RPから入ってくるUNITY定数の宣言
思ったより簡単に書けたが、色々な処理を無視しているし
影とかは難しそうな気配・・
PS,XBOX,Switch等の対応とかも考えると、ShaderGraphで書く方が楽だろうなあ・・・

テクスチャマッピングする

これは非常に簡単だった
今までのBuiltIn-Shaderの作法にのっとり
Texture2DをPropertiesに出し、Texture2DとSamplerを宣言し
AttributesとVaryingsに TEXCOORD0を入れて
SAMPLE_TEXTURE2Dでマッピングした結果をリターンすればいい

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

意外と素直

影を落とす

"Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
をIncludeすることにした

そして今回はメインライトからの影のみを取るので
pragma multi_compile _ _MAIN_LIGHT_SHADOWS をつけた

shadowAttenuationを計算するのだが、ShadowMapをSampleするには、ワールド座標のPositionが必要なので
positionWSを計算することに
TransformObjectToWorld(input.positionOS)
で簡単に取得できた

ワールド座標系のオブジェクトポジションを使い
TransformWorldToShadowCoord(input.positionWS)
をすると、ShadowCoordが取得できるので、そこから
GetMainLightを使い、メインライトの情報、影の情報が取れる
今回はライトカラーなどは使わずshadowAttenuationだけを使い、テクスチャにそのまま乗算した

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

とりあえず影はできた

今回の完成シェーダコード

Shader "MyShader/URPUnlit"
{
    Properties
    {
            [NoScaleOffset] MainTex("_MainTex", 2D) = "white" {}
            [HideInInspector][NoScaleOffset]unity_Lightmaps("unity_Lightmaps", 2DArray) = "" {}
            [HideInInspector][NoScaleOffset]unity_LightmapsInd("unity_LightmapsInd", 2DArray) = "" {}
            [HideInInspector][NoScaleOffset]unity_ShadowMasks("unity_ShadowMasks", 2DArray) = "" {}
    }


    SubShader
    {
        Tags
        {
            "RenderPipeline" = "UniversalPipeline"
            "RenderType" = "Opaque"
            "UniversalMaterialType" = "Unlit"
            "Queue" = "Geometry"
        }
        Pass
        {
            Name "Pass"

            // Render State
            Cull Back
            Blend One Zero
            ZTest LEqual
            ZWrite On

            HLSLPROGRAM

            // Pragmas
            #pragma target 4.5
            #pragma exclude_renderers gles gles3 glcore
            #pragma vertex vert
            #pragma fragment frag


            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS

            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl"

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

            TEXTURE2D(MainTex);
            SAMPLER(samplerMainTex);

            struct Attributes
            {
                float3 positionOS : POSITION;
                float3 normalOS : NORMAL;
                float4 tangentOS : TANGENT;
                float4 uv0 : TEXCOORD0;
            };
            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float4 texCoord0 : TEXCOORD0;
                float3 positionWS: TEXCOORD1;
            };

            Varyings vert(Attributes input)
            {
                Varyings output = (Varyings)0;
                output.positionCS = TransformWorldToHClip(TransformObjectToWorld(input.positionOS));
                output.texCoord0 = input.uv0;
                output.positionWS = TransformObjectToWorld(input.positionOS);
                return output;
            }

            half4 frag(Varyings input) : SV_TARGET
            {
                half4 o = SAMPLE_TEXTURE2D(MainTex, samplerMainTex, input.texCoord0.xy);
                Light l = GetMainLight(TransformWorldToShadowCoord(input.positionWS));

                return o*l.shadowAttenuation;
            }
            ENDHLSL
        }
    }
}

Instancingやメイン以外のライト等、いろいろすっ飛ばしているので実用性はないが
URPのシェーダーは、こんな感じで書く事は可能だ
ShadowCasterやDepthOnlyパスは消してしまったが同じように簡単に作る事ができそう

ただし、URPはバージョンアップで色々変わってしまうので
ShaderGraphを使う方が楽と思う

URP10.2.2でBuiltin Shaderに沿って影を出すのはかなり難しい

前回まで色々頑張ってBuiltIn Shaderに沿って影を出そうとしたけど
昔のURPバージョンでは少しの変更で出せていたが
最新バージョンでは、BuiltIn Shaderのシェーダー変数にも値が入っておらずなかなか出来ずにいた

もちろん、細かくURPを読んで、同じようなロジックを移植すればBuiltIn Shaderでも影を作れるかもしれないが
URP7あたりから、影のアルゴリズムが大きく変わり、互換性を持つことが難しくなったようだ

docs.unity3d.com

影のアルゴリズムが色々と最適化された
BuiltInシェーダーでURP RPで影を落とす調査はあきらめ
URPの調査に入る事にする

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では大きく変わってるのかなあ・・・
って事で、後日調査しますか。。

URPの勉強をする。概要

趣旨

Unityが従来の固定レンダリングパイプライン(BuiltIn RP)の後継にURPを指名した
ので、早急にURPを調査する必要がある

blogs.unity3d.com

UNITYのレンダリングパイプライン

SRP

UNITYのレンダリングは下記のようなパイプラインで行われる

それらのパイプラインは、UNITYエンジンでハードコーディングされており、BuiltIn RPと呼ばれる
UNITY2018より、PreviewとしてScriptable Render Pipeline(SRP)がテスト実装された
SRPでは、レンダリングパイプラインをプログラマが自由に変更できるようになった

blogs.unity3d.com

LWRP, HDRP, URP

レンダリングパイプラインを変更すると、シェーダーも全部作り直す必要があり
非常にコストが高いため
ある程度汎用的な2つのパイプラインをUNITY社は用意をした

ハイクオリティーレンダリング用途のHDRP(High Definition Render Pipeline)と
低スペック端末用のLWRP(Light Wait Render Pipeline)

そして、従来LWRPと呼んでいたものを、UNITY2020からURP(Universal Render Pipeline)と改名し
BuiltIn RPの後継に指名した

note.com

コードリポジトリ

BuiltIn Shaderのコードリポジトリは見つけられなかったが、下記でバージョンごとにダウンロードできる ダウンロードタブを押すと、ビルトインシェーダーを選択できる
unity3d.com

レンダーパイプラインはリポジトリが公開されているので、対象のバージョンをTagで指定してダウンロードできる
github.com

使っているUNITYのRenderPipelineのバージョンを調べるには、UnityPackageManagerでRP等で検索してバージョンを調べる
例えば、Unity2020.2.1 だと、v10.2.2である
f:id:murasame-labo:20210120031600p:plain

シェーダーの書き方

UNITYのシェーダーはHLSLベースの、ShaderLabという言語で書く
テキストエディタで作る
シェーダーのフル機能を使う事が出来る
私の知る限りだが、ビジュアルスクリプティングでは一部の表現が出来ない

ビジュアルスクリプティング

以前より優良アセットとして、ShaderForge、Amplify Shader Editorがある(あった)
ShaderForgeは開発中止されたが、Amplifyは今でも使われていて、URPにも対応しているらしい
UNITY社はShaderGraphを無料で提供し、当然URPにも対応している
一部出来ないことはあるかもしれないが、ノードベースでシェーダーを書きたい人の選択肢になればと

URP プロジェクトを作ってみる

プロジェクトの作成は簡単
UnityHubで新規プロジェクト作成時にURPプロジェクトのテンプレートがあるので作成する

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

そこに、仮に独自シェーダーのモデルをImportすると

f:id:murasame-labo:20210120045304p:plain
ShaderError

URPに対応していないシェーダーなのか、シェーダーエラーになる

仮に、URP/Unlitシェーダーを適用すれば、テクスチャがはられたのみのモデルが表示される

f:id:murasame-labo:20210120045024p:plain
URP/Unlit

URP/Unlitシェーダーを覗く

github.com

チラ見で気になるのが、SRP batching
軽くみたかんじ、BuiltIn RPでは同じマテリアルでしかBatchingが出来なかったが
SRP(URP)では、異なるマテリアルであっても、シェーダーが同じであればInstancing出来るようだ
そのため、他のシェーダーとも共通化してあるのかな

        // SRP batching compatibility for Clear Coat (Not used in Lit)
        [HideInInspector] _ClearCoatMask("_ClearCoatMask", Float) = 0.0
        [HideInInspector] _ClearCoatSmoothness("_ClearCoatSmoothness", Float) = 0.0

URPには、 "RenderPipeline" = "UniversalPipeline" Tagが必要そう

独自のシェーダーパスも簡単に作れそうだ
qiita.com

今度は簡単なURP対応シェーダーを作ろうと思う