【Unity】為ShaderGraph制作自定義Main Light節點


概述

在百度第一頁,關於這個問題基本上都來自於同一個文章,原文章地址我沒有找到,因此附上其中一篇轉載:在Unity 2019.2中擴展Shader Graph,實現自定義光照
然而和標題一樣,這個實現是基於2019.2版本的,移植到更新的版本時會出各種各樣的問題。

這篇博客記錄了我嘗試把主光源信息 (MainLight) 相關內容移植到目前 Unity 最新版本 (2020.2) 的 URP 渲染管線時遇到的問題與解決方案。

前置問題

這篇文章需要你至少懂得:

  • 在 Unity 中制作基於文件的自定義節點 (Custom Node) 與子圖 (Sub Graph)。

同時如果你能夠有下面這些能力,能獲得更通順的閱讀體驗(當然沒有也行):

  • 下載了 Unity 2021.2 版本
  • 簡單接觸過 Unity 的 URP Shader 代碼編寫,並且使用過 Shader Graph。
  • 懂得訪問不存在的網站,或者能夠登錄 Github。

解決方案

文章的解決方案基於 Github 上的項目 Shader Graph Custom Lighting Sample Project 實現,這個項目是基於 Unity 2019.2 的。
直接采用我在概述中提到的鏈接里的解決方案會報各種各樣的錯,甚至無法編譯成功(對百度指指點點)。

這個 Github 倉庫中有用的部分包括下面的路徑,倉庫中的其余部分是作者自己做的示例:

  • \Assets\Includes
  • \Assets\Sub Graphs

這兩個文件夾下的文件提供了一些光照節點。其中 Includes 文件夾下的 .hlsl 文件是自定義節點的源文件。

直接移植功能基本正常,可能會出現一些小 bug,但只要它不出現,你就可以當它不存在。

這篇博客僅基於這個 Git 倉庫制作 Get Main Light 節點獲取主光源信息,解決了移植到 2021.2 版本時出現的無法接受來自主光源的陰影問題,如果其他版本也出現了這個問題,你也可以嘗試這個博客的解決方案。
同時,稍微修改了一下原倉庫中的節點設置,以提供更容易使用的精度 (Precision) 控制方法。

源文件 (.hlsl)

首先給出自定義主光源節點的源文件 MainLight.hlsl

#ifndef CUSTOM_LIGHTING_INCLUDED
#define CUSTOM_LIGHTING_INCLUDED

#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT

void MainLight_float(float3 WorldPos, out float3 Direction, out float3 Color, out float DistanceAtten, out float ShadowAtten)
{
#if SHADERGRAPH_PREVIEW
    Direction = float3(-0.5, 0.5, 0);
    Color = float3(1, 0.95, 0.8);
    DistanceAtten = 1;
    ShadowAtten = 1;
#else
#if SHADOWS_SCREEN
    float4 clipPos = TransformWorldToHClip(WorldPos);
    float4 shadowCoord = ComputeScreenPos(clipPos);
#else
    float4 shadowCoord = TransformWorldToShadowCoord(WorldPos);
#endif
    Light mainLight = GetMainLight(shadowCoord);
    Direction = mainLight.direction;
    Color = mainLight.color;
    DistanceAtten = mainLight.distanceAttenuation;
    ShadowAtten = mainLight.shadowAttenuation;
#endif
}

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 = half3(1, 0.95, 0.8);
    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;
    ShadowAtten = mainLight.shadowAttenuation;
#endif
}

#endif

這個文件刪除了原倉庫CustomLighting.hlsl中的其余函數,僅保留了 MainLight_floatMainLight_half 用於不同精度的運算。

同時,在文件頭部增加了三個 pragma 用來修復陰影問題。(修復之前的 ShadowAtten 沒有辦法正常使用,但其余 Out 參數正常)
其中,第一個 _MAIN_LIGHT_SHADOWS 是產生陰影是才會用到的參數,實際上並不需要(這里我們其實只需要接受陰影),因此刪掉也完全OK。
第二個參數 _MAIN_LIGHT_SHADOWS_CASCADE 是關鍵的參數,用於接受陰影,不能缺少,缺少后就會出現 ShadowAtten 失效的問題。
第三個參數 _SHADOWS_SOFT 可以讓陰影邊緣柔化,如果注釋掉可以得到硬邊緣的陰影,可以根據需要采用或者刪除。
增加的三個 pragma

#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _SHADOWS_SOFT

最后,修改了這兩個函數在 Shader Graph 節點預覽中的初始設置,使得修改是否發揮了作用更容易被檢測到。
具體來說,我使不同精度下的光照方向不同,從而使切換精度時節點預覽中的光照方向發生改變。另外,使光線不是純白色而是微微泛黃(通過修改Color實現),讓光照顏色加入運算時會對預覽圖產生影響。
對於 float 精度:

#if SHADERGRAPH_PREVIEW
    Direction = float3(-0.5, 0.5, 0);
    Color = float3(1, 0.95, 0.8);
    DistanceAtten = 1;
    ShadowAtten = 1;
#else

對於 half 精度:

#if SHADERGRAPH_PREVIEW
    Direction = half3(0.5, 0.5, 0);
    Color = half3(1, 0.95, 0.8);
    DistanceAtten = 1;
    ShadowAtten = 1;
#else

子圖 (SubGraph)

子圖保持與倉庫相同的名字Get Main Light,在節點連線上與原倉庫相同:

MainLight (Custom Fuction) 節點的精度 Precision 設置為 Use Graph Precision :

再在這個子圖的 Graph Settings 中將 Precision 設置為 Switchable ,這樣就可以在使用子圖的時候直接在 Shader Graph 中更換精度了。

需要更換精度時,只需要在使用了這個子圖的地方設置子圖的節點屬性中的精度 Precision 即可:

按照前文的設置,我們在更換精度時,節點預覽界面中的光照方向應該會發生改變,從而讓我們確信調用的函數確實發生了變化。

下載鏈接

鏈接:https://pan.baidu.com/s/1PS94YZHFGnF8GuCqY8GZGQ
提取碼:rfun
文件包含一個 .hlsl 源文件,以及一個 Sub Graph,鏈接掛掉的話請評論或私信告知。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM