book/08-urp-hlsl-library-map.md

08. URP HLSL 라이브러리 구조 지도

Unity 6.3(6000.3) / URP 17.3.0 기준으로 “파일 역할→심볼 시그니처→정의 위치→호출 흐름”을 연결해 탐색/학습 루틴을 고정한다

08. URP HLSL 라이브러리 구조 지도(파일/함수 역할)

URP 셰이더를 “코드로 확장”하려고 할 때 가장 빨리 막히는 지점은 단순합니다.

  • “이 함수/구조체는 어디에서 정의되나?”
  • “이 include는 무슨 기능을 제공하나?”
  • “Forward+ 같은 기능은 어디에서 분기되나?”

이 챕터는 위 질문을 검색 가능하게(Traceable) 만들기 위해:

  • 파일 역할(어떤 범주인가)
  • 심볼 시그니처(반환값/파라미터)
  • 정의 위치(파일/라인)
  • 호출 흐름(어디에서 호출되나)

를 하나의 루틴으로 묶습니다.

선행: 07. Forward/Forward+/Lights

8.0 정확 레퍼런스(Generated, URP 17.3.0)

이 저장소는 로컬 URP/Core 소스를 스캔해서 “정확 레퍼런스”를 생성합니다.

Generated를 먼저 보고(정의 위치 확정) → 소스를 열어 맥락을 읽는 순서를 추천합니다.

8.1 URP/Core 소스는 어디에 있나? (embedded vs cache)

Unity 프로젝트에서 패키지 소스는 보통 두 군데 중 하나에 있습니다.

  • embedded: Packages/<packageName>/...
  • cache: Library/PackageCache/<packageName>@<version>/...

이 저장소의 스크립트는 embedded를 우선하고, 없으면 cache를 찾습니다.

  • 경로 해석 유틸: tools/_lib/UnityPackageResolve.ps1

Generated 문서에서는 절대 경로 대신 <URP>, <CORE>로 치환해 기록합니다(경로 노출 방지 + 재현성).

8.2 URP HLSL을 “범주”로 읽기: 5개 레이어

파일명을 외우는 방식은 URP 버전이 바뀌는 순간 무너집니다. 대신 아래 5개 레이어로 분류하면 안정적입니다.

  1. Core(기반): 플랫폼/정밀도/입력 상수/기본 매크로/좌표 변환
  2. Input(엔진 제공 값): 카메라/스크린/시간/텍스처 선언/프레임 상수
  3. Surface(표면/재질 입력): BaseMap/Normal/Mask 등 샘플링 → SurfaceData 구성
  4. Lighting/Shadows/GI(조명/그림자/간접광): Light 접근, BRDF, 쉐도우, 라이트맵/프로브
  5. Pass(엔트리/계약): Forward/GBuffer/DepthOnly/DepthNormals/Meta/MotionVectors 등 단계별 엔트리

“내가 찾는 심볼이 어느 레이어인가?”를 먼저 결정하면 탐색 속도가 크게 올라갑니다.

8.3 Core.hlsl가 무엇을 묶나? (실제 include 체인)

URP에서 Core.hlsl은 사실상 “URP 셰이더 세계의 루트(include entry)”입니다.

URP 17.3.0의 Core.hlsl 앞부분에서 특히 중요한 포인트:

  • _CLUSTER_LIGHT_LOOPUSE_CLUSTER_LIGHT_LOOP로 변환(Forward+ 루프 스위치)
  • SRP Core(공통) include를 끌어옴(Common.hlsl, Packing.hlsl 등)
  • URP의 Input.hlsl을 include(전역 상수/구조체/유틸의 기반)

이 3개를 기억하면:

  • “Forward+가 어디서 켜지나?”
  • “TransformObjectToHClip 같은 변환 함수는 왜 Core에서 오나?”
  • “InputData/SurfaceData 같은 구조체는 어디를 따라가야 하나?”

를 빠르게 추적할 수 있습니다.

관련 심볼(정의 위치는 generated 참고):

  • USE_CLUSTER_LIGHT_LOOP: <URP>/ShaderLibrary/Core.hlsl:14 / :16
  • _CLUSTER_LIGHT_LOOP: <URP>/ShaderLibrary/ForwardPlusKeyword.deprecated.hlsl:20

8.4 “심볼을 찾는 루틴”(검색/레퍼런스 결합)

URP HLSL 탐색에서 가장 빠른 루틴은 아래입니다.

8.4.1 1단계: Pass 루트 파일을 잡는다

예: Lit Forward라면

  • <URP>/Shaders/LitForwardPass.hlsl
  • <URP>/Shaders/LitInput.hlsl

정확 include 목록은 book/generated/urp-lit-map.md에 있습니다.

8.4.2 2단계: generated에서 “정의 위치(파일/라인)”를 고정한다

예시(URP 17.3.0):

Symbol Returns Defined-in
TransformObjectToHClip float4 <CORE>/ShaderLibrary/SpaceTransforms.hlsl:108
GetMainLight Light <URP>/ShaderLibrary/RealtimeLights.hlsl
UniversalFragmentPBR half4 <URP>/ShaderLibrary/Lighting.hlsl:282

8.4.3 3단계: 로컬 소스에서 “맥락”을 읽는다

정의가 어떤 #if에 감싸져 있는지, 어떤 전역 상수/버퍼를 읽는지, 어떤 매크로로 분기하는지를 확인합니다.

8.5 파일 역할 지도(URP 17.3.0, 학습 핵심만)

아래 표는 “파일 → 제공 심볼(대표) → 어디서 쓰나”를 연결한 지도입니다.
전체 심볼 목록은 book/generated/urp-17.3.0/symbols/files.md를 보세요.

File 역할 대표 심볼(예시) 대표 소비처
<URP>/ShaderLibrary/Core.hlsl 루트 include/플랫폼/Forward+ 스위치 USE_CLUSTER_LIGHT_LOOP, TEXTURE2D_X 거의 모든 URP 셰이더
<CORE>/ShaderLibrary/SpaceTransforms.hlsl 좌표 변환 TransformObjectToHClip Lit/Unlit/Depth* 전반
<URP>/ShaderLibrary/Input.hlsl InputData/전역 상수 기반 InputData struct 등 LitForward, Lighting
<URP>/ShaderLibrary/RealtimeLights.hlsl Light abstraction/라이트 루프 Light, GetMainLight, GetAdditionalLight, LIGHT_LOOP_BEGIN/END Lighting.hlsl, LitForward
<URP>/ShaderLibrary/Lighting.hlsl PBR/조명 합성 UniversalFragmentPBR LitForwardPass
<URP>/ShaderLibrary/Shadows.hlsl 쉐도우 샘플링 TransformWorldToShadowCoord Lighting/RealtimesLights
<URP>/Shaders/LitForwardPass.hlsl Forward 엔트리/입력 초기화 LitPassVertex, LitPassFragment, InitializeInputData Lit.shader(UniversalForward)
<URP>/Shaders/LitInput.hlsl Lit 표면 입력 InitializeStandardLitSurfaceData LitForward/GBuffer/Meta
<URP>/Shaders/LitGBufferPass.hlsl Deferred 엔트리 LitGBufferPassVertex/Fragment Lit.shader(UniversalGBuffer)
<URP>/ShaderLibrary/ObjectMotionVectors.hlsl MotionVectors 엔트리/계약 (motion vector entry) Lit.shader(MotionVectors/XRMotionVectors)

8.6 Depth/Normals 텍스처: “생성 → 선언 → 샘플링 → 선형화” 4단계

Depth/Normals가 필요한 화면 기반 효과(Outline/SSAO/SSR류)는 단순히 SampleSceneDepth를 호출하는 것만으로 해결되지 않습니다.

  1. 생성: URP 파이프라인이 Depth/Normals 텍스처를 실제로 만들고 있는가?
  2. 선언: 셰이더에서 URP가 제공하는 Declare/샘플링 include를 사용하고 있는가?
  3. 샘플링: UV/렌더스케일/XR에서 올바르게 샘플링하는가?
  4. 선형화: raw depth를 _ZBufferParams로 LinearEyeDepth로 변환하는가?

개념 코드(예시):

HLSL
float raw = SampleSceneDepth(uv);
float eye = LinearEyeDepth(raw, _ZBufferParams);

정확한 include/함수명은 URP 버전에 따라 다를 수 있습니다.
“4단계(생성→선언→샘플링→선형화)”를 체크리스트로 들고 가는 게 핵심입니다.

8.7 검색 레시피(Generated + rg)

8.7.1 generated에서 빠르게 찾기

8.7.2 소스에서 직접 찾기(rg)

POWERSHELL
rg -n "float4\\s+TransformObjectToHClip\\(" Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl
rg -n "int\\s+GetAdditionalLightsCount\\(" Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl
rg -n "LIGHT_LOOP_BEGIN" Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl
rg -n "UniversalFragmentPBR\\(" Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl

추가 읽을거리(공식/권위 자료)