PT / GI 팩
pt_surface.hlsl: 패스 트레이싱과 오프라인 GI 렌더러에서 팩을 적용하는 방법. PackEvaluate, PtPackIn / PtPackOut, 텍스처, 디노이저, 제한.
PT / GI 팩이란
표면 팩(surface.hlsl)은 PackShade로 래스터와 레이 트레이싱 카메라 뷰를 셰이딩합니다. 패스 트레이서(--render pt, PT 영상 렌더러)와 오프라인 GI 렌더러(GI 스틸·영상)는 모든 광선을 하나의 컴퓨트 셰이더 안에서 추적하기 때문에 PackShade를 거기서 실행할 수 없습니다. 팩은 두 번째 파일 pt_surface.hlsl로 참여할 수 있고, 이 파일은 히트 지점의 재질을 기술합니다. 태양 그림자, 간접광, 방사 조도 캐시, 디노이저 같은 빛 수송은 렌더러가 계속 맡습니다.
MMDX12 1.5.0 이상이 필요합니다. 이 파일이 없는 팩은 PT와 GI에서 기본 셰이딩을 쓰고, 이전 버전은 이 파일을 무시합니다.
파일
my_pack/
pack.json 매니페스트 (변경 없음)
surface.hlsl 래스터 / 실시간 RT (PackShade)
pt_surface.hlsl 패스 트레이싱 / 오프라인 GI (PackEvaluate)
shared.hlsli 선택: 두 파일이 함께 쓰는 수학
두 파일 모두 팩 폴더의 #include "shared.hlsli"를 쓸 수 있어서 룩을 한 번만 작성하면 됩니다. 온라인 갤러리 팩 nimble_toon이 이렇게 만들어졌습니다.
PackEvaluate
PtPackOut PackEvaluate(PtPackIn i);
PtPackIn
| 필드 | 의미 |
|---|---|
pos, normal, V, uv | 월드 위치, 셰이딩 법선, 카메라 방향, 텍스처 좌표 |
L, sunVis | 태양 방향, 추적한 그림자 광선의 태양 가시성 0..1 (확산 바운스에서는 0) |
baseColor | 선형 텍스처 색 × 재질 색, 조명 없음 |
materialClass | classes 규칙에서 정한 PACK_BODY / SKIN / FACE / EYE / HAIR / WEAPON |
params[16] | pack.json 순서의 슬라이더 값 |
headPos, headScale, headRight, headUp, headForward, headValid | PackSurface와 같은 머리 본 프레임 |
PtPackOut (모든 필드를 대입하세요. 대입하지 않은 필드가 있으면 pack_check가 경고합니다)
| 필드 | 의미 |
|---|---|
albedo | 선형 표면 색. 확산 바운스와 디노이저가 보는 값 |
shadowTint | 그림자 쪽에 곱하는 선형 배율 |
shadowBias | N.L 단위로 경계를 이동 (부드럽게 한 얼굴 법선: dot(Nsmooth, L) - dot(normal, L)) |
terminator | 경계 smoothstep의 N.L 끝점 (lo, hi). (0, 0)이면 엔진 기본값 |
specular | 더해지는 선형 광휘(림, 광택, 매트캡). sunVis가 곱해집니다 |
flatFace | 엔진의 평면 얼굴 처리 사용 (이 표면에 간접광 그라디언트 없음) |
렌더러가 쓰는 방식
- 카메라 광선과 거울·유리 체인:
lerp(albedo * shadowTint, albedo, term * sunVis) * sunIntensity + specular * sunVis, 여기서term = smoothstep(lo, hi, N.L + shadowBias). - 확산 바운스(다른 표면이 모으는 빛):
albedo만 사용합니다. 툰 항은 수집 광선에서 실행되지 않습니다. - 환경광(ambient) 항을 더하지 마세요. 패스 트레이서가 실제 간접광을 추적합니다.
- 하프 램버트 램프
threshold ± softness는terminator = (2 * (threshold - softness) - 1, 2 * (threshold + softness) - 1)로 옮길 수 있습니다.
텍스처
pack.json에 선언한 텍스처를 쓸 수 있습니다 (명시적 LOD만, 암시적 미분 없음):
float4 PtPackSampleTex(uint i, float2 uv); // 레벨 0
float4 PtPackSampleTexLevel(uint i, float2 uv, float lod);
uint PtPackTexCount();
float2 PtPackTexSize(uint i);
범위를 벗어난 인덱스나 없는 파일은 PackSampleTex처럼 흰색입니다. sRGB 텍스처는 선형 값으로 샘플됩니다.
제한
- 캐릭터만 해당합니다. 무대와 소품에는 팩이 적용되지 않습니다.
- 한 장면에 서로 다른 PT 팩이 여럿이면 첫 번째 팩을 씁니다 (경고가 로그에 남습니다).
- 오프라인 GI 렌더러는 앱 기본 외곽선을 그립니다 (
PackEdge는 래스터와 RT에 적용). - 디노이저는 팩의 직접광을 기본 툰 조명과 똑같이 처리합니다. 정지 테스트에서는 딱딱한
step()하이라이트 경계가 선명하게 남았지만, 빠른 움직임은 확인하지 않았습니다. PackEvaluate에서 끝이 정해지지 않은 루프는 피하세요. GPU가 멈추면 앱이 종료됩니다.pack_check <폴더> --compile로 확인하세요. 래스터, 오프라인 GI, 패스 트레이서 변형을 모두 컴파일합니다.