새소식

개발/Shader

[Game Jams] [Snow Footprint] 01. Deformer

  • -

12월 공부 리스트인 중 하나인 Snow Footprint 프로젝트 분석을 위한 기초 공부 자료입니다.


본 포스팅은 http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch42.html 의 내용을 번역 및 실습하며 이루어집니다.


1.     디포머란?

A.   명시적 정의 : 정점들의 집합을 연산했을 기존 정점들의 집합이 새로운 좌표를 가질 있도록 하는 연산자를 Deformer라고 한다.

                         i.         조건 :

1.     Deformer 의해 새로운 Vertex Edge 생기면 안됩니다.

2.     Deformer 의해 변형된 정점은 다른 정점의 변화과정을 통해 영향을 받으면 안됩니다.

A.       규칙을 어기는 :

                                                    i.         Vertex Averaging :

주어진 Vertice 중심 값을 의미합니다.

                                                   ii.         Vertex Smoothing (Laplacian Smoothing) :
폴리곤 매쉬를 부드럽게 만드는 알고리즘으로,


N = 노드 i 연결된 인접 노드의 개수, x’j j번째 인접 노드의 좌표, x’i 새로 생긴 좌표입니다.

3.     같은 Defomer를 통해 위치 벡터를 변환시키면 벡터장에 상관없이 같은 결과가 나와야 합니다. (선형성 성립)


B.     수학적 정의

                         i.          일반적으로, 우리는 deformer vector 함수, f(x,y,z) 생각합니다. 하지만 다음과 같이도 표현이 가능합니다. (fx(x,y,z), fy(x,y,z), fz(x,y,z))
번째 표현 같은 경우엔 기존 (x, y, z) 좌표를 각각의 컴포넌트 함수 fx, fy, fz 사용해 새로운 벡터를 만드는 것을 의미합니다.

                        ii.         Wave 같이 공간에 의존하는 Deformer 좌표계에서 각기 다른 결과를 도출 입니다.

                       iii.         회전, 닮음, 대칭, 이동과 같은 선형 변환은 모든 Deformer 가장 간단한 하위 집합입니다. 이런 선형변환은 좌표 집합을 입력으로 받고  새로운 좌표 집합을 행렬  형태로 출력합니다

B.      Controls

                         i.         deform 연산은 deformer 컨트롤에 의존하며, 컨트롤이란 deformer 연산에 영향을 미치는 parameter입니다.
예를 들어, wave deformer 결과는 wave 진동수에 의존하며 이를 기술적으로 해석하면, 함수 f freq 변수에 의존한다고도 있습니다.
그러나 우린 f(x, y, z, freq) 같이 표현하진 않을 겁니다. 대신 freq deformation 위해 주어진 상수라고 생각할 입니다.
(freq
정점들이 deformer 의해 변형돼도 변하지 않습니다. 따라서 freq 함수 f 구성함수 적어도 하나에 상수로써 사용 입니다.)
변형 연산을 animate하기 위해 사용되는 time parameter 마찬가지로 상수가 입니다.
(time parameter t
x, y, z 의존관계가 없음으로, f 상수로 사용될 입니다.)


2.     GPU에서의 Deforming

A. Deformer 공식화하기

                         i.    Deformer 연산을 우리의 수학적 정의와 맞게 공식화하면 법선 벡터(Normal) 계산하는데 용이 합니다.
(
만약 y 축으로 2만큼 증가 시키는 deformer 있다면 이를 함수 f형태로 표현하면, f(x,y,z) = (fx ,fy ,fz ) = (x,y + 2,z) 표현 있습니다. )
만약 우리가 방사형의 wave deformer 구현한다면

                          위와 같이 l 위상제어 parameter 함수 f 만들게 입니다.

B. Vertex Shader 작성해보기

                         i.  과정에서 deformer 함수를 성했다면, 함수를 통해 정점을 수정하는 프로그램을 짜야 합니다

Direct3D 통한 그래픽스 작업에서 폴리곤은 아래 자료와 같은 Stage 거쳐 처리됩니다.

(출처 : http://www.realtimerendering.com)

여기서 우리가 관심을 가져야 할 것은 처음에 있는 Vertex Stage입니다. 여기서 정점에 대한 연산을 하기에, 앞서 

든 Deformer Function을 이 곳에서 구현해야 합니다.

이런 그래픽 파이프라인에 관여 가능한 소스코드를 작성하기 위해, 각 그래픽 라이브러리는 다양한 언어를 지원합니다. 

대표적 으로 Direct3D는 HLSL, OpenGL은 GLSL, 그리고 Cg가 있으며, 

여기선 Unity Engine을 사용 할 것이기Cg Programming Language를 사용 합니다.

                        ii. Shader 작성

1.   Property

A.     _Amplitude : Wave 높이 상수입니다.

B.      _Frequency : Wave 발생 빈도를 나타내는 상수입니다.

C.    _Speed : Animate 속도에 곱해지는 계수입니다.

D.     _Anchor : 이번 예제에선 정점의 월드 좌표계를 이용하기 때문에, 상대좌표를 얻기 위해 방사형의 시점이 월드좌표가 여기 저장됩니다.

E.      _Cover : 사용되는 Mesh 월드 사이즈를 담습니다.

2.    DisplaceFunc

Mesh 정점을 가공하는데 필요한 리소스를 계산하는 역할의 함수입니다

함수에선 정점의 월드좌표 worldPos 방사 시점과의 상대 좌표 relativePos 얻습니다.

3. WaveFunc

앞서 공식화 했던 f 코드화한 부분입니다.

A. dist : 방사형의 시점에서부터 정점까지의 거리를 저장하는 변수입니다.

B. 월드 좌표 pos 수정하는 기본 과정은 다음과 같습니다.

                                                    i. 새로운 좌표에서의 pos.y = 기존 pos.y + _Amplitude * sin (_Frequency * dist - _Time.y * _Speed) / dist

                                                   ii. 마지막에 나눈 dist 방사의 원점에서 멀어질수록 물결이 약해지는 효과를 줍니다. 하지만 dist 0 가까워질수록 없이 강한 물결이 만들어지기에, dist 제한을 두어 제한을 넘길시 dist 나누는 대신 _Cover * 2 곱해 일정 높이를 유지하게 만들었습니다.


4. 결과


5. 정점의 Deforming 간단하게 해결됐습니다. 하지만 변경된 정점의 법선 벡터 (Normal) 어떻게 구할 있을까요?

A. Normal 이란?

                                                    i. 선형 변환은 매트릭스로 표현이 가능합니다. 우리는 이 매트릭스(M)의 역을 통해 Normal을 구할 수 있었는데, Wave Deformer 같은 경우엔 대게 비선형 변환이라 매트릭스 표현이 불가능해집니다.
(이유는 homomorphism 키워드를 통해 공부 하실 수 있습니다.)
따라서 우리는 이 비선형 변환에서도 Normal을 구할 수 있는 새 방법이 필요합니다.

B. 근사 수치 기법

                                                    i. deformed normal 얻기 위한 방법 하나며, 모든 입력 정점에 대해  정점을 deforming 함으로써 근사한 normal 값을 구 합니다. 하나는 입력 정점이며, 나머지 정점은 각각 입력정점을 tangent 방향으로, binormal (bitangent) 방향으로 매우 약간 이동시킴으로써 얻을 있습니다. 이렇게 만든 정점은 2개의 벡터를 만들며, 벡터를 외적하면 Normal 벡터를 얻을 있습니다. 이를 이용해서, 정점을 Deforming 하고 얻은 Deformed 정점들로 Normal 구할 있습니다. 방법은 정점이 가까이 모여있을수록 정확한 값을 얻을 있습니다.

C. The Jacobian Matrix

                                                    i. 만약 deformer f(x, y, z) = (fx, fy, fz) 연속인 1 편미분을 갖는다면 우리는 Jacobian Matrix (called J) 사용 있습니다. 우리는, f(x) 끊김 없이 부드럽게 이어진다면 함수는 근사적으로 직선으로 간주 있다는 점을 이용해서 f(x) ~ f'(a)(x - a) + f(a) J 이용해서 f(x) ~ J(a)(x - a) + f(a) 같이 표현 있습니다. 이는 테일러 정리 의해 밝혀진 부분이니 궁금하신 내용은 추가적으로 공부하시면 됩니다.

                                                   ii. J 선형변환


이제
위를 이용하여 원하는 position deform 있으며, J * tangent, J * binormal 통해 deformed tangent binormal 얻을 있습니다.

                                                  iii. J 통한 Normal 계산 :


6.     근사 수치 기법을 이용한 프로그래밍
포스팅 이후 진행 프로젝트 분석(Tessellator)에선 근사 수치 기법으로 normal 구했기 때문에 원문과는 다르게 근사 수치 기법으로 normal 구해보겠습니다.


7.     수정된 DisplaceFunc


개의 입력 정점의 월드 좌표와 개의 가상 정점을 만드는 과정이 추가됐습니다. 과정에서 bitangent 필요해 상단에 bitangent 추가로 구했습니다.


Anchor
와의 상대좌표를 얻습니다. 이는 방사의 시점에서부터 정점까지의 거리를 측정하는데 사용됩니다.


정점을 모두 Deforming 합니다.


Deformed
정점으로부터 구한 Vector 통해 deformed normal 구합니다.


8.     Normal 추가한 효과를 보기 위해 Light 추가해봅시다.




9.     결과






Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.