역자의 말: 테크아트 분들이 구직활동을 할 법한 기간이기도 하여 참고가 될 만한 중국분의 블로그 기술 포스팅을 가져와 봤습니다. 예전에도 종종 언급을 했었지만 중국 Zhihu에 올라오는 글들은 두 가지로 나뉘는데요. 하나는 정말 취미로 기술 분석 해서 공유 하는 걸 즐거움으로 사는 시니어 엔지니어 그리고 나머지는 대학교 졸업 준비 전 취업을 위해 자신이 나름 연구 한 과정을 글로 포스팅 하는 분들입니다. 실제로 중국에서는 HR이 신입 이력서를 받을 때 쯔후나 CSDN 에 기술 블로그 포스팅이 있는지 물어 보고 링크를 받아서 면접관에게 전달하는 경우가 많습니다. 특히 상해에 있는 회사들은 거의 다 그랬던 것 같습니다. 중국에서는 꽤 오랫동안 면접관 생활을 오래 했었기 때문에 그건 확실한 내용일거에요. 뭐 결론적으로 쯔후의 글 들이 모두가 다 프러덕션 레디는 아니라는 말이 되는것이니까요.... 걸러서 취하시면 되시겠습니다. 아무튼 워낙 하루 일관 된 루틴 이라 오전에 선별해서 하나 정도의 글을 번역문으로 이곳에 올리는게 습관화 되어 있는데요. 지하철에서 종종 다시 읽어보는 습관도 저에게는 참 좋은 것 같더군요. 그럼 또 하루 일에 너무 매몰되지 마시고 두루두루 살펴보면서 또 살아가보시죠. ㅎㅎ
저자: 在野
이것은 제가 작성한 첫 번째 시스템 방안 수준의 글입니다. 이 글은 시스템 방안을 공유하고 개인 구직을 위해 작성되었습니다.
최근 확실히 느낀 점은 완전한 프로젝트 방안은 장기적인 반복 개발이 필요하다는 것입니다. 이 방안도 오랜 시간 반복 개발했으며, 두 달 이상 작업했습니다. 먼저 상편을 작성하여 전역 및 지역 윈드 필드 설계와 일부 인터랙션에 대한 고민을 기록하고자 합니다.
완전한 장면 전시 테스트
이것은 프로젝트 초기의 윈드 필드 테스트 데모입니다. 그중 낙엽의 표현도 윈드 필드 구동을 받습니다.
분위기 있는 지형 구축:

적절한 구도 확정
완전한 테스트:
장면 실행 화면:

실행 화면1

실행 화면2

실행 화면3
고품질 식생 동적 윈드 필드란 무엇인가?
현재 3A급 프로젝트 게임 중 전역 윈드 필드와 관련된 것은 매우 드물며, 동시에 효과 표현이 우수한 것은 더욱 희소합니다. 그래픽 렌더링이나 게임 업계 종사자라면 윈드 필드를 언급할 때 가장 먼저 떠오르는 것은 갓 오브 워의 윈드 필드입니다. 실제로 저는 쓰시마의 윈드 필드 설계를 참고했습니다. 그 이유를 설명하겠습니다. 먼저 갓 오브 워와 쓰시마의 GDC 방안을 대략 살펴보겠습니다. 그런 다음 제 윈드 필드에 대한 설계와 인식을 설명하겠습니다.
갓 오브 워 윈드 필드 설계
갓 오브 워의 윈드 필드 설계는 쓰시마의 처리와 같습니다. 둘 다 윈드 필드를 전역 윈드 필드와 지역 윈드 필드로 나눴습니다. 그러나 두 방식의 전역 윈드 필드와 지역 윈드 필드 구현은 모두 다릅니다. 갓 오브 워의 방안은 비교적 물리적이고, 쓰시마의 방안은 매우 트릭적입니다. 저는 둘 다 매우 흥미롭다고 생각하여 모두 재현했습니다.
윈드 필드의 기능은 다음을 포함합니다:
- 식생 구동
- 캐릭터 입력 수용: 움직임, 스킬 발동
- 윈드 필드 자체의 인터랙션 영향
- 윈드 필드의 파티클에 대한 영향
- 기타
따라서 윈드 필드는 대략 두 가지 측면으로 나눌 수 있습니다. 하나는 외부로의 출력이고, 다른 하나는 내부로의 입력입니다. 제가 간단히 표현하자면 전역 윈드 필드는 식생 애니메이션에 영향을 미치고, 지역 윈드 필드는 식생에 인터랙션 구동을 하고, 스킬 영향을 받으며, 파티클을 구동합니다. 이것이 제 윈드 필드에 대한 인식 구분입니다. 이러한 구분은 쓰시마와 갓 오브 워의 방안을 분리하는 데 도움이 됩니다. 그렇다면 갓 오브 워의 방안에 따라 그들은 어떻게 윈드 필드를 설계했을까요?
그들이 설계한 윈드 필드 구조는 다음과 같습니다:

갓 오브 워의 윈드 필드 구조
갓 오브 워 전역 윈드 필드 구축
전역 윈드 필드는 식생과 잔디의 형태를 구동하는 데 사용됩니다. 따라서 게임에서 플레이어가 가장 많이 보는 것은 실제로 인터랙션 표현 효과가 아니라 전역 윈드 필드 표현입니다. 이 부분에서 갓 오브 워의 처리는 매우 간단합니다. 간단히 벡터를 설정하여 바람의 크기와 속도를 나타내고, 전역 크기 내에서 펄린 노이즈와 같은 노이즈를 사용하여 이 바람의 크기와 속도를 변경하여 시각적 표현상 전역 바람 효과를 달성합니다:

갓 오브 워의 전역 윈드 필드 설계
갓 오브 워는 이러한 방안이 대부분의 게임에서 사용되어 자신들의 표현에 적합하지 않다고 생각했지만, 최종 결과로 볼 때 채택했을 것으로 보입니다. 갓 오브 워의 장점은 지역 인터랙션 윈드 필드 구축에 있습니다.
갓 오브 워 지역 인터랙션 윈드 필드 구축
분명히 저는 윈드 필드를 전역 윈드 필드와 지역 윈드 필드로 나눴습니다. 효과와 정보를 빠르게 분리할 수 있습니다. 이 부분의 내용에서 갓 오브 워는 유체 시뮬레이션 형식으로 구현했습니다. 관련 세부 내용은 제 이전 글을 참고하시면 됩니다. 여기서는 간단히 살펴보겠습니다.
갓 오브 워는 바람의 표현과 유체의 표현이 일치성을 가진다고 생각했습니다. 그래서 유체로 윈드 필드를 구현하자고 제안했습니다. 그들은 캐릭터의 액터에 3D 메시 집합을 배치하여 각 레이어의 3D 메시마다 메시의 속도 입력을 획득하고, 스킬과 아이템의 속도 입력을 포함하여 유체 시뮬레이션을 진행한 후, 식생이 샘플링할 때 높이에 따라 샘플링합니다. 당연히 이러한 장점은 매우 명확합니다:
- 물리 기반 윈드 필드 구동 표현
- 아이템과 캐릭터 자체를 모두 같은 유형의 속도 입력으로 볼 수 있음
- 파티클 샘플링과 식생 샘플링이 더 간단하고 명확함
- 그리고 3차원 입체 윈드 필드이기 때문에 XYZ 모두에서 표현 가능하며, 바람을 통해 장면 모델의 형태를 표현할 수 있음

갓 오브 워 지역 윈드 필드 방안
간단히 이해하자면:
갓 오브 워 = 노이즈 교란의 전역 윈드 필드 + 지역 유체 계산의 인터랙션 윈드 필드
쓰시마 윈드 필드 설계
왜 제가 위에서 쓰시마의 설계가 매우 트릭적이라고 했을까요? 그들이 새로운 공간 데이터인 "Vorticles"를 정의했기 때문입니다. 저는 이것을 회전 파티클이라고 부르고 싶습니다. 쓰시마의 바람 표현은 매우 인상적입니다. 그래서 저도 그들의 설계를 참고하고 있습니다. 이 회전 파티클 안에는 매우 흥미로운 것들이 저장되어 있습니다. 먼저 쓰시마의 윈드 필드 구조 정의를 살펴보겠습니다:

쓰시마의 윈드 필드 정의
쓰시마 전역 윈드 필드 구축
그들도 벡터로 바람을 표현할 수 있고 지역 노이즈로 교란할 수 있다고 생각했습니다. 하지만 이러한 간단한 표현이 충분히 자연스럽지 않고 지역 인터랙션 윈드 필드에 직접 사용할 수 없다고 생각했습니다. 그러나 쓰시마의 경우 콘솔 플랫폼에 올려야 했기 때문에 더 복잡한 계산을 할 수 없었습니다. 따라서 그들은 매우 트릭적인 아이디어를 제안했는데, 바로 위에서 언급한 회전 파티클입니다.
그리고 이 회전 파티클은 전역 윈드 필드 구동으로 사용될 수 있습니다.

회전 파티클의 역할
회전 파티클(이하 회전자로 통칭). 이 회전자는 바람의 크기와 방향을 변경하는 역할을 합니다. 왜 이 파티클이 필요할까요?
쓰시마는 지역 노이즈 교란만으로는 다양한 윈드 필드 표현을 시뮬레이션하기에 부족하다고 생각했습니다. 예를 들어 캐릭터 스킬로 인한 폭발로 퍼지는 바람 등은 갓 오브 워에서 유체 시뮬레이션을 통해 완전히 해결할 수 있지만, 쓰시마는 성능 문제로 이 방안을 채택할 수 없었습니다. 그래서 이러한 특수한 회전자를 사용하여 바람의 크기와 방향을 변경했습니다. 즉, 지역 노이즈 교란 기반에 회전 파티클의 작용을 중첩했습니다.
전역 윈드 필드의 경우 장점은:
- 더 무작위적이고 더 동적인 전역 윈드 필드 표현
- 회전자를 통해 더 다른 윈드 필드를 표현할 수 있으며, 더 독특한 아트 표현 가능
- 연기와 인터랙션 구동
중요한 점은 회전자가 인터랙션을 할 수 있다는 것입니다. 이것은 어떻게 구현되었을까요?
쓰시마 지역 인터랙션 윈드 필드 구축
이렇게 많은 텍스트를 봤으니 GIF를 조금 보여드리겠습니다. 그렇지 않으면 이 텍스트가 너무 길고 지루하다고 느낄 수 있습니다. 아직 제 핵심 내용으로 들어가지 않았으니 인내심을 가져주시기 바랍니다. 저는 이 방안의 구현에 많은 에너지를 소비했으며, 더 나은 긍정적 피드백을 받기를 희망합니다.

낙엽은 분명히 자체 기본 물리학을 가지고 있지만, 분명히 불길이 낙엽에 영향을 미치는 것을 볼 수 있습니다. 이러한 영향은 회전 파티클을 통해 낙엽 속도장의 크기와 방향을 변경하여 구현됩니다. 이는 쓰시마 내의 윈드 필드 표현이 모두 이러한 부드럽고 원활한 전환이며, 특별히 돌출된 날카로운 인터랙션 표현이 나타나지 않는다는 점에서 명백합니다.
회전자에는 다음이 저장됩니다:
- 풍력 크기 변경
- 풍력 방향 변경
- 파티클 자체의 생명 주기
쓰시마가 이러한 회전자를 통해 어떻게 잔디를 제작했는지는 아래 UE의 구체적인 세부 사항에서 설명하겠습니다. 여기서는 기본적인 인식을 구축합니다:
쓰시마 = 노이즈와 회전자 교란의 전역 윈드 필드 + 회전자 구동의 지역 인터랙션 윈드 필드
그렇다면 똑똑한 독자는 이때 생각했을 것입니다~ 쓰시마가 회전자를 통해 풍력을 변경한다면, 지형이 비교적 돌출된 곳에서 관통이 발생하지 않을까요?
즉, 낙엽이나 파티클 효과가 평탄한 지표에서 가파른 지표로 불어갈 때, 낙엽이나 파티클 효과가 지하로 관통할 것입니다. 답은 그렇습니다. 이 문제도 매우 간단합니다. 낙엽에 충돌체를 추가하더라도, 일부 연기 구동에는 당연히 충돌체를 추가할 수 없으므로 관통이 발생하지만, 이러한 관통은 아티스트에게는 당연히 원하지 않는 것이며, 최종 효과 표현에도 치명적입니다.
1미터 간격으로 회전 파티클을 배치하여 윈드 필드를 구동하더라도 이러한 상황이 존재할 수 있습니다. 쓰시마의 해결 방안은 매우 간단합니다. 지형의 높이 맵을 샘플링하여 Z 방향을 위조하고, 날카로운 지표의 풍력을 직접 변경합니다. 물론 지형도 매우 복잡할 수 있으므로, 높이 맵을 샘플링할 때 평균값을 취할 수 있습니다. 또는 미리 사전 계산할 수도 있습니다. 이것은 정말 트릭적이고 재미있는 해결 방법입니다.
두 방안의 비교 총괄
종합하면, 쓰시마와 갓 오브 워의 방안은 각각 장점이 있습니다. 특히 쓰시마의 방안은 회전자의 도입으로 인터랙션에 새로운 아이디어를 제공했습니다. 그리고 오버헤드가 더 낮지만, 갓 오브 워가 분명히 더 사실적일 것입니다. 그래서 저는 두 방안 사이에서 제 자신의 방안 업데이트를 진행했습니다.
고품질 식생 윈드 필드 방안 정의
쓰시마와 갓 오브 워에 대한 논의를 거쳐 고품질 식생 윈드 필드에 대한 정의를 완성할 수 있었습니다. 고품질 식생 윈드 필드 세트는 다음을 포함합니다:
- 전역 윈드 필드: 식생 구동
- 지역 인터랙션 윈드 필드: 아이템 구동, 스킬 연결, 특수 스킬 윈드 필드, 캐릭터 인터랙션
- 툴
여기서 툴에 대해 중점적으로 이야기하고 싶습니다. 쓰시마의 설계에서 그들이 CS를 사용하여 절차적 잔디를 제작했기 때문에, 아티스트의 시각에서 그들은 잔디 클러스터링을 제안했고, 저는 이 설계를 따라 아티스트가 조작할 수 있는 원클릭 클러스터링 툴을 작성했습니다. 또한 갓 오브 워와 쓰시마는 모두 LOD 문제에 대해 언급했지만, 식생에 LOD를 부여하면, 예를 들어 잔디의 경우 원근 변화 시에도 여전히 전환이 충분히 자연스럽고 부드럽지 않은 문제가 존재합니다. 그래서 저도 자동 마스크 생성 툴을 작성하여 아티스트가 더 나은 품질을 달성하는 데 도움이 되기를 바랍니다.
그래서 할 일에 대해 이야기했으니, 품질 문제에 대해 이야기하겠습니다. 소위 성능, 효과, 사용성 불가능 삼각형이라고 하지만, 저는 고품질 윈드 필드 방안이 우수한 성능 표현을 가지면서, 동시에 전역 윈드 필드의 설계가 충분히 표현이 우수하여, 일반적인 윈드 필드를 표현할 수 있을 뿐만 아니라 특수한 윈드 필드, 예를 들어 토네이도가 잔디에 미치는 영향도 표현할 수 있기를 희망합니다. 동시에 확장이 편리하여 다양한 스킬 아이템과 캐릭터를 쉽게 연결할 수 있으므로 최종 기술 선정은 다음과 같습니다:
- 전역 윈드 필드: 쓰시마의 회전자 설계 도입, 식생의 전체 표현 구동
- 지역 인터랙션 윈드 필드: 갓 오브 워의 윈드 필드 설계 채택, 3차원 유체 인터랙션 윈드 필드 제작
- 툴: 잔디 클러스터링 툴 제작, LOD 전환 마스크 툴 제작
물론 이것들은 모두 포스 필드 구동 관점에서 이야기한 문제입니다. 저는 렌더링 레벨에서도 최종 효과를 제어할 수 있기를 더 희망하므로, Blender로 사실적 PBR 잔디 렌더링 프로세스를 만들고, 이 윈드 필드 방안과 결합하여 더 나은 효과 표현을 만들 것입니다.
전역 윈드 필드 구축
UE의 머티리얼 함수에서 공식은 윈드 필드 머티리얼 함수인 SimpleGrassWind를 제공합니다. 원리에서 분석하여 성능 효과 표현이 우수한 전역 윈드 필드를 어떻게 구축하는지 살펴보겠습니다.
전역 윈드 필드 기본 원리
SimpleGrassWind를 클릭하여 들어가면 머티리얼 함수가 매우 복잡합니다:

SimpleGrassWind
가독성이 매우 떨어지므로 정리하겠습니다:

아래는 정리한 후 기능이 동일한 윈드 머티리얼 함수입니다
분리한 후 당연히 로직이 훨씬 명확해집니다:

공식 구현 잔디 바람 움직임의 로직 재정리
UE 공식이 잔디 바람 움직임을 구현하는 데 사용한 것은 RotateAboutAxis입니다. 즉, 회전축 형식을 사용하여 먼저 월드 위치를 스케일한 후, time과 y 방향과 같은 방향을 규정하여 이동하고, 다시 frac으로 UV 리매핑과 유사한 작업을 합니다. sin, cos 함수와 같은 주기적 파동을 표현하는 것을 얻은 후 Angle로 변환하여 RotateAboutAxis에 전달하여 주기적인 흔들림을 만들어 바람 움직임을 표현합니다. 원리는 매우 간단하지만 그중에는 매우 재미있는 점도 있습니다.
공식은 주기적 결과에 대해 스무딩 처리를 하지 않았습니다. 이 점의 설명을 위해 스무딩 커브를 사용하여 설명할 수 있습니다:

커브의 스무딩 처리
주기적 결과에 대해 스무딩 처리를 진행하여 잔디의 흔들림이 불균일한 효과를 갖도록 하면 더 사실적으로 보입니다. 여기에 많은 스무딩 커브와 해당 구현 코드를 기록한 웹사이트가 있습니다: Easing Functions Cheat Sheet

공식 버전과 제 머티리얼 함수의 효과 표현을 비교하겠습니다:
스무딩 함수를 추가한 후 잔디 바람 움직임 표현이 더 자연스러워지는 것이 분명합니다. 이제 문제로 돌아가면, UE의 이 방안은 무엇을 표현했을까요? 또는 쓰시마는 어떻게 노이즈에서 회전 파티클로 확장했을까요? 주기 계산 부분을 생성하는 바람 움직임으로 돌아가겠습니다:

주기적 파동
이 과정은 실제로 FlowMap을 샘플링하는 과정과 같습니다. 예를 들어 이 UV Map에서 제가 처음 샘플링할 때 First 위치를 샘플링했고, 일정 시간과 가로 방향 후 제 UV Map이 역방향으로 이동하기 때문에 실제 샘플링은 Second 위치에 도달했습니다.

샘플링
위의 주기적 파동은 이 결과를 실행합니다. 그런 다음 노이즈, 또는 텍스처로 돌아가면 본질은 무엇일까요? 본질은 이산 데이터이며, 주기성은 텍스처에서 4방향 연속을 나타냅니다. 따라서 이론적으로는 이 주기적 파동 함수를 작성할 필요가 전혀 없습니다. 바람 움직임 노이즈를 계속 롤링하여 위의 효과를 달성할 수 있습니다. 이것도 대부분의 게임이 전역 윈드 필드를 구현하는 방법입니다. 4방향 연속 바람 움직임 노이즈를 사용하여 계속 한 방향으로 롤링한 후 샘플링합니다. 다음과 같이:

그런 다음 매우 흥미롭고 가치 있는 논의로 돌아갑니다. 텍스처의 경우 이러한 4방향 연속성을 유지하려면 얼마나 많은 정보가 필요할까요? 왜 이 문제를 논의해야 할까요? 윈드 필드를 표현하기에 충분하지만 최소 정보량을 계산하고 싶기 때문입니다. 그래서 어떻게 윈드 필드의 연속성을 유지할까요? 모델을 제시하겠습니다:

윈드 필드 RT 모델
현재 바람이 오른쪽으로 이동해야 한다고 가정하면, 전체 빨간색 계산 결과가 자연스럽게 오른쪽으로 오프셋이 발생합니다:

윈드 필드 롤링 모델
발견하셨나요? 그중에 매우 흥미로운 것이 나타났습니다. 4방향 연속성이 필요하지만 윈드 필드의 정보량을 줄여야 하기 때문에 주기성으로 인해 두 번째 프레임의 윈드 필드에서 중간 영역에 중첩이 발생했습니다. 이것이 무슨 나쁜 점이 있을까요?
- 현재 윈드 필드를 상상해보세요. 값이 매우 크지만 윈드 필드 시스템은 최대 5단계만 있는데, 중간 영역이 중첩을 거쳐 매우 커집니다. 10단계가 되어 최종 화면 효과에 완전히 영향을 줍니다
- 동시에 중간 정보가 반복적으로 중첩되기 때문에 표현이 우수한 주기적 바람 움직임 효과를 형성할 수 없습니다
해결 방안은 그림에서 볼 수 있듯이 네 모서리에서만 절반의 데이터를 계산하면 주기적인 연속 결과를 거쳐 최종적으로 얻는 것이 완전한 윈드 필드 RT입니다.
쓰시마 전역 윈드 필드 구축
이론적으로 현재 볼 수 있는 문제에 대해 논의를 마쳤으므로, 이제 Niagara를 사용하여 이 시스템을 구현해보겠습니다. 이전의 3D 유체 인터랙션 윈드 필드와 같이 이러한 아이디어로 쓰시마의 설계를 구현할 수 있습니다:
- 회전자를 저장할 배열을 정의할 수 있습니다. 먼저 회전자가 저장하는 데이터를 고려하지 않습니다
- Grid2D에 따라 각 Cell에 회전자를 무작위로 할당합니다
- Index에 따라 회전자와 결합하여 사전 할당된 풍력을 재계산합니다
이렇게 시도해보겠습니다. Niagara 시스템을 새로 만들고 GPU 모드로 변경합니다.

Grid2D 초기화 (네, 저는 노드 플러그인을 교체했습니다)
여기서는 풍력 RT를 사용하여 Grid2d와 정렬합니다. 최종 결과는 여전히 RT를 샘플링해야 하므로 하나의 Cell이 RT 영역에 대응하는 것이 가장 좋습니다.
회전자를 생성합니다. Vector4 배열을 사용하여 저장할 수 있습니다. 무작위 회전자이므로 노이즈와 같은 효과를 제공할 수 있기를 희망하므로, 파티클의 생명 주기, 저장된 풍력 크기, 저장된 풍력 방향은 모두 무작위여야 합니다. 여기서는 비교적 핵심적인 부분을 시연하겠습니다:
무작위 풍력 크기:

무작위 풍력 크기
무작위 풍력 각도:

무작위 풍력 각도
그러면 문제로 돌아갑니다: 회전자가 Grid2D의 Cell에 올바르게 정렬되도록 하려면 어떻게 해야 할까요? 예를 들어 과정에서 다음과 같은 상황이 발생할 수 있습니다:

회전자와 Grid Cell의 매칭 (영혼 그림)
분명히 그중 4번 회전자가 우리가 원하는 것입니다. 왜 그럴까요? 두 Grid Cell의 경계에 있을 때 이 회전자는 무효 회전자이며 해당 데이터를 가져올 수 없습니다. 그래서 일정량의 회전자를 할당하고 유효성 검증을 해야 합니다. 또는 여기에 다른 아이디어가 있습니다:
Cell의 크기에 따라 회전자를 스텝으로 무작위 할당하는 것입니다. 저는 이 아이디어를 채택하지 않았습니다. 더 무작위로 회전자를 할당할 수 있기를 희망하기 때문입니다. 회전자의 유효성 검증은 다음을 포함해야 합니다:
- 파티클 생명 주기 검증
- 파티클 위치 업데이트
- 파티클 오버플로 처리
- 파티클 죽음 후 리셋
회전자의 생명 주기는 frac를 사용하여 재사용을 구현할 수 있습니다. 로직은 실제로 오브젝트 풀과 조금 유사합니다. 코드는 다음과 같습니다:
// 초기화 조건: 정규화 연령 0 (새로 생성된 파티클)
const bool bParticleSpawn = ParticleParams2.y == 0.0;
// 연령 증가 (DeltaTime과 생명 주기 기반)
ParticleParams2.y += inDeltaTime / max(ParticleParams2.z, 0.01);
// 죽음 조건: 정규화 연령 ≥ 1.0 (생명 주기 종료)
const bool bParticleDeath = ParticleParams2.y >= 1.0;
// 연령을 [0,1) 범위 내로 유지 (순환 생명 주기 구현)
ParticleParams2.y = frac(ParticleParams2.y);동시에 여기에 문제가 있습니다. 앞에서 언급한 내용과 가깝습니다. 스무딩 처리입니다. 파티클을 사용하여 노이즈를 대체하기로 선택했다면, 전체 전역 바람의 스무딩 처리(페이드 인 페이드 아웃)를 어떻게 구현할까요? 제 생각은 매우 간단합니다. 회전자의 본질은 실제로 여전히 파티클이므로 투명도를 직접 사용하여 페이드 인 페이드 아웃을 구현하고, floor를 사용하여 주기적 운동을 만들어 범위를 벗어난 파티클을 처리합니다:
else {
// 방향/속도의 스무딩 전환 (반응성 계수 기반)
[ParticleParams1.zw](http://ParticleParams1.zw) = lerp([ParticleParams1.zw](http://ParticleParams1.zw), WindDir, ParticleParams3.w * inDeltaTime);
ParticleParams2.x = lerp(ParticleParams2.x, (inWindForce * ParticleParams3.z), ParticleParams3.w * inDeltaTime);
}
// 투명도 계산 (중간이 높고 양 끝이 낮은 포물선 커브)
ParticleParams2.w = 1.0 - (abs(ParticleParams2.y - 0.5) * 2.0);
// 위치 업데이트 (속도*방향*시간)
ParticleParams1.xy += ([ParticleParams1.zw](http://ParticleParams1.zw) * ParticleParams2.x) * inDeltaTime;
// 타일링 오버플로 처리 (무한 순환 운동 구현)
const float ParticleOverflowX = floor(ParticleParams1.x * inInvTileWidth) * inTileWidth;
const float ParticleOverflowY = floor(ParticleParams1.y * inInvTileWidth) * inTileWidth;
ParticleParams1.xy -= float2(ParticleOverflowX, ParticleOverflowY);이 단계까지 구현한 결과는 다음과 같습니다:

효과는 있지만 결과는 그다지 이상적이지 않습니다. 세밀도가 충분하지 않습니다. 우리는 분명히 잔디 3-4개가 하나의 움직임 상태를 나타내기를 희망하지, 한 덩어리가 하나의 움직임 상태를 나타내기를 희망하지 않습니다. 그래서 노이즈를 추가하여 결과를 교란시킬 수 있습니다. 교란 텍스처를 추가합니다:

교란 Texture
전역 윈드 필드의 풍력 레벨 시연
여기까지 실제로 쓰시마의 윈드 필드 시스템 복제를 완료했고, 회전자 영향의 전역 윈드 필드를 구현했습니다. 간단한 쇼케이스 장면을 구축했습니다. 나무는 아직 전체 시스템에 연결되지 않았으므로 잔디 표현을 관찰할 수 있습니다:
지역 인터랙션 윈드 필드 구축
지역 인터랙션 윈드 필드 구축에 대해 이야기하겠습니다. 이 부분의 내용은 플레이어가 느끼는 식생 품질을 결정합니다. 그래서 대담한 결정을 내렸습니다. 바로 3D 유체를 사용하여 이 부분의 내용을 만드는 것입니다. 그러나 지역 인터랙션 윈드 필드는 분명히 다른 캐릭터 입력에 따라 다른 유형으로 나눌 수 있습니다:
- 플레이어 움직임으로 생성되는 인터랙션 표현
- 스킬 아이템으로 생성되는 인터랙션 표현
- 장면으로 생성되는 인터랙션 표현
동시에 다른 기종 또는 다른 프로젝트 요구 사항으로 인해 이러한 고비용 방안이 필요하지 않을 수 있으므로, 저도 스프링 질점의 인터랙션 방안과 GPU 스키닝의 식생 인터랙션 방안을 구현했습니다. GPU 스키닝의 식생 인터랙션 방안의 구체적인 세부 사항은 설명하지 않으며, 관련 자료는 아래 인용에 있습니다.
갓 오브 워 윈드 필드 원리
갓 오브 워는 오버 숄더 시점이기 때문에 윈드 필드 중심에 대해 일정한 조정을 했습니다.

갓 오브 워 윈드 필드
제가 이전에 이미 해당 프로젝트 복제를 작성했으므로 여기서는 구체적인 세부 사항을 말하지 않겠습니다. 대략적인 아이디어는: Grid3D를 사용하여 전체 윈드 필드를 구현하고, 각 레이어는 해당 메시의 Velocity를 샘플링하여 유체 시뮬레이션의 입력 항목으로 사용하고, 마지막으로 계산 결과를 해당 Grid Cell에 저장합니다. 마지막으로 z축 절단 형식을 채택하여 RT에 타일링합니다. 즉, 아래 시연 그림입니다:

Z축 절단 형식에 따라 RT를 타일링
이렇게 하면 Niagara를 사용하여 갓 오브 워 윈드 필드를 구현할 수 있습니다.
갓 오브 워 윈드 필드 구현에 대하여
구체적인 구현은 내부 프로젝트와 개인 작품집에서 수정했습니다. 그러나 대략적인 방안은 제 이전 글을 참고하실 수 있습니다.
스프링 질점의 인터랙션 방안
일반적으로 인터랙션에는 세 가지가 있습니다: 정점의 변위, GPU 시뮬레이션, 그리고 파티클 구현 방식입니다. 여기서 대략적인 원리를 설명하겠습니다.
먼저 여전히 스프링 질점 시뮬레이션을 하지만, 모델의 높이에 따라 정점이나 파티클로 표현된 제약 관계를 RT로 변환합니다. 그런 다음 식생이 샘플링할 때 높이에 따라 다른 레벨을 샘플링할 수 있고, 결과를 오프셋으로 사용하여 식생 정점 위치를 오프셋하도록 구동합니다. 효과의 경우 제 테스트 과정의 비디오를 볼 수 있습니다:
그런 다음 구체적인 구현에서 몇 가지 문제를 인식했습니다: 피벗을 채택해야 할까요? 피벗에 관해서는 UE 공식의 PivotPainter 설명을 보시기 바랍니다.
왜 이 문제를 생각했을까요? 스프링 질점의 경우 각 레이어의 정점 오프셋을 레이어별로 가져와서 잔디 굽힘 표현을 스프링으로 형성할 수 있지만, 제 지역 인터랙션 윈드 필드 설계를 고려하여 PivotPainter 방안을 사용하여 피벗 관계를 UV에 베이킹하기로 결정했습니다. 이렇게 하면 잔디와 나무가 모두 같은 로직입니다. 그리고 제 지역 윈드 필드는 수체나 다른 물체의 움직임을 구동하도록 분할할 수 있습니다. 전체 시스템에 대해 적용성이 더 광범위합니다.
그러나 사람은 모두 욕심이 많습니다. 여전히 잔디 반발 표현을 원합니다. 어떻게 할까요?
잔디 반발 효과 제작
먼저 잔디 반발이 없는 효과를 보겠습니다:
반발을 구현하려면 아이디어도 매우 간단합니다. 이전 캐릭터 RT를 기록한 후 두 번째 RT에 그려야 합니다. 두 번째 RT를 사용하여 이전 몇 프레임/몇 초의 발자국을 그릴 수 있습니다. 글의 간결함을 위해 두 가지 핵심 단계만 제시하겠습니다:
- 캐릭터 발자국 기록
- RT 지연
방법은 비교적 간단합니다. 저는 직접 충돌체 감지를 사용했습니다. 캐릭터의 속도가 일정한 값에 도달하면 발자국을 기록하여 RT에 그립니다.

감지 실행 필요 여부
일정 Velocity를 초과한 후, 현재 캐릭터 액터가 유효하다는 것을 나타내며, RT에 그려야 합니다. 직접 여러 번 Draw Material을 사용하여 Canvas를 RT에 그립니다:

RT에 그리기
그런 다음 두 RT를 핑퐁합니다.
잔디 반발 시연 비디오:
글이 거의 만 자를 돌파했으므로 일단 여기까지 작성하겠습니다. 다음 편에서 계속하겠습니다. 더 많은 특수 윈드 필드 구현과 더 흥미로운 스킬 연결을 작성할 것입니다. 다음 편에서는 과정에서 제가 작성한 재미있는 툴을 작성할 계획입니다.
참고
GDC:
- Blowing from the West: Simulating Wind in 'Ghost of Tsushima'
- Interactive Wind and Vegetation in 'God of War'
블로거:
- Experimenting with a novel technique to create 2D wind in UE5
지후:
- UE5 시뮬레이션 인터랙션 편 (5) 물리 필드 방식으로 식생 인터랙션 구현
- UE5 시뮬레이션 인터랙션 편 (4) 유체 윈드 필드와 환경 인터랙션 방안
마지막으로
이 글이 더 많은 사람들에게 보이기를 희망합니다. 목적은 구직이기 때문입니다. 먼저 업계에 진입한 후 다른 문제를 논의해야 합니다. 독자 여러분께서 많이 전달하고 수집해주시면 감사하겠습니다. 정식으로 안정된 후 오픈소스 방안을 고려하겠습니다. 동시에 텐센트에 감사드립니다. 학부 1학년 때 TA 관련 내용을 접한 것부터 백인 계획 강의, 그리고 지금 학부 4학년까지, 텐센트에서 한동안 테크니컬 아티스트로 근무할 수 있었습니다. 이것은 제 자신의 꿈을 이루는 것이라고 생각하지만, 안타깝게도 운이 나빠 자신의 이유로 1년의 시간을 허비했고, 긴 시간 동안 불안해하며 자신의 잘못을 반성했습니다. 오랜 시간 동안 제 자신을 부정하며, 자신이 쓰레기라고 생각했지만, 자신의 하이라이트를 조금이나마 빛낼 수 있었고, 마지막으로 얻은 결론은 여전히 게임을 만들고 싶고, 그래픽을 연구하고 싶다는 것입니다. 그래서 눈여겨봐주시는 선배님들께서 저를 도와주시기를 희망합니다.
앞길을 모르기 때문에 가면서 소중히 여깁니다.
'TECH.ART.FLOW.IO' 카테고리의 다른 글
| [번역] MatCap 박막 간섭 비눗방울 렌더링 (0) | 2025.11.11 |
|---|---|
| [번역] UE5 Add Custom MeshDrawPass (0) | 2025.11.03 |
| [번역] SLG 게임에서의 나무 컬링 최적화 - GPU 기반 접근법 (0) | 2025.10.25 |
| [번역] Unity - PBR과 PBR+NPR 캐릭터 렌더링 연구 (0) | 2025.10.25 |
| [번역] UE5. 앰비언트 라이트 및 GI 2: 노멀 스무딩하기 (0) | 2025.10.23 |