39. 기술 심화: Eye Shading + Parallax/Refraction
[B] 눈은 서브컬쳐 캐릭터에서 “표정”과 “생동감”을 결정하는 부위라, 작은 비용으로도 깊이감을 만들 수 있으면 룩이 크게 좋아집니다. 다만 눈은 면적이 작고 하이라이트가 강해, 구현이 거칠면 바로 티가 납니다.
- [B] 목표: 각막/홍채/동공/하이라이트를 레이어로 분리하고, 저비용 parallax/굴절 근사로 “동공이 안쪽”인 인상을 만든다.
- [B] 핵심: 월드축이 아니라 안구 로컬 축 기준으로 view 방향을 투영해 UV 오프셋을 계산한다.
목적
- [B] 눈 렌더링을 레이어 단위로 분해한다.
- [B] 저비용 시차 기반 깊이감 기법을 제시한다.
증거 등급 요약(A/B/C)
- [B] 다층 눈 렌더링 재현 사례 반복
- [C] 실제 굴절 모델은 엔진/타이틀별 차이
핵심 개념
서론: 눈은 “작지만 가장 민감한 곳”이다
- [B] 눈 표현은 작은 영역에서 큰 대비(하이라이트/검은 동공)가 생겨 aliasing/클리핑/소팅 문제가 잘 드러난다.
- [B] 그래서 “물리적으로 정확한 굴절”보다, 각도/표정 변화에서 안정적으로 유지되는 근사 모델이 실무적으로 유리하다.
개론: 레이어 분해(권장)
- [B] Sclera(흰자): 저주파 색/혈관 디테일(약함)
- [B] Iris(홍채): 색 패턴 + 시차(parallax) 대상
- [B] Pupil(동공): 가장 안쪽, 시차 강도를 더 크게
- [B] Cornea/Spec: 하이라이트는 별도 로브로 분리해 “항상 예쁘게” 유지
이론: parallax/굴절 근사는 “UV 오프셋” 문제로 환원된다
- [B] 핵심은
view 방향을 안구 로컬 공간으로 변환해, 그 XY 성분으로 UV를 이동시키는 것이다. - [C] 극측면(시선이 스치듯 들어올 때)에는 오프셋이 과해져 동공이 밖으로 밀리는 아티팩트가 생기므로 clamp가 필요하다.
심화: 안정성(temporal)과 하이라이트 분리
- [B] 눈 하이라이트는 캐릭터 인상에 직접 영향을 주므로, parallax 오프셋과 분리해 안정적으로 유지한다.
- [B] TAA 환경에서는 작은 하이라이트가 쉽게 히스토리 오염을 만들기 때문에(43장), 하이라이트는 폭/강도 상한을 둔다.
코드 해설
- [B]
worldToLocal변환은 안구 회전 시 오프셋 축을 메시에 고정하기 위해 필요하다. - [B]
height(깊이감)와scale(왜곡량)을 분리하면, “깊어 보이는데 왜곡은 덜한” 튜닝이 가능하다.
HLSL
float2 EyeParallax(float2 uv, float3 viewWS, float3x3 worldToLocal, float height, float scale)
{
float3 viewLS = mul(worldToLocal, viewWS);
float2 offset = height * viewLS.xy;
offset.y = -offset.y;
float2 shifted = uv - offset * scale;
return saturate(shifted); // grazing angle에서 오프셋 과다 방지(간단 clamp)
}
URP 매핑 포인트
설계 해석
-
[B] 눈 전용 머티리얼을 face 본체와 분리해 blend/queue를 독립 제어해야 하이라이트가 안정된다.
-
[C] 극측면에서 offset clamp가 없으면 동공이 스클레라 밖으로 밀리는 아티팩트가 발생한다.
-
[B] eye 전용 material로 layer blend 분리
-
[C] 극측면에서 offset clamp 필요
-
[B] 권장 운영: 눈(opaque/alpha clip)과 하이라이트(transparent/additive)를 같은 머티리얼로 억지로 합치지 않는다.
실패 패턴/오해
- [B] 월드축 기반 오프셋으로 회전 시 방향 반전
- [B] 하이라이트 블렌딩 모드 오류
- [B] 극측면 clamp 누락으로 동공이 “밖으로 튀어나오는” 아티팩트
- [B] 눈 하이라이트가 TAA에서 반짝임/잔상으로 번짐(43장과 함께 조정 필요)