탄젠트 스페이스 없는 범프 매핑

이전 탄젠트 스페이스가 작동하지 않을 때 3D 프로시저럴 셰이더에서 범프 매핑을 이뤄내는 법입니다.

Choose your operating system:

Windows

macOS

Linux

Bump mapping (범프 매핑)이란, 지오메트리를 추가하지 않고 셰이딩 계산 조절을 통해 표면에 오돌도돌한 느낌을 내는 (1978년 James Blinn이 개발한) 그래픽 프로그래머들이 오래도록 사용해온 팁입니다. 셰이딩에는 표면 노멀 대신 새로운 노멀이 사용됩니다. 새로운 노멀은 (Perlin 노이즈, 그레이스케일 텍스처와 같은) 1d 함수로 조절 가능합니다. 이 방법에는 (실루엣, 오클루전, 섀도 등) 약간의 결점이 있긴 하지만 실제 디스플레이스먼트 매핑보다 훨씬 빠릅니다.

bump_none.png

bump_only.png

bump_withnormal.png

범프 매핑 없음

범프 매핑 있음

범프 & 노멀 매핑 있음

실시간 렌더링에서는 보통 노멀 매핑 이라 불리는 (푸르스름한 텍스처) 범프 매핑 변종을 사용합니다. 노멀 맵은 텍스처의 각 픽셀에 색을 저장하는데, 실제로는 1 길이의 3d 벡터입니다.

노멀 맵을 생성하는 방법은 두 가지 있습니다:

  • 그레이스케일 이미지에서 노멀 맵 생성 - 각 픽셀의 가로 세로 인접 픽셀과의 차를 미리계산합니다. 두 (파생) 결과 수치를 단위 노멀로 변환하여 색으로 저장합니다.

  • 하이 폴리 3d 모델에서 노멀 구워내기 - 텍스처의 각 픽셀을 하이 폴리 오브젝트의 3d 표면상의 위치에 연결한 다음 그 노멀을 색으로 인코딩하여 저장합니다.

결과 텍스처를 어느 방향에서도 재사용할 수 있게 만들려면 저장된 노멀 벡터는 탄젠트 스페이스 에 있어야 합니다. 일반적으로 노멀, 탄젠트, 바이노멀(법선, 접선, 종법선)로 일컬어지는 3벡터로 구성되지요. 이를 통해 표면이 향하는 방향을 정의합니다. 즉 모든 노멀을 탄젠트 스페이스로 변환함으로써 현재와 같이 표면에 상대적으로 정의된 것처럼 재사용할 수 있는 것입니다. 탄젠트 스페이스 매핑은 오브젝트의 UV 매핑에 의존하는데, 텍스처의 X 와 Y 방향이 월드 스페이스 내 탄젠트 스페이스 벡터 둘(탄젠트와 바이노멀) 을 정의합니다. 탄젠트 스페이스 부작용이 없는 좋은 UV 매핑을 만들기란 어렵고 시간이 걸리는 일입니다.

Perlin noise 같은 3d 그레이스케일 함수를 사용하고자 한다면 어떨까요? 이 함수는 UV 매핑을 요하지 않아 범프 표면의 근처 디테일 렌더링을 향상시킬 수 있습니다. 탄젠트 스페이스를 요하지 않는 범프 매핑을 구현하면 이것이 가능한 것입니다.

ddx 와 ddy

탄젠트 스페이스 없는 범프 매핑을 구현하기 위해서 머티리얼 에디터에 ddx ddy 라는 두 개의 머티리얼 표현식을 머티리얼 에디터에 추가했습니다. 이들 각각의 표현식은 그 입력의 파생형 근사치를 반환합니다. 그래픽 하드웨어는 두 픽셀을 셰이딩한 뒤 그 결과를 빼서 그 파생형 근사치를 계산합니다 ( ddx = 오른쪽 - 왼쪽 , ddy = 아래 - 위 ).

이 함수들은 픽셀 셰이더에서만 사용할 수 있으며, 일반적으로는 머티리얼 함수에서 커다란 이펙트 구현을 할 때만 유용합니다.

항목

설명

입력

Value

값 - 계산할 파생물 값입니다.

출력

Out

출력 - 입력의 파생물 근사치입니다. 입력의 유형에 일치됩니다. 예를 슬어 스칼라 입력은 스칼라 출력으로, 2d 입력은 2d 출력으로 식입니다.

ddx 와 ddy 는 2x2 블록으로 계산되므로 해상도가 높은 입력에서 사용될 때는 약간 각이 지는 부작용이 생길 수 있습니다.

범프 매핑 머티리얼 함수

머티리얼에서 탄젠트 스페이스 노멀 맵에 의존하지 않는 범프 매핑 구현을 하기 위해 여러 개의 머티리얼 함수 가 제공됩니다.

ComputeFilterWidth

FilterWidth.png

ddx 와 ddy 를 활용하여 값이 화면에서 얼마나 빨리 변해가는지를 계산하는 함수입니다. 이를 통해 프로시저럴 셰이더에 노이즈가 끼기 시작할 거리에서 페이드 아웃 되게 만들 수 있습니다. 페이드 덕에 움직일 때는 훨씬 눈에 띄게 될 깜빡임이 덜하게 되며, 굴곡진 표면의 반사성은 엄청난 계단현상을 유발할 수 있기에 범프 매핑에는 매우 중요합니다.

다음 예제 이미지는 프로시저럴 범프 맵 함수로 페이드 아웃 되는 원거리 부분이 어떤지 볼 수 있습니다.

필터 폭 미사용

필터 폭 사용

항목

설명

입력

In

입력 - 필터 폭을 계산할 값입니다.

출력

Result

결과 - 픽셀에서 픽셀까지 입력이 얼마나 빨리 변해가는가 입니다.

PerturbNormalLQ

그레이스케일 범프 맵을 월드 스페이스 노멀로 변환해 주는 함수입니다. 그러나 앞서 말했듯이 2x2 블록 부작용이 있는 ddx 와 ddy 를 사용하기에, 월드 스페이스 노멀 출력의 퀄리티는 낮습니다.

낮은 퀄리티

높은 퀄리티

항목

설명

입력

Bump

범프 - 월드 스페이스 노멀을 계산해 올 스칼라 범프 (그레이스케일) 값입니다.

출력

WS Normal

월드 스페이스 노멀 - 계산된 월드 스페이스 노멀입니다.

이 함수가 출력하는 월드 스페이스 노멀을 사용하기 위해서는, Material 노드의 Tangent-space Normal 세팅을 False 로 설정해야 합니다.

이 함수는 참고용일 뿐, 머티리얼 함수 라이브러리에 노출되어 있지 않습니다. PerturbNormalHQ 함수를 대신 사용해 주시기 바랍니다.

PerturbNormalHQ

ddx 와 ddy 가 제공하는 파생물보다 더욱 정교한 계산으로 보다 높은 퀄리티를 내는 함수입니다. 그 방법은 샘플 위치 셋 사용하여 스칼라 함수를 여러 번 계산하는 식입니다.

항목

설명

입력

Bump one pixel right

한 픽셀 오른쪽 범프 - 현재 위치에서 한 픽셀 오른쪽인 (그레이스케일) 스칼라 범프 값입니다.

Bump center

중앙 범프 - 현재 위치에서의 스칼라 범프 값입니다.

Bump one pixel down

한 픽셀 아래 범프 - 현재 위치에서 한 픽셀 아래인 (그레이스케일) 스칼라 범프 값입니다.

WS Normal

월드 스페이스 노멀 - 옵션. 범프 맵과 합쳐지는 월드 스페이스 노멀입니다. 탄젠트 스페이스 노멀은 Vector Transform 표현식을 통해 월드 스페이스 노멀로 변환 가능합니다.

출력

WS Normal

월드 스페이스 노멀 - 합친 월드 스페이스 노멀입니다.

이 함수가 출력하는 월드 스페이스 노멀을 사용하기 위해서는, Material 노드의 Tangent-space Normal 세팅을 False 로 설정해야 합니다.

PreparePerturbNormalHQ

PerturbNormalHQ 함수가 월드 스페이스 노멀을 계산하는 데 필요한 샘플 위치 셋을 계산하는 함수입니다.

항목

설명

입력

Value

값 - 현재 위치에서의 (그레이스케일) 스칼라 범프 값입니다.

출력

Value one pixel right

한 픽셀 오른쪽 값 - 현재 위치에서 한 픽셀 오른쪽인 (그레이스케일) 스칼라 범프 값입니다.

Value

값 - 현재 위치에서의 (그레이스케일) 스칼라 범프 값입니다.

Value one pixel down

한 픽셀 아래 값 - 현재 위치에서 한 픽셀 아래쪽인 (그레이스케일) 스칼라 범프 값입니다.

FilterWidth

필터 폭 - 원거리의 디테일을 페이드 아웃 시키는 데 유용한 필터 폭도 계산합니다.

3 함수 대신 1 함수

범프 매핑 함수를 캡슐화시켜 다른 함수에서 그 값을 세 번 구하는 머티리얼 함수를 만들 수 있습니다. 복잡도가 일정 수준 감소됩니다.

텍스처 사용하기

더 나은 퍼포먼스를 위해 범프 매핑 머티리얼 함수에다 텍스처를 사용할 수는 있습니다. 그러나 그래픽 카드가 텍스처 필터링을 처리하는 방식에 따라 부작용이 생길 수 있습니다. 정상적으로 필터링된 색은 선형 보간되며, 그 파생물은 상수입니다. 무슨 뜻이냐면 그레이스케일 텍스처를 사용하면 표면에 부드럽게 보간되지 않는 노멀이 나온다는 뜻입니다.

참고

여기 설명하는 방법은 Morten S. Mikkelsen 의 작업을 기반으로 한 것입니다 (레퍼런스 참고).

퍼포먼스

프로시저럴 셰이더는 퍼포먼스 비용이 꽤나 발생할 수 있으며, (텍스처 매핑에 비교해서) 에일리어싱 없이 구현하기가 힘듭니다. 현재 Perlin noise 를 제공하며, 이 머티리얼 표현식을 최적화시킬 수 있기는 하지만 연산 비용은 항상 비쌉니다. n 개 레벨에 대해서라면 대부분의 연산을 n 번 해야 합니다. 범프 매핑 때문에 함수 값을 세 번 구한다면 더욱 심해지지요. 이 비용은 픽셀 수와 비례한다는 점에 유의하시구요. 이 모든 기능을 활용할 수는 있지만, 프로토타이핑이나 통제된 상황에서만 사용하시기 바랍니다.

문제

  • 아직 Flipped/Mirrored UV 가 제대로 처리되지 않습니다.

앞으로의 작업

이 방법은 탄젠트 스페이스 명시적 저장 방법을 대체할 수 있습니다. 그 방향으로 나아가기 위해 경험이 더 필요한데, 현재 구현에서 이 방법은 아티스트의 범프 매핑에 활용되기도, 연구 방법이 되기도 합니다.

레퍼런스

언리얼 엔진 문서의 미래를 함께 만들어주세요! 더 나은 서비스를 제공할 수 있도록 문서 사용에 대한 피드백을 주세요.
설문조사에 참여해 주세요
건너뛰기