목표
- URP 쉐이더그래프 중 Unlit 그래프를 이용해 직접 Lit 쉐이더 만들기
1. Diffuse 구현
- 커스텀 함수를 이용하여 메인라이트의 방향, 색상, 감쇠를 얻어낸다.
Custom_Mainlight.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
half4 shadowCoord = TransformWorldToShadowCoord(WorldPos);
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
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half shadowStrength = GetMainLightShadowStrength();
ShadowAtten = SampleShadowmap(shadowCoord,
TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture),
shadowSamplingData, shadowStrength, false
);
#endif
}
-
주변광을 얻어와야 하므로, 주변광을 얻기 위한 커스텀 함수와 서브 노드를 이용한다.
-
Sub_AdditionalLights
-
여기에 들어가는 커스텀 함수 :
Custom_AdditionalLights.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void AdditionalLights_half(half3 WorldPos, half3 WorldNormal, half3 WorldView, out half3 Diffuse)
{
half3 diffuseColor = 0;
#ifndef SHADERGRAPH_PREVIEW
WorldNormal = normalize(WorldNormal);
WorldView = SafeNormalize(WorldView);
int pixelLightCount = GetAdditionalLightsCount();
for (int i = 0; i < pixelLightCount; ++i)
{
Light light = GetAdditionalLight(i, WorldPos);
half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
diffuseColor += LightingLambert(attenuatedLightColor, light.direction, WorldNormal);
}
#endif
Diffuse = diffuseColor;
}
- PBR 라이팅 공식을 이용해 조립한다.
2. Soft Shadow 적용
- 이대로는 하드 쉐도우만 적용되므로, 키워드를 이용해 소프트 쉐도우를 적용한다.
- Keyword - Boolean : Shader Feature, Global
- _MAIN_LIGHT_SHADOWS_CASCADE
- _SHADOWS_SOFT
3. Fog 적용
- 여기에 필요한 커스텀 함수 2가지
Custom_ComputeFogFactor.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void ComputeFogFactor_float(in float z, out float fogFactor)
{
float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z);
#if defined(FOG_LINEAR)
fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w);
#elif defined(FOG_EXP) || defined(FOG_EXP2)
fogFactor = (unity_FogParams.x * clipZ_01);
#else
fogFactor = 0.0h;
#endif
}
Custom_ComputeFogIntensity.hlsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void ComputeFogIntensity_float(in float fogFactor, out float fogIntensity)
{
fogIntensity = 1;
#if defined(FOG_EXP)
fogIntensity = saturate(exp2(-fogFactor));
#elif defined(FOG_EXP2)
fogIntensity = saturate(exp2(-fogFactor * fogFactor));
#elif defined(FOG_LINEAR)
fogIntensity = fogFactor;
#endif
}
4. Specular, Rim Light 추가
-
쉐이더그래프의 월드 Normal, View 벡터들은 크기가 1이 아니므로
반드시 정규화시켜서 사용해야 한다.
-
블린 퐁 스페큘러와 림라이트까지 적용한 커스텀 릿 쉐이더를 완성하였다.
비교
- 좌측 : PBR, 우측 : Custom Lit