Shader) Unity 기본 조명, 기본 그림자 받아오기
Unity에서 Shader를 직접 작성할 때, 기본 조명과 그림자 데이터를 받아오는 방법을 정리한다.
Shader Graph에서 활용할 Custom Function을 만들고, HLSL을 사용하여 유니티의 조명 및 그림자 정보를 가져오는 방법을 다룬다.
기본 조명 가져오기
GetMainLight()
를 통해 씬의 메인 라이트 정보를 가져올 수 있다.
다음과 같이 HLSL 함수를 작성하면, 메인 라이트의 방향(Direction)과 색상(Color)을 받아올 수 있다.
void GetMainLight_float(out float3 Direction, out float3 Color)
{
#ifdef SHADERGRAPH_PREVIEW
Direction = float3(1, 1, 1); // Shader Graph 미리보기 환경에서는 기본 방향을 설정
Color = float3(1, 1, 1);
#else
Light mainLight = GetMainLight();
Direction = mainLight.direction; // 씬 내 실제 조명 방향 사용
Color = mainLight.color;
#endif
}
- Shader Graph 미리보기 모드(
SHADERGRAPH_PREVIEW
)- 미리보기에서는 씬 조명이 없으므로,
Direction = float3(1,1,1)
과 같이 임의의 값을 할당한다.
- 미리보기에서는 씬 조명이 없으므로,
- 실제 조명 적용 (
#else
)GetMainLight()
를 통해 유니티 씬의 메인 라이트 정보를 가져온다.mainLight.direction
→ 조명의 방향mainLight.color
→ 조명의 색상
이를 Shader Graph의 Custom Function에서 활용하면, 유니티 기본 조명을 받아와 사용할 수 있다.
유니티 기본 그림자 받아오기
유니티의 그림자 데이터를 가져오려면 그림자 좌표(Shadow Coordinate)를 계산한 후, 이를 샘플링해야 한다.
아래 Custom_Shadow_float
함수는 그림자 감쇄(Shadow Attenuation)를 계산하는 역할을 한다.
void Custom_Shadow_float(float3 worldPos, out float ShadowAtten, out float3 Direction, out float3 Color)
{
#ifdef SHADERGRAPH_PREVIEW
Direction = float3(1,1,1);
Color = float3(1,1,1);
ShadowAtten = 1.0f;
#else
Direction = float3(1,1,1);
Color = float3(1,1,1);
// Shadow Coord 만들기
#if defined(_MAIN_LIGHT_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)
half4 clipPos = TransformWorldToHClip(worldPos);
half4 shadowCoord = ComputeScreenPos(clipPos);
#else
half4 shadowCoord = TransformWorldToShadowCoord(worldPos);
#endif
// 그림자 사용 여부 확인
#if !defined(_MAIN_LIGHT_SHADOWS) || defined(_RECEIVE_SHADOWS_OFF)
ShadowAtten = 1.0f;
#endif
// Shadow Atten 샘플링
#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
}
-
Shader Graph 미리보기 모드
ShadowAtten = 1.0f; // 그림자가 없는 상태
Direction
,Color
도 기본값으로 설정.
-
Shadow Coordinate(그림자 좌표) 계산
-
_MAIN_LIGHT_SCREEN
이 활성화된 경우:
TransformWorldToHClip(worldPos)
→ 월드 좌표 → 클립 공간 변환ComputeScreenPos(clipPos)
→ 스크린 좌표 변환
-
그렇지 않은 경우:
TransformWorldToShadowCoord(worldPos)
→ 월드 좌표를 그림자 좌표로 변환
-
-
그림자가 적용되지 않는 경우(옵션 비활성화)
_MAIN_LIGHT_SHADOWS
가 없거나_RECEIVE_SHADOWS_OFF
가 설정된 경우, 그림자 효과 없이ShadowAtten = 1.0f;
로 설정.
-
그림자 샘플링
-
SHADOWS_SCREEN
이 활성화된 경우:
SampleScreenSpaceShadowmap(shadowCoord)
→ 스크린 공간에서 그림자 샘플링
-
그렇지 않은 경우:
SampleShadowmap()
을 통해 그림자 맵을 샘플링하여 그림자 강도를 계산
-
이 함수를 활용하면 Shader Graph에서 유니티의 기본 그림자 데이터를 받아올 수 있다.
트러블 슈팅
Custom Function 오류 해결 트러블슈팅
Shader Graph에서 CustomLight_Shadow_float
를 사용하는 Custom Function
노드에서 다음과 같은 오류가 발생했다.
-
'CustomLight_Shadow_float': no matching 2 parameter function
-
'CustomLight_Shadow_float': cannot convert output parameter from 'float3' to 'float'
원인: Shader Graph에서 Custom Function 노드의 Output 개수 부족
문제 발생 원인은 Shader Graph에서 Custom Function 노드의 출력(Outputs) 설정이 HLSL 함수의 반환 값과 일치하지 않아서였다.
void CustomLight_Shadow_float(float3 worldPos, out float ShadowAtten, out float3 Direction, out float3 Color)
-
이 함수는
총 3개의 출력 값
을 반환해야 한다:
ShadowAtten (float)
Direction (float3)
Color (float3)
-
그러나 Shader Graph에서 Custom Function 노드의 출력이 일부 누락된 경우, Shader Graph가 올바르게 호출할 수 없어 오류가 발생했다.
결과적으로 Shader Graph가 잘못된 인자 개수로 Custom Function
을 호출하려고 시도했으며, 그로인해 함수 매칭 오류가 발생했다.
no matching 2 parameter function
→ 인자 개수가 맞지 않음
하지만 ShadowAtten의 자료형을 변환 할 수 없는 오류가 뜨는게 이상하긴 하다.
댓글남기기