3
2

[Unity]ShaderGraphで影だけを描画する

Last updated at Posted at 2024-06-20

仕事上の需要で、キャラクターやオブジェクトの影だけが落ちて、それ以外は描画されないようなshaderが必要になりインターネットの海で見つけたのが以下の記事。
https://qiita.com/kochiyukimoto/items/a687531ab94d21aa0801

DirectionalLightの影を落とすだけなら以下の画像のような効果がつくれます
image.png

ただ、spotLightなどいわゆる追加ライトの影が落ちないようになっていため、現状のURPでの
対応を含めShaderGraph対応をしてみました。

結論

コードだけ知りたい方はここだけ見れば大丈夫です。
変更点はGetAdditionalLightで引数が1つ増えてます。

//既存のコードはこれ
Light AddLight0 = GetAdditionalLight(i.worldPos);
//新規がこれ
Light AddLight0 = GetAdditionalLight(i, worldPos,1);

これだけで追加ライトの対応は完了です。 とりあえず1にしておけば動くが、なぜ1でよいのかは調べ中。
追記(2024/09/01)
最後の引数はshadowMaskというプロパティで、どうにも渡す値によらずこのプロパティがある方でのみライトの影減衰率を渡しており、これが影響している模様。

ShaderGraph対応

カスタムノード化したコードがこちら。

#ifndef YOTHUBALAB_RECEIVESHAODW_INCLUDED
#define YOTHUBALAB_RECEIVESHADOW_INCLUDED


#ifndef SHADERGRAPH_PREVIEW
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#endif
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT

void ReceiveShadow_half(float shadowAlpha,float3 worldPos, out half shadowAttenuation)
{
    #ifdef SHADERGRAPH_PREVIEW
    shadowAttenuation = 1.0;
    
    #else
    half4 shadowCoord = TransformWorldToShadowCoord(worldPos);
    Light mainLight = GetMainLight(shadowCoord);
    half shadow = mainLight.shadowAttenuation;
    int pixelLightCount = GetAdditionalLightsCount();
    for(int i = 0; i < pixelLightCount; i++)
    {
        Light AddLight0 = GetAdditionalLight(i, worldPos,1);
        half shadow0 = AddLight0.shadowAttenuation;
        shadow *= shadow0;
    }
    
    
    shadowAttenuation = shadow * shadowAlpha;
    #endif
   
}


#endif

カスタムノード自体の詳細は省きますが、ifdef SHADERGRAPH_PREVIEW
で分岐している箇所だけ説明するとShaderGraphのエディタ上で表示されるpreviewの描画でライト周りの関数にアクセスできないため、分岐で処理を分けています。
参考 https://blog.unity.com/ja/engine-platform/custom-lighting-in-shader-graph-expanding-your-graphs-in-2019

使用例

CustomNode化したコードをさらにサブグラフ化してしようしております。(GetShadow)
サブグラフの出力であるShadowAttenuationは影部分で0,そうでない部分で1になるような数値ですので、
OneMinusしてあげることで、影部分では1、そうでない部分では0となるようにします。
それをアルファに入力してあげることで、影部分以外を描画しないようなMaterialを作成できます。
image.png
image.png

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2