반응형

 

 

이번 포스팅은 Shader Graph에서 Unlit Shader 기반으로 커스텀 라이팅 구현 중 간단한 Lambert구현에 대해 작성합니다.

 

 

기본 Lambert 구현


기본적으로 Lambert를 구현하기 위해서는 Normal Vector와 Light Vector를 Dot연산해서 구현합니다.

하지만 Normal Vector 노드는 있지만 Light Vector 노드는 없습니다, 그래서 Custom Function이라는 노드를 이용해 코드를 작성해서 기능을 만들어야합니다.

 

#if SHADERGRAPH_PREVIEW
	lightDir = half3(0.5f, 0.5f, 0.0f);
	lightColor = 1;
#else
	Light light = GetMainLight();
	lightDir = light.direction;
	lightColor = light.color;
#endif

Custom Function 노드를 생성후 톱니 버튼을 누른 뒤 위 사진 우측처럼 세팅합니다.

 

그리고 나머지 NDotL연산을 하면 램버트가 구현됩니다.

 

 

 

 

Custom Function 외부 파일 불러오기


이전에는 위 Type을 String으로 해서 노드에 직접 코드를 입력헀지만 기본적으로 매우 불편합니다.

그래서 유니티 디렉토리 내부에 .hlsl 확장자 파일을 만들어서 코드를 작성해도 동작하게 됩니다.

하지만 따로 hlsl 파일 생성하는 기능이 없어 메모장이나 아무 파일만들어서 직접 확장자 변경해야합니다.

 

 

Shadow 처리


이슈 발견

https://blogs.unity3d.com/kr/2019/07/31/custom-lighting-in-shader-graph-expanding-your-graphs-in-2019/

 

 

셰이더 그래프의 커스텀 조명: 2019 버전 그래프 확장 - Unity Technologies Blog

Unity 에디터 2019.1이 출시되면서 셰이더 그래프(Shader Graph) 패키지의 프리뷰가 공식적으로 종료되었습니다! 2019.2 버전에도 셰이더 그래프에 더 많은 기능이 추가될 예정입니다. 2019 버전에서 향상된 기능 커스텀 함수 및 서브그래프 업그레이드 이...

blogs.unity3d.com

위 자료에 있는 내용을 참고해서

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;
   ShadowAtten = mainLight.shadowAttenuation;
#endif
}

위 코드를 작성하고 자료에 있는 노드대로 구현했지만 

 

작동되지 않습니다.

 

 

이슈 해결

URP의 Include 형식 쉐이더들은 Packages/Universal RP/Shaders에 들어 있습니다, 해당 이슈를 추적하기 위해 GetMainLight()함수 부터 추적했습니다.

 

 

일단 핵심 원인은 Shadows.hlsl 파일의 위 코드입니다, 쉐이더가 그림자 데이터를 요청하지 않거나 쉐도우가 꺼진 경우에 무조권 1.0을 리턴한다는 내용인데 Unlit Shader가 그림자 데이터를 요청하지 않고 있는 것 같습니다.

 

그래서 위 조건문을 무시하고 아래 코드를 강제로 끄집어내서 제 CustomLight 함수에 수정을 해봤습니다.

 

/**
* worldPos : 월드 픽셀 포지션

* lightDir : 메인 라이트 방향 벡터
* lightColor0 : 메인 라이트 컬러
* distanceAtten : 컬링마스크에 의해 컬링되면 1, 아니면 0 (No확실)
* shadowAtten : Cast Shadow 값
**/
void CustomLight_half(float3 worldPos, out half3 lightDir, out half3 lightColor0, out half distanceAtten, out half shadowAtten)
{
#if SHADERGRAPH_PREVIEW			//! 쉐이더 그래프 프리뷰에서 보이는 결과
	lightDir = half3(0.5, 0.5, 0);
	lightColor0 = 1;
	distanceAtten = 1;
	shadowAtten = 1;
#else

#if SHADOWS_SCREEN	//! Screen Space Shadow 사용할때 (No확실)
   half4 clipPos = TransformWorldToHClip(worldPos);
   half4 shadowCoord = ComputeScreenPos(clipPos);
#else
   half4 shadowCoord = TransformWorldToShadowCoord(worldPos);	//! 월드 공간좌표를 그림자 공간 좌표로 변환하는 함수 (No확실)
#endif

   Light mainLight = GetMainLight();			//! Lighting.hlsl 함수로 라이트 정보 및 쉐도우 데이터 구조체 얻어옴
   lightDir = normalize(mainLight.direction);	//! 메인 라이트 벡터
   lightColor0 = mainLight.color;				//! 메인 라이트 칼라

   distanceAtten = mainLight.distanceAttenuation;	//! 컬링마스크에 의해 컬링되면 1, 아니면 0 (No확실), 라이트맵 상황때는 다름
   //shadowAtten = mainLight.shadowAttenuation;		//! <ㅗ
   ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();	//! 쉐도우 감쇠값
   half4 shadowParams = GetMainLightShadowParams();
   shadowAtten = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), TransformWorldToShadowCoord(worldPos), shadowSamplingData, shadowParams, false);
#endif
}

 

 

Shadow Cast와 Receive가 정상적으로 작동하게 됬습니다.

 

 

 

삽질


https://forum.unity.com/threads/shadow-and-distance-attenuation-do-not-work-in-urp-unlit-graph.803025/

 

Shadow and distance attenuation do not work in URP Unlit Graph

Hi! I'm using Unity 2019.3.0f3 and URP 7.1.7 I'm trying to follow this tutorial:...

forum.unity.com

해당 #pragma 코드를 추가하면 된다고 하지만 Shader Graph에서 pragma 코드를 넣을 곳을 못찾음,

 

키워드 기능을 사용해서 포함할 수 있다고 주장해서 

_MAIN_LIGHT_SHADOW, _MAIN_LIGHT_SHADOWS_CASCADE, _RECEIVE_SHADOWS_ON/OFF 등 시도해봤지만 에러나고 안됨

 

 

https://www.youtube.com/watch?time_continue=619&v=DOLE4nrK97g&feature=emb_title

위 영상에서 Unlit 쉐이더에 그대로 구현을 PT하고 있지만 영어를 잘 못 들어서 놓친것인지 영상속에서는 Shadow Receive가 잘됨

 

https://forum.unity.com/threads/turn-off-receive-shadows-on-custom-pbr-graph-lwrp.657814/

 

Feature Request - Turn off "Receive shadows" on custom PBR graph [LWRP]

Hi, standard LWRP "Lit" and "Simple Lit" shaders have a checkmark for turning off "Receive shadows" (see below. There needs to be something similar for...

forum.unity.com

위 글은 PBR 쉐이더에서 Receive Shadow끄는 법을 알려주고 있는데 지금 상황하고 맞지 않음, 응용해서 _RECEIVE_SHADOWS_ON를 해봤지만 안먹힘

 

 

 

 

 

 

반응형

WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,