Unity 검색

2022 LTS의 셰이더 그래프를 사용하여 자연 셰이더를 만드는 방법

2023년 7월 28일 엔진 & 플랫폼 | 15 분 소요
Sample scenes that apply nature shaders – sand (left) and water (right) – using Shader Graph in 2022 LTS
Sample scenes that apply nature shaders – sand (left) and water (right) – using Shader Graph in 2022 LTS
공유

Is this article helpful for you?

Thank you for your feedback!

이 블로그에서는 2022 LTS의 URP(유니버설 렌더 파이프라인)를 사용해 서로 다른 2개의 자연 셰이더를 만드는 방법을 살펴봅니다. 스타일라이즈드 물 셰이더와 사실적인 모래 셰이더도 함께 살펴보겠습니다. 에셋은 올해 안으로 새로운 URP 3D 샘플 씬과 함께 Unity Hub에서 릴리스될 예정입니다.

시각 효과는 얼핏 복잡해 보입니다. 하지만 이러한 기능을 뒷받침하는 디자인 기반의 사고 과정을 심도 있게 살펴보고 그 구현 기법을 단계별로 분석해 보려 합니다. 이제 셰이더 개발 단계를 파헤치며 멋진 자연 셰이더를 만들어 보겠습니다.

물 셰이더

오늘의 목표는 위 동영상에서 묘사하는 대로 일본식 정원 씬 중앙에 흐르는 스타일라이즈드 개울을 만드는 것입니다. 주변 환경은 불교적인 느낌의 조용한 분위기를 풍기고 아트 스타일은 사실적인 느낌보다는 애니메이션에 가깝게 표현되어 있습니다.

씬에 임베드된 터레인을 보면 물은 폭포와 다리 아래로 흐르는 개울의 조합으로 이루어져 있습니다. 스튜디오 지브리의 물 씬은 매우 감성적이며 다음의 3가지 요소가 눈에 띄는 경우가 많습니다.

  1. 물의 흐름을 정립하기 위한 흐름 라인
  2. 물과 주변 터레인의 상호 작용을 보여 주는 에지 하이라이트
  3. 계단식 낙수 또는 폭포의 느낌을 살리는 포말 효과

최종 물 셰이더에는 이러한 요소가 모두 사용됩니다. 이제 이러한 모습을 구현하는 방법을 자세히 살펴보겠습니다.

폭포: 포말 및 물보라

폭포는 기본 폭포 메시와 잔물결을 생성하는 원형 평면 메시라는 두 가지의 서로 다른 메시가 있습니다. 별도의 언릿 셰이더를 잔물결에 사용하면 노이즈 노드를 타일화하고 셰이더의 알파 값으로 사용할 수 있습니다. 그러면 나머지 영역이 마스킹 영역에서 제외되므로 원하는 위치에만 잔물결이 나타납니다.

Breakdown of the primary waterfall mesh and disc-shaped plane for generating ripples

핵심은 메시의 각 영역이 서로 다른 동작을 수행하게 하는 것입니다. 이는 빨간색(R), 초록색(G), 파란색(B) 채널의 버텍스 컬러로 메시를 사전 페인팅하는 방식으로 구현할 수 있습니다. 그러면 버텍스 컬러가 특정 영역의 연산을 분리하는 마스크로 사용됩니다.

셰이더 그래프의 Vertex Color 노드를 사용해 사전 페인팅된 버텍스 컬러 데이터에 액세스합니다. 아래 이미지의 오른쪽에 보이는 대로 버텍스 컬러의 빨간색 채널을 T 값으로 사용하여 폭포의 수직 및 수평 부분 사이를 보간(선형)하면 부드러운 전환 효과를 구현할 수 있습니다. 계단식 낙수 효과를 만들려면 타일링과 오프셋이 다른 두 개의 Voronoi 노드를 결합합니다. 그러면 역동적인 낙수 효과가 만들어집니다.

Split view of the Vertex Color Node in Shader Graph, showing Vertex Color in the red (R) channel

실제 폭포는 상층 수평면에서 물이 계단식으로 낙하하는 영역과 하층 수평면에 부딪히는 영역에서 포말과 물보라가 더 두껍게 발생하는 경우가 많습니다. 이 씬에서는 파란색 채널의 버텍스 컬러를 사전 페인팅하여 특정 영역에만 효과가 나타나도록 할 수 있습니다. 버텍스 컬러 마스크를 사용하면 최대 4가지의 효과를 단일 데이터 조각에 결합할 수 있습니다. 이 접근 방식은 각 효과에 사용할 그레이스케일 마스크 텍스처를 별도로 만드는 것보다 더 효율적입니다.

여러 레이어의 물이 모서리에서 쏟아 내리는 듯한 착시를 만들기 위해 다양한 스케일과 속도의 노이즈 노드를 활용합니다. 노이즈 노드를 낮은 속도에서 큰 스케일로 스크롤하는 동시에 높은 속도에서 작은 스케일로 스크롤하여 원하는 효과를 구현할 수 있습니다. 폭포의 수평 부분과 일관성을 유지하기 위해 개울의 데이터를 재사용합니다. 물줄기에 대한 세부적인 내용은 잠시 후에 살펴보겠습니다.

Split view of the Vertex Color Node in Shader Graph, showing Vertex Color in the blue (B) channel

개울: 반사, 모서리 포말, 물길

잔잔한 폭포를 만들었으니 이제 개울로 넘어가겠습니다. 보통 애니메이션 스타일의 물은 몇 가지 주요 특징을 지니고 있습니다. 실제 해안에서 볼 수 있는 격동적인 포말과 달리 지브리 스타일의 개울은 해안 근처에서 포말이 매우 얇게 형성되는 편입니다. 또한 물꼬리가 있어 역동적이고 생동감 있는 물의 움직임을 볼 수 있습니다. 씬의 시간대가 밤으로 설정되어 있으므로 사실적인 반사 효과도 필요합니다. 셰이더 그래프에서 이러한 효과를 어떻게 구현하는지 자세히 살펴보겠습니다.

반사

수면에서 반사를 캡처하는 방법이 여러 가지 있습니다. 가장 효율적인 방법은 URP에 내장된 GlossyEnvironmentReflection 함수를 호출하는 커스텀 함수 노드입니다. 이 함수는 씬의 박스 투영 반사 프로브에서 샘플링된 반사 컬러를 반환합니다. 사용자는 함수에 필요한 월드 공간 위치, 카메라 시점, 노멀, 스크린 위치만 전달하면 됩니다.

Split view of the Reflection Node settings in-Editor alongside final water shader reflection in the garden scene

더 뛰어난 비주얼과 사실적인 반사가 필요한 경우에는 URP의 평면 반사가 훌륭한 선택지일 것입니다. 평면 반사로 거울 같이 평평한 표면의 반사를 만들 수 있으며, 이는 평면 구조로 인해 물 메시에 적합합니다.

평면 반사를 구현하려면 별도의 카메라와 렌더 텍스처를 설정하여 반사 데이터를 저장해야 합니다. 반사 평면(이 경우에는 씬의 개울) 아래에 반사 카메라를 배치하고 플레이어 카메라의 위치와 방향에 따라 업데이트하는 것이 기본 개념입니다. 렌더 텍스처도 실시간으로 업데이트됩니다.

이 경우 반사 카메라의 근평면을 반사 평면 자체로 설정할 수 있다는 장점이 있습니다. 반사 평면 아래에 있는 오브젝트를 잘라 낼 필요가 없으므로 구현 프로세스를 간소화할 수 있습니다. 셰이더 그래프에서 텍스처 프로퍼티를 만들고 스크립트에서 전에 생성한 렌더 텍스처를 할당합니다.

렌더 텍스처를 성공적으로 연결하려면 셰이더 프로퍼티를 설정할 때 프로퍼티 세트가 셰이더 그래프에서 만든 텍스처 프로퍼티의 레퍼런스 ID와 일치해야 합니다. 렌더 텍스처를 업데이트할 때 스크립트에서 정확한 프로퍼티 ID를 호출해야 한다는 것을 잊지 마세요. 그런 다음 스크린 위치를 UV로 사용해 텍스처를 샘플링합니다. 이제 셰이더에서 평면 반사를 성공적으로 구현했습니다.

Planar reflection example scenes

평면 반사를 구현하려면 여러 기술적인 고려 사항과 세부 사항을 확인해야 합니다. 자세한 설명과 구현 예시가 필요하다면 이 URP 샘플을 살펴보세요. 참고로 평면 반사는 오브젝트가 두 번 렌더링되기 때문에 반사 프로브를 사용할 때보다 컴퓨팅 리소스가 더 많이 소비된다는 점을 기억하세요.

모서리 효과

모서리 포말 효과를 구현하려면 뎁스 차이를 계산해야 합니다. Scene Depth 노드Linear01 옵션은 불투명 오브젝트에 0~1 범위의 선형 뎁스값을 반환합니다. 이 값에 Camera Far Plane Distance를 곱하면 카메라와 불투명 오브젝트(이 경우에는 바위) 간의 거리를 결정할 수 있습니다. Screen Position 노드에서 Raw 옵션의 z 컴포넌트는 눈 공간 뎁스를 제공합니다. 이제 투명한 수면과 불투명한 바위 간의 뎁스 차이를 쉽게 계산하고 뎁스값을 Emission 출력으로 전달하여 포말 같은 효과를 생성할 수 있습니다.

Split view of calculating depth value in-Editor versus the in-scene result

씬에서 뎁스값을 가져오려면 프로젝트 설정에서 Depth Texture를 활성화해야 합니다. Depth Texture 옵션은 렌더 파이프라인 에셋의 General 섹션에 있습니다. 현재 렌더 파이프라인 에셋은 Edit > Project Setting > Graphics > Render Pipeline Asset을 통해 액세스할 수 있습니다.

View of the Universal Render Pipeline Asset window in the Unity Editor, showing how to find the Depth Texture option

개울 물줄기

개울을 따라가는 물의 흐름을 보여 주는 물길은 간단하게 만들 수 있습니다. 두 개의 Voronoi 노드를 타일링 및 오프셋하고 버텍스 컬러로 원하는 영역을 마스킹 영역에서 제외하면 수면을 따라 흐르는 스타일라이즈드 물길을 만들 수 있습니다. 그런 다음 이전의 낙수와 일치하도록 노이즈 노드의 속도를 조정합니다. 이제 수면을 따라 흐르는 스타일라이즈드 물길이 만들어졌습니다. 폭포의 물줄기를 만드는 데 사용되는 기법과 매우 유사합니다.

Split view of flow indicator using Voronoi Nodes in-Editor versus the in-scene result

모래 셰이더

Example of final scene of sand made using nature shaders in Shader Graph

이제 스타일라이즈드보다는 사실성에 초점을 맞춘 셰이더를 살펴보겠습니다. 모래 셰이더는 터레인이 시각적으로 실제 모래와 매우 유사해야 하는 사실적인 사막 씬에 사용됩니다. 

모래 렌더링은 흥미로운 작업입니다. 평범한 PBR 셰이더로는 강렬한 햇빛이 내리쬐는 사막 모래의 모습을 담아내지 못합니다. 모래 셰이더에서 중요하게 다루는 두 가지 특징이 있습니다. 하나는 미묘하지만 눈에 띄는 요소인 모래의 반짝임이며, 다른 하나는 생동감을 연출하는 동적 특징인 먼지 바람입니다.

모래는 수많은 미세 알갱이로 이루어져 있기 때문에 햇빛에 노출되면 반짝거립니다. 그러한 반짝임 효과를 어떻게 구현할 수 있을까요? 스페큘러 반사와 마찬가지로 먼저 표면 노멀을 사용해 반사 벡터를 계산합니다. Journey에서 얻은 아이디어를 활용해, 노멀 벡터와 하프웨이 벡터 간의 내적을 계산하는 대신 노멀과 카메라 시점 간의 내적을 계산합니다. 이렇게 조정하면 시야각에 따라 반짝임 패턴을 다르게 하여 셰이더의 시각적 완성도를 높일 수 있습니다.

셰이더에는 두 개의 노이즈 맵이 있습니다. 하나는 반짝임을 샘플링하는 데 사용되고, 다른 하나는 더 동적이고 매력적인 결과물을 위해 메인 노이즈 텍스처를 마스킹 영역에서 제외하는 데 사용됩니다. 이전에 계산한 반사 벡터를 사용해 노이즈 마스크 샘플링에 사용되는 UV를 왜곡합니다.

Split view of noise maps in-Editor versus the in-scene result, showing the sand glitter effect

모래 먼지 바람 효과는 움직이는 모래 자국과 모래 파도라는 두 요소의 조합으로 이루어집니다. 매우 단순한 개념에 기반하며 서로 다른 노멀 맵을 타일링하여 원하는 결과물을 생성합니다. 모래 자국 효과에서 중요한 사항은 노멀 맵을 마스킹 영역에서 제외하고 더 역동적인 효과를 구현하기 위한 마스크가 필요하다는 점입니다. 기본 UV를 사용하는 대신 절대 월드 포지션으로 두 개의 노이즈 맵을 샘플링합니다.

Position 노드의 World 옵션이 여러 렌더 파이프라인의 설정에 따라 바뀌므로, 파이프라인 전환 시 동작이 변경되는 것을 방지하도록 Absolute World 옵션을 선택해야 한다는 것을 잊지 마세요. 이제 두 개의 맵을 대각선 방향으로 타일링하면 잔잔한 파도 같은 효과가 만들어집니다. 그런 다음 또 다른 노이즈 맵을 모래 파도 방향으로 스크롤하여 모래가 흩날리는 느낌을 추가합니다.

Split view of how to choose the Absolute World option within the Position Node in-Editor versus the in-scene result, showing a blowing dust effect

한 가지 중요한 지점은 셰이더에서 노멀 블렌딩을 구현하는 방법입니다. 알베도 맵이 다른 터레인에 비해 복잡하지 않을 수 있는 모래 터레인에서 노멀은 시각적 표현에 중요한 역할을 합니다. 셰이더에서 여러 노멀 맵을 블렌딩합니다. 알베도 맵의 블렌딩과 달리 노멀 맵에서는 방향이 저장되며 서로 다른 블렌딩 방법을 사용해 매우 다양한 결과물을 생성할 수 있습니다.

셰이더 그래프의 Normal Blend 노드를 예로 들겠습니다. 노멀 맵 A 및 B를 블렌딩할 때 Normal Blend 노드의 기본 옵션에 두 맵의 x 및 y 채널이 함께 추가되며 z 채널을 곱해서 블렌딩 노멀의 3번째 요소를 획득합니다. 방향 재지정 옵션은 이름이 의미하는 대로 더 복잡한 프로세스가 필요하며, 맵 A의 방향과 일치하도록 맵 B의 노멀을 회전시킵니다. 이러한 접근 방식은 두 맵에서 대부분의 데이터를 유지할 수 있는 반면 컴퓨팅 리소스도 가장 많이 소비됩니다.

Three-way view of blending comparisons of the Normal Blend Mode in Shader Graph – Reorientated, Default, and Method in the scene

이 셰이더는 단순한 노멀 블렌딩 방법을 선택했습니다. 노멀을 블렌딩하는 주된 이유는 모래가 날리거나 사막 표면을 가로질러 이동하는 장면을 생생하게 연출하기 위해서입니다. 정확도는 최우선적인 고려 사항이 아닙니다. 또한 셰이더는 상대적으로 큰 터레인 메시에 적용되므로 컴퓨팅 리소스 비용을 최소화하는 것이 중요합니다.

이를 고려한 간단한 방식이 있습니다. 노멀 맵의 빨간색 및 초록색 채널을 함께 추가하고 파란색 채널은 값 1을 전달합니다. 그런 다음 노멀 강도를 약간 높이면 훌륭한 결과를 얻을 수 있습니다.

Final split view of Unity sample sand scene compared to in-Editor settings, showing an approach with bigger normal strength

언급된 기능 외에도 여러 컨트롤이 셰이더에 구현되어 있습니다. 그중 하나인 일반 페이딩 컨트롤은 카메라 거리에 따라 터레인에 효과가 나타나는 위치를 결정합니다. 이를 통해 카메라가 멀어짐에 따라 점진적으로 전환 및 페이딩되는 효과를 구현할 수 있습니다.

거리의 평활도 값을 조정하여 모래 언덕과 배경 터레인을 더 효과적으로 블렌딩할 수도 있습니다. 씬을 확대하면 터레인 노멀이 세밀한 입자성 노멀 맵으로 대체됩니다. 이러한 치환 효과로 모래 표면의 디테일과 텍스처 수준을 높임으로써 더 사실적인 사막 경험이 구현됩니다.

지금까지 두 셰이더의 모든 특징을 각각 살펴봤습니다. 이제 여러분만의 버전을 만들어 볼 차례입니다. 셰이더 그래프로 셰이더를 제작하는 데에 관심이 있다면 유니티 포럼이나 Discord를 방문해 주시기 바랍니다. 연재 중인 Tech from the Trenches 시리즈에서 Unity 개발자들의 향후 기술 분석도 확인해 보세요.

2023년 7월 28일 엔진 & 플랫폼 | 15 분 소요

Is this article helpful for you?

Thank you for your feedback!

관련 게시물