저번 포스트에 이어 타이탄폴2를 목표로 개발을 하였습니다.


저번에는 이단 점프를 개발했는데 여기에 덧붙여 슬라이드 시스템을 개발하였습니다.


슬라이딩 시스템을 개발하기 위해 mixamo에서 무료 애니메이션을 다운받아 적용하였습니다.


이 사이트를 처음 알았을 때, 감탄이 나오더군요. 거의 제가 원하던 애니메이션이 많았기 때문이었습니다.


잡담은 그만하고 저는 슬라이딩 시스템을 개발하기 위해 다음과 같은 TODO 리스트를 짜보았습니다.


Running Slide

 

Crouch를 토글로 변경하기

Sprint를 토글로 변경하기

대각선으로 Sprint가능하게 하기

Sprint중 점프 가능하게 하기

Sprint중 재장전 가능하게 하기

Slide 애니메이션이 제대로 나오도록 하기

Sliding Crouch시 멈춤


처음에는 홀드 방식을 토글로 변경하는 간단하게 리팩토링 하였습니다.


이를 위해서 다시 타이탄폴2를 실행하여 연구?를 해보았습니다.



제가 직접 플레이한 게임 영상입니다. 오랜만에 하니 바니합이 잘 안되는 군요.


뭐 일단 바니합은 소스 엔진의 상징적인 버그기 때문에 제쳐두고


다양한 방면으로 생각해보았습니다. 따라서, 위와 같은 TODO 리스트가 나왔는데요.


애니메이션을 다루는 건 정말 어려웠습니다. 직접 본들을 리타겟팅하고, 루트 모션을 조작해보기도 하고 삽질도 하고....


이번 슬라이딩 시스템을 만들면서 클래스 내의 딜레이 구현은 식은 죽 먹기가 된 것 같습니다.


특별히 블루프린트를 다룬 것이 없었고, 코드 자체도 불 변수 조절해준 것 밖에 없었기 때문에 깃을 확인해주시면 감사하겠습니다.


Git : https://github.com/Titane22/FPS-Feature



'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #5  (0) 2018.08.21
Operation Indigo  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #4  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #3  (0) 2018.08.09
FPS 기능 만들기 프로젝트 #2  (0) 2018.08.07

지금까지 개발의 방향을 레인보우식스 시즈로 잡았습니다.


달리기는 직선밖에 안되며, 달리는 중에는 점프가 안되는 등 행동방면에서 많은 제약이 있었는데요


이번에는 제가 좋아하는 FPS 중 하나인 타이탄폴2를 목표로 잡고 개발해보았습니다.


먼저 개발한 것은 이단 점프입니다.


기본적으로 아주 간단했습니다. 


현재 점프 횟수를 기록할 JumpCount가 최대 점프 횟수인 MaxJumpCnt보다 작으면 점프가 가능하도록 하는 것인데


이단 점프라면 당연히 최대 2번이겠죠?


이것을 초기화하기 위해서 Tick에서 다음과 같은 코드로 초기화 해주었습니다.



제일 중요한 것은 this->GetCharacterMovement()->IsFalling() 함수인데요, 


이 함수는 현재 캐릭터가 바닥에 붙어있는지에 대해 불변수를 리턴받는 함수입니다.


즉, 점프중인지 확인해주는 함수죠. 


하지만, 전 코드보다 에디터 부분에서 애를 먹었습니다.



다중 점프를 위해선 두 값을 세팅해줘야 합니다.


오히려 여기서 시간을 더 잡아먹은 것 같습니다. 아무리 해도 점프를 하질 않으니;;;


읽어주셔서 감사합니다.


Git : https://github.com/Titane22/FPS-Feature


'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #6  (0) 2018.08.21
Operation Indigo  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #4  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #3  (0) 2018.08.09
FPS 기능 만들기 프로젝트 #2  (0) 2018.08.07

 이번 장은 이론 위주였습니다. 코드만 왕창 보다가 다시 이론만 나오니 졸리기도 하는 이 황금 배합에 감탄하고 말았습니다. 그래도 익숙해서 그런가 어렵지 않았던 것 같습니다.


3차원 같은 2차원


 영화 cg나 게임을 하면서 어떻게 3D 그래픽을 표현했을 까 하는 생각을 가끔씩 했을 것입니다. 저는 이 부분을 공부하면서 3D2차원 이미지를 3차원처럼 보이게 만든 마술 같은 기술임을 알았습니다. 다음은 이 마술 같은 표현을 이루어 주는 기법입니다.

-       소실점 : 원근법이라고도 할 수 있는 이 기법은 깊이 알고리즘에 의해 오브젝트와 투영 창과의 거리에 따라 오브젝트의 크기를 조절하는 기법입니다.

-       오버랩 : 4장에서도 배웠던 것처럼 오브젝트의 겹침을 알고 렌더링 하는 기법입니다. 이것 또한 깊이 알고리즘을 이용합니다.

-       조명(Lighting) : 조명이 있고 없고 차이는 그림에서 명암 표현이 있고 없고의 차이와 같은 것 같습니다. 조명에 따라 오브젝트의 입체감이 살기 때문입니다.

-       그림자(Shader) : 그림자의 위치에 따라 조명의 위치를 알 수 있습니다. 조명과 그림자는 뗄 수 없는 조합인 것 같습니다.

4 기법은 일상생활에서도 느낄 수 있는 당연한 것들이지만, 덕분에 2차원 이미지를 3차원으로 느낄 수 있도록 도와줍니다.


모형의 표현


 3D 모델링을 해본 사람이라면 오브젝트들이 모두 평면의 메시로 이루어져 있다는 것을 알 것입니다. 저도 1인 개발을 해보겠다고 무작정 무료 모델러인 블렌더를 깔 고 모델을 해봤는데요.

레고 캐릭터 하나 만들고 현자타임이 와버리더군요. 3차원 오브젝트를 표현하는 데에 삼각형 모양의 메시가 아주 작은 크기로 근사하여 따닥따닥 붙어 모양을 나타내줍니다.


컴퓨터의 색상 표현


 RGB라는 명칭이 많이들 익숙할 것입니다. 이 뜻이 Red, Blue, Green이라는 것을 처음 알았을 때 이렇게 쉬운 단어들이 모인 것일 줄은 몰랐었습니다. RGB는 컴퓨터 내에서도 색상을 표현하는데 이용됩니다. 역시 빛의 삼원색이기 때문인 것 같습니다. 컴퓨터에서는 RGB이외에 알파라는 값을 추가시켰습니다. 알파는 불투명도를 나타내는데 딱 봤을 때, 언리얼 게임을 만들면서 마테리얼을 작업 할 때 Opanity와 같은 역할을 함을 느꼈습니다.


네 가지 값을 이용해 4차원 벡터를 만들 수 있습니다. 각각의 값들은 0부터 1까지 나타낼 수 있는데, 0은 빛이 없음을 의미하고 1은 빛의 세기가 최대임을 나타냅니다. 4차원 벡터를 이용하여 나타낸 색상은 특별한 연산이 있습니다. 벡터이지만 내적이나 외적 같은 기본적인 벡터연산이 색상을 표현하는 데에는 의미 없기 때문에 컬러 벡터만의 연산인데요. 이것을 변조(Modulation) 또는 성분별 곱셈(Componentwise multiplication)이라고 합니다. 거창하게 컬러 벡터만의 연산이라고는 하지만 의미만 다를 뿐 다른 벡터 연산과 비슷합니다. 내적과 비슷하지만 각 성분끼리 곱을 한 후 그것이 각 성분이 됩니다.




내적은 각 성분끼리 곱한 값을 모두 더하여 스칼라 값을 반환한 반면에 변조는 말 그대로 성분별 곱셈만 한 후 벡터 값을 반환합니다.


렌더링 파이프라인


 렌더링 파이프라인의 정의는 3차원 장면의 기하학적 서술과 가상 카메라의 위치 및 방향이 주어졌을 때 현재 가상 카메라에 비친 3차원 장면의 모습에 근거해서 2차원 이미지를 생성하는 데 필요한 일련의 단계들 전체를 가르키는 것을 의미합니다.

다음은 렌더링 파이프라인의 대표적인 과정인데요 맨 위에서부터 맨 아래까지 순서대로 이루어지는 과정입니다. 각 단계는 GPU로부터 리소스를 받아 수행되는데, 기하 쉐이더에서는 유일하게 GPU로 스트림을 출력합니다. 무엇을 출력하는지 자세한 것은 다음 장에서 공부해보겠습니다.


-       입력조절기(Input Assembler)

n  입력 조절기에서는 간단하게 VertexIndex 버퍼를 채우고, 기하목록에서 어떤 도형을 형성할 것인지 기본도형 위상구조를 나타내는 enum형 인            D3D_PRIMITIVE_TOPOLOGY을 참고하여 설정하는 단계입니다.

n  Vertex 버퍼에는 기본도형을 형성하기 위해 사용되는 vertex들이 저장되는데 모두 연속적인 메모리에 저장됩니다. 하지만, 어떤 식으로 조합되었는지 나타나있지 않아 기본도형 위상구조를 설정해줘야 합니다.

n  기본도형 위상구조의 예로 개별적인 점으로 그려지는 점 목록(POINTLIST), 차례로 연결된 선분들을 형성하는 선 띠(LINESTRIP), 매 정점 두 개가 하나의 선분을 형성하는 선 목록(LINELIST), 삼각형들이 연결되어 있다는 가정하에서 인접한 두 삼각형이 정점들으르 공유하는 삼각형 띠(TRIANGLESTRIP), 매 정점 세 개가 하나의 삼각형을 형성하는 삼각형 목록(TRIANGLELIST)이 있습니다. 목록과 띠의 차이는 독립적이냐 연속적이냐의 차이입니다.

n  삼각형 목록에서는 인접성이라는 특별한 기능을 가질 수 있는데요, 이 인접성은 삼각형 목록에서 삼각형을 형성할 때 각 변에서 인접한 삼각형에 대한 정보를 가진 삼각형을 의미합니다. 인접성을 포함한 삼각형 목록은 기하 쉐이더에서 사용되는데 기하 쉐이더 부분에서 다시 공부해보겠습니다.

n  Index 버퍼는 vertex의 중복에 따라 메모리와 Gpu 처리량의 낭비를 해결하기 위해 사용되는 버퍼입니다. 함께 사용되는 vertex 버퍼와 일대일로 대응하도록 만든 이 버퍼는 어떤 vertex들을 어떤 순서로 사용하여 삼각형을 형성하는지를 나타냅니다. 보통은 삼각형이 만들어질 때 기준 vertex를 기준으로 시계방향 순으로 작성됩니다. Index 버퍼를 이용함으로써 정수형의 자료형을 가지기 때문에 적은 양의 메모리를 사용하고, 정수 값이 정해진 순서로 작성되어 캐시에 저장하여 처리한다면 Gpu의 처리량도 줄어듭니다.

-       정점 쉐이더(Vertex Shader)

n  모든 길은 로마로 통한다라는 속담이 어울리는 단계입니다. 화면에 그려지는 모든 vertex들은 모두 이번 단계를 거쳐가야 합니다.

n  Local Space & World Space :

n   

-       테셀레이터(Tesellator)

n  오브젝트의 삼각형 메시를 분할하여 새로운 삼각형 메시를 만드는 기법입니다.

-       기하 쉐이더(Geometry Shader)

n  선택적입니다.

n  이전 단계들로부터 생성된 vertex를 이용하여 새로운 vertex로 변형하거나 삭제시킬 수 있습니다.

n  절단(Clipping) : 시야에서 보이지 않는 부분을 잘라냄으로써 최적화하는 기법입니다. 게임을 하는 데에 있어 가장 중요한 것은 부드러운 게임 환경인데요. 좀 더 효율적인 연산을 위해 보이는 부분만 렌더링하고 보이지 않는 부분은 과감히 잘라내어 렌더링을 하지 않는 것입니다.

-       래스터화(Rasterization)

n  뷰포트 변환, 후면 선별과 정점 특성의 보간 등의 기능을 가지고 있으며 주로 픽셀에 색상을 계산합니다.

-       픽셀 쉐이더(Pixel Shader)

n  각 픽셀마다 특정한 작업을 하여 픽셀 단편을 생성한 뒤 다음 단계로 출력합니다.

-       출력 병합기(Output Merger)

n  이전 단계로부터 받은 픽셀 단편을 폐기하거나, 백 버퍼에 추가합니다.

n  블렌딩 : 백 버퍼에 픽셀들을 혼합하여 얻은 결과를 추가하는 것입니다.


이외에도 헐 쉐이더와 도메인 쉐이더가 있지만 교재에서는 언급만 했기 때문에 이번 장에서는 넘어가도록 하겠습니다.


'GameDev > DirectX12' 카테고리의 다른 글

Direct3D의 초기화  (0) 2018.08.17
변환(Transformation)  (0) 2018.08.17
행렬(Matrix)  (0) 2018.07.25
벡터(Vector)  (0) 2018.07.25

Direct3D?


Direct3D는 응용 프로그램에서 GPU를 제어하고 프로그래밍하는 데 쓰이는 저수준 그래픽 API입니다.


COM(Component Object Model)이란?


COMDirectX의 프로그래밍 언어 독립성과 하위 호환성을 가능하게 하는 기술입니다. COM객체를 COM 인터페이스라고 합니다. COM 객체를 스마트포인터처럼 이용하기 위해서는 ComPtr 클래스를 이용해야 합니다. ComPtr wrl.h 헤더파일을 불러줘야 합니다. COM new 생성자를 이용할 필요가 없으며, delete 대신 COM 클래스 내의 Release 함수를 불러야 합니다. 하지만, ComPtr를 이용하면 자동으로 Release를 호출합니다.


Sawp ChainPresenting

만약에, 매 프레임마다 게임을 로딩한다면, 재미보다 짜증을 느낄 것입니다. Swap Chain은 이것을 줄이기 위해, Front BufferBack Buffer를 이용하여 현재 화면은 Front Buffer에 나타내고 다음 프레임의 화면을 Back Buffer에 두는 것을 Swap Chain을 형성한다고 합니다. 그리고 Front Buffer에서 Back Buffer로 전환하는 것을 Presenting이라고 합니다. 이렇게 함으로써, 효율적으로 화면에 텍스쳐를 그림을 그릴 수 있게 됩니다. 이와 같은 방법을 Double Buffering 이라고 합니다.


Depth Buffering

Depth Buffer는 각 픽셀의 Depth 정보를 담습니다. Depth0.0일 때 최대한 절두체에 가깝게 표현합니다. 1.0일 때에는 최대한 멀리 있게 표현합니다. Depth BufferingZ-Buffering에 의해 구현됩니다. 자세한 방법은 Z-Buffering을 개인적으로 해석하고, 구현해봄으로써 설명하겠습니다.


ResourceDescriptor(=View)


리소스는 컴퓨터가 렌더링 등에 사용할 수 있는 자원을 말합니다. 3D게임 개발에서는 메모리, GPU, CPU등이 대표적입니다. Draw명령을 제출하기 위해서는 이 리소스중에 Draw호출에 사용할 리소스들을 렌더링 파이프라인에 Binding 해줘야 합니다. 하지만, 이 리소스들이 직접적으로 Binding되는 것이 아닙니다. Descriptor를 통해 Binding됩니다.


Descriptor는 리소스들을 GPU에게 전달하기 위한 자료구조입니다. GPU는 리소스 descriptor를 통해서 리소스의 실제 자료에 접근하며, 그 리소스를 사용하는 데 필요한 정보 역시 리소스 Descriptor로부터 얻습니다. GPU 리소스는 범용적인 메모리 조각이기 때문에, 똑 같은 리소스를 각각의 서로 다른 렌더링 파이프라인에서 사용될 수 있습니다. 왜냐하면, 리소스 자체로는 어떤 곳에 쓰이고 있는지, 어떤 형식인지에 대해 알려주지 않기 때문입니다. 따라서, Descriptor로부터 리소스의 사용법을 알 수 있고, 무형식의 리소스를 구체적으로 명시할 수 있도록 도와줍니다.  이후에 View라는 단어도 나오는데 이는 Descriptor와 같은 의미입니다.


 Descriptor를 담을 수 있는 배열이 있는데 이것을 Descriptor heap이라고 합니다. 이 힙에는 같은 종류의 descriptor들이 저장됩니다. 또한, 한 종류의 descriptor에 대해 다수의 힙을 둘 수 있습니다. 하나의 자원을 참조하는 descriptor가 하나뿐이어야 하는 것은 아닙니다. 예를 들어 한 리소스의 여러 부분 영역을 여러 descriptor가 참조할 수 있습니다. 또한, 앞에서 언급했듯이 하나의 리소스가 렌더링 파이프라인의 여러 단계에서 binding할 수 있는데, 각 단계마다 개별적인 descriptor가 필요합니다.

Descriptor생성은 프로그램의 초기화 시점에서 하는 것이 형식 점검과 유효성 검증을 통해 더 좋은 효율성을 얻습니다.


DXGI(DirectX Graphics Infrastructure)?


DXGIDirect3D와 함께 쓰이는 API입니다. 여기에는 여러 그래픽 API에 공통적인 그래픽 관련 작업들이 존재합니다. 예를 들어, 앞서 배운 SwapChainAPI도 여기에 속해있습니다. 또한, 우리가 게임을 시작해 옵션에 들어가면 창모드와 전체화면 설정을 볼 수 있을 것입니다. 이 기능 또한 DXGI에서 그래픽 설정을 통해 구현할 수 있습니다.

DXGI에는 핵심적인 인터페이스가 있습니다. IDXGIFactory라는 인터페이스인데 이름부터 공장 찍어내듯이 그래픽을 찍어낼 것 같군요. IDXGI에는 IDXGISwapChain 인터페이스 생성과 디스플레이 어댑터 열거가 있습니다. SwapChain은 앞서 배웠기 때문에 무엇인가 알 수 있겠지만 디스플레이 어댑터 열거라는 것이 걸리는 군요.

디스플레이 어댑터는 물리적인 하드웨어 장치를 의미합니다. 쉽게 말해 그래픽 카드입니다. 하지만, 이것을 흉내 내는 소프트웨어 디스플레이 어댑터도 존재합니다. 하나의 시스템에 여러 개의 어댑터가 있을 수 있는데 한 예로, 알파고의 GPU100개가 넘었죠……


CPUGPU의 상호작용


-       Command QueueCommand List

n  그래픽 프로그래밍에서는 CPUGPU에 의해 작동합니다. 둘은 병렬로 작동하기 때문에 동기화가 필요합니다. 동기화란, 한 처리 장치가 작업을 마칠 때까지 다른 한 처리 장치가 놀고 있어야 함을 의미합니다. 하지만, 최적의 성능을 위해서는 하나라도 멈춰서는 안됩니다.

n  GPU에는 명령 대기열(Command Queue)이 하나 있습니다. CPU는 그리기 명령들이 담긴 명령 목록(Command List)Direct3D API를 통해서 GPU의 대기열에 제출합니다. 대기열에 명령이 추가되면 GPU가 이 명령들을 뽑아 실행합니다. 하지만, 대기열에 명령이 추가된다 하더라도 그 명령을 바로 실행하는 것은 아닙니다.

n  명령 대기열을 대표하는 인터페이스는 ID3D12CommandQueue입니다.

n  명령 목록을 대표하는 인터페이스는 ID3D12GraphicsCommandList입니다. 이 인터페이스에는 명령들을 목록에 추가하는 다양한 함수들이 있습니다. 하지만, 이 명령들을 대기열에 추가하기 위해서는 ExcuteCommandLists를 호출해야만 합니다. 호출하지 않으면 그저 목록에 추가만 할 뿐이기 때문입니다. 하지만, 명령 목록은 현재 명령들을 추가하는 명령 목록 이외에는 모두 닫혀있어야 합니다. 명령들을 여러 명령 목록에 동시에 기록할 수는 없기 때문입니다. 따라서, 명령을 대기열에 추가한 뒤 Close함수를 통해 닫아줘야 합니다.

n  명령 목록에는 메모리 할당자가 부여됩니다. 추가된 명령들은 이 할당자의 메모리에 저장이 됩니다. 대기열이 명령을 실행할 때 이 할당자를 참조하기 때문에 명령이 실행되기 전까지는 재설정해서는 안됩니다. 명령이 실행되기 전에 재설정 시 대기열은 실행해야 할 명령을 실행하지 않고, 변경된 명령을 실행하게 될 것입니다. 컴파일러가 막아주겠지만 유의해야 합니다. 할당자는 ID3D12CommandAllocator형식의 인터페이스가 존재합니다.

-       Fence

n  FenceGPU가 대기열의 지정된 지점까지의 모든 명령을 처리할 때까지 CPU를 기다리게 하는 것입니다. ID3D12Fence 인터페이스가 대표적입니다. 이것이 GPUCPU의 동기화 방법 중 하나입니다.

-       Transition Resource Barrier

n  GPU가 리소스에 데이터를 다 기록하지 않았거나, 기록을 아예 시작하지도 않은 상태에서 리소스의 데이터를 읽으려 하면 문제가 생기는 상황을 리소스 하자드라고 합니다. 줄여서 리자드라 부르겠습니다. (사실 책에서는 자원 위험 상황이라고 하지만 뭔가 어감이 이상해서 이렇게 부르겠습니다.)

n  자원 상태 전이는 리자드를 해결하기 위해, Direct3D가 리소스들에게 상태를 부여하는 것을 의미합니다. 예를 들어 텍스처 리소스에 데이터를 기록해야 할 때에는 텍스처의 상태를 Render Target 상태로 설정합니다. 이후 텍스처의 데이터를 읽어야 할 때가 되면 상태를 셰이더 리소스 상태로 변경합니다. 프로그램이 상태 전이를 Direct3D에게 보고함으로써, GPU는 리자드를 피하는 데 필요한 조치를 할 수 있습니다.

n  Transition Resource BarrierGPU에게 리소스의 상태가 전이됨을 알려주는 하나의 명령입니다. 배리어 덕분에 GPU는 이후의 명령들을 실행할 때 리자드를 피하는 데 필요한 단계들을 밟을 수 있게 됩니다.


Direct3D의 초기화


1.     D3D12CreateDevice함수를 이용해서 ID3D12Device를 생성한다.

A.     초기화 과정은 길지만, 프로그램이 실행 시 한 번만 초기화하면 됩니다.

B.       

2.     ID3D12Fence 객체를 생성하고 Descriptor들의 크기를 얻는다.

3.     4X MSAA* 품질 수준 지원 여부를 점검한다.

4.     Command QueueCommand List Allocator 그리고 Command List를 생성한다.

5.     Swap ChainDescript하고 생성한다.

6.     응용 프로그램에 필요한 Descriptor Heap들을 생성한다.

7.     후면 버퍼의 크기를 설정하고, 후면 버퍼에 대한 Render Target View를 생성한다.

8.     Depth and Stencil 버퍼를 생성하고, 그와 연관된 Depth and Stencil View를 생성한다.

9.     뷰포트와 Scissor Rectangle들을 설정한다.


성능 타이머


 성능타이머의 시간 측정 단위는 Tick의 개수입니다. 언리얼 엔진을 다루어 보신 분이라면 익숙할 단어네요. 틱 수 단위의 현재 시간을 얻을 때에는 QueryPerformanceCounter 함수를 사용하고, 초 단위 시간을 얻기 위해서는 QueryPerformanceFrequency 함수를 사용합니다. 두 함수 모두 자료형이 LARGE_INTEGER*인 매개변수로부터 값을 반환합니다.


 mSecondsPerCount = 1.0 / (double) countsPerSec  (1sec/초당 틱 수 = 틱당 초 수)를 보아하니 주파수와 주기율의 관계를 보는 듯 합니다. 틱당 초 수에 틱 수를 곱하면 초 단위 시간이 도출됩니다.


 valueInSecs = valueInSecs * mSecondsPerCount


하지만, 중요한 것은 항상 성능 타이머가 돌려준 실제 값들 자체가 아니라 측정한 두 시간 값 사이의 상대적 차이입니다. 따라서, 두 개의 값의 차에 틱당 초 수를 곱해줌으로써 우리는 어떤 작업을 했을 때 걸린 시간을 얻을 수 있습니다.


 시간 측정에 관해서는 꼭 교재를 참고해주시길 바랍니다. 이 부분은 수학적인 부분도 많고, 코드와 그림도 많이 첨부되어 있어 요약한 내용으로는 부족한 부분이 많아 이해하기 힘들 것입니다. 내용을 요약하려니 요약하기가 어려운 파트였던 것 같습니다.

이상으로 4장을 마치겠습니다. 4.5절에서 Win32프로그래밍 지식이 전제조건이라 하는데 이것도 공부를 해야 할 것 같군요 ㅠㅠ


'GameDev > DirectX12' 카테고리의 다른 글

렌더링 파이프라인  (0) 2018.08.17
변환(Transformation)  (0) 2018.08.17
행렬(Matrix)  (0) 2018.07.25
벡터(Vector)  (0) 2018.07.25

 이번에는 변환에 대해서 공부하겠습니다. 3차원 그래픽은 3차원 세계의 물체들을 기하학적으로 묘사한다고 합니다. 무슨 말인지 이해하기 힘들어 친절하게도 책에서는 구체적으로 설명한다고 해서 읽어보니 물체의 외부 표면을 근사(approximation)하는 일단의 삼각형들로 물체를 표현한다고 하는데 일단의 삼각형이 뭔지를 모르겠네요. 오히려 더 이해가 안가는 상황이 왔습니다.

 

- 선형변환

선형변환이란, 벡터 v를 함수 에 대입했을 때 이 될 때 선형 변환이라고 합니다. 하지만, 선형변환이 되기 위해서는 두 가지 조건이 필요합니다.


첫 번째로 이고, 두 번째는입니다. 이때 k는 스칼라 값입니다.

선형변환은 기저벡터를 이용해 행렬로 표현할 수 있습니다.

                                


다음과 같이 선형변환은 행렬로 표현하며, 이러한 행렬A를 선형변환 의 행렬 표현이라고 부릅니다.

- 비례

비례행렬은 Scaling이라고 하며 확대 및 축소를 의미합니다. 따라서, 벡터 값이 비례행렬과 행렬 곱을 하였을 때 벡터의 크기를 조절할 수 있도록 해줍니다

비례행렬은

이렇게 행렬 표현합니다.


- 회전

회전 행렬의 기하학적 의미로는 벡터v를 축 n에 대해 회전함을 의미합니다. 아름다운 증명 과정이 있지만 생략을 하고, 회전 행렬 R을 식으로 표현하면



입니다. 여기서 c 을 의미하며, ssin 를 의미합니다. 회전행렬에는 각 행벡터가 단위 길이이고, 서로 직교라는 성질을 가지고 있습니다. 따라서 행벡터들은 정규직교를 나타냅니다. 또한, 직교행렬은 그 역행렬이 전치행렬과 같다는 성질을 가지고 있습니다.

회전 행렬은 각 회전축(x,y,z)에 따른 회전행렬을 가지고 있습니다.



이와 같이 회전 행렬은 특정 축만을 이용하여 벡터를 회전시킬 수 있습니다.


- 아핀변환

아핀변환은 선형변환에 이동변환을 결합한 것을 의미합니다. 하지만, 벡터는 방향과 크기를 의미하기 때문에 이동에 대해서는 불변이어야 합니다. 이동을 표현하기 위해서는 벡터가 아닌 점에 적용해야 합니다. 동차좌표를 이용해 벡터와 점을 동일한 방식으로 다룰 수 있습니다.

아핀변환은 선형변환에 이동변환을 결합한 것을 의미한다고 했습니다.

이동변환은 이동벡터 b로 표현할 때, 아핀변환 를 수식으로 표현하면 다음과 같습니다.



행렬로 표현하면


(여기서, A는 선형변환의 행렬 표현입니다.)


- 동차좌표

동차좌표는 3차원 벡터에 w성분을 추가한 4차원 벡터입니다. w값에 따라 동차좌표가 벡터인지 점인지를 나타낼 수 있습니다. 예를 들어 w1일 때 점을 나타내고, 0일 때 벡터를 나타냅니다. 따라서, 이동변환을 적용시키기 위해서는 w값을 1로 설정해야 합니다. w값이 0일 때에는 벡터의 성분들이 바뀌지 않기 때문에 크기와 방향을 유지할 수 있습니다.

w=1인 동차좌표를 도입했을 때 아핀변환을 다음과 같이 나타낼 수 있습니다.



b0일 때에는 점이 아닌 벡터로 일반적인 선형변환과 같음을 나타냅니다.

아핀변환 행렬의 기하학적 해석을 나타내자면 강체변환, 즉 변환 시 물체의 형태가 그대로 유지되는 변환을 의미합니다. 따라서, 회전, 이동, 비례 행렬을 적용하였을 때, 변환을 적용한 물체는 변환 전과 같은 모양을 유지합니다.

- 이동

이동변환은 선형변환 부분이 하나의 단위행렬인 아핀변환이라고 정의할 수 있습니다.

여기서, I는 항등변환입니다.)

위와 같은 수식은 ub만큼 이동함을 의미합니다.

이동행렬 T는 다음과 같이



으로 표현할 수 있습니다.


- 좌표 변경 변환

한 좌표계의 좌표를 다른 좌표계의 자표로 변환하는 것을 좌표 변경 변환이라고 합니다. 따라서, 좌표 변경 변환을 적용한 물체에서 바뀐 것은 좌표들의 기준인 좌표계 뿐 입니다.  이것은 비례, 회전, 이동 변환과는 대조적임을 의미합니다.

 


'GameDev > DirectX12' 카테고리의 다른 글

렌더링 파이프라인  (0) 2018.08.17
Direct3D의 초기화  (0) 2018.08.17
행렬(Matrix)  (0) 2018.07.25
벡터(Vector)  (0) 2018.07.25

한이음 프로젝트가 끝난 뒤 언능 게임을 만들고 싶어


동아리도 찾아보고, 게임 개발사이트를 샅샅이 뒤졌지만 팀 구하기란 하늘에 별따기 였을 때


굳이 국내에서만 찾으란 법은 없다는 생각에 무작정 해외사이트인 gamedev.net에서 구한 팀 프로젝트입니다.


디스코드를 이용하여 커뮤니케이션을 나눴고, 기획서는 hacknplan이라는 사이트에서 공유받았었습니다.


트렐로와 비슷하지만 게임에 특화되었던 사이트인데 신기했습니다.


비록 프로젝트는 무산되었지만, 혼자서 XCOM2 기반의 턴제 게임 시스템을 개발하면서 엄청 공부했던 것 같습니다.


타일에 시각적 표현을 위해 A* 알고리즘을 공부한 뒤 구현해보기도 하고,


특히, 목표 지점으로 움직이는 것이었습니다. 이것때문에 유튜브를 찾아보거나(심지어 프랑스언어까지 있었다는...)


트러블 슈터 제작자 분들에게 페이스북 메세지까지 보내 정보를 얻었습니다.


결국, 구현은 했지만 구현하자마자 팀이 해체되고 말았지요 ㅠㅠ


그래도 꽤 재밌었던 것 같습니다. 이때 유튜브 엄청 돌려봐서 그런가 영어 듣기도 좀 늘었고;;


디스코드로 채팅하다보니 영작도 늘고


역시 초보자들만 모였던 것이 문제인지 진행속도도 느렸고, 피드백도 엄청 오래걸렸던 걸로 기억하네요.


다음에 실력이 늘면 다시 도전해보아야 겠습니다.






'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #6  (0) 2018.08.21
FPS 기능 만들기 프로젝트 #5  (0) 2018.08.21
FPS 기능 만들기 프로젝트 #4  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #3  (0) 2018.08.09
FPS 기능 만들기 프로젝트 #2  (0) 2018.08.07

이번에 만든 기능은 재장전 기능입니다. 


개발한 기능에 앞서 달리는 중에 마우스를 떼었다 놓으면 총을 쏘는 버그가 발생해 수정했습니다.


SetFiring이 토글식이었다 보니 달리는 중에 총을 쏘면 토글이 잘못 되어 계속 총을 쏘는 것이었습니다.



간단하게 마우스 왼쪽 클릭을 떼었을 때 새로운 함수를 바인딩하여 해결하였습니다.


재장전 기능은 간단한 산술적인 표현이 들어간 기능이었습니다.


캐릭터 내의 바인딩할 Reload 함수를 작성하였습니다.


Reload함수에서는 달릴 때 재장전을 할 시 달리기 기능을 풀어주는 기능을 포함하였습니다.


다음에 SetTimer함수를 이용하여 애니메이션의 길이만큼 딜레이를 준 뒤, 다른 FPS 처럼 탄창이 장전된 뒤에 탄창이 새로 채워지도록 하였습니다.



다음은 총기 클래스 내의 Reload 함수입니다. 


CliSize는 탄창의 크기, Ammo는 현재 탄창의 잔탄량, MaxAmmo는 현재 가지고 있는 탄창입니다.


ClipSize와 같을 때 장전하면 안되니 제어해주고, RemainAmmo를 이용하여, 잔탄량을 두 가지로 나눠 표현하였습니다.




애님 그래프는 이전에 했던 작업과 똑같으므로 게재하지 않았습니다.


참고 : https://www.youtube.com/playlist?list=PLL0cLF8gjBprG6487lxqSq-aEo6ZXLDLg

Git : https://github.com/Titane22/FPS-Feature




'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #5  (0) 2018.08.21
Operation Indigo  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #3  (0) 2018.08.09
FPS 기능 만들기 프로젝트 #2  (0) 2018.08.07
FPS 기능 만들기 프로젝트 #1  (0) 2018.08.01

이번에는 c++ 클래스를 전체적으로 클래스 명을 리팩토링 하였습니다. 불필요한 부분도 삭제해줬구요.


역시 소스는 정리해야 찾기가 편하네요.


하지만, 익숙치 않아 꽤 많이 돌아갔네요. 이전에 Udemy 강의를 보며 해보긴 했지만 감으로만 하다가 큰일 날뻔 했습니다.


다음으로 달리기 기능을 수정했습니다.


앞,뒤,좌,우로 달릴 수 있었던 이전과는 달리 오직 앞으로만 달릴 수 있도록 하였습니다.


처음에는 벡터를 배운 김에 멋지게 활용해보자 했지만, 역시 겉 멋들고 어렵게 생각할수록 


시간만 잡아먹는 것 같습니다. 


Simple is Best 


다른 분야는 잘 모르지만 역시 똑같은 결과라면 화려하기보다는 무조건 간단해야 하는 것 같습니다.


즐겨하던 레인보우식스 시즈로부터 생각나서 이같은 방향으로 디자인했습니다.


입력 값을 받아  if문에서 제어 해줬는데요.


FwdValue가 오직 1일 때에만 달릴 수 있습니다.


또한 좌우 축키와 바인딩 된 MoveRight에서는 달리는 중을 의미하는 불 변수 bSprintTrue가 참 일 경우 입력을 할 수 없도록 하였습니다.


bIsAiming은 나중에 나올 조준모드 임을 나타내는 불 변수입니다. 아무생각없이 조준하고 달렸다가 토 나올 뻔했습니다;;;;


다음은 탄환의 삭제 기능을 수정했습니다.


기존에 있던 탄환은 Mobility가 Movable인 물체에 닿았을 때에만 삭제가 되었습니다.



if문과 else if문의 차이는 IsSimulatingPhysics 함수의 유무입니다.


IsSimulatingPhysics()의 원본은 UPrimitiveComponent::IsSimulatingPhysics() 입니다. 


부딪힌 물체가 현재 physics simulation을 사용 중인지 반환해주는지를 알려주는 함수입니다.


기존에 상자가 아닌 벽과 부딪혔을 때에는 이 함수가 false를 반환해줬기 때문에 탄환이 삭제되지 않았습니다.


따라서, else if문에서는 이 함수를 제거하고 AddImpulseAtLocation 함수를 제거하여 가해지는 힘을 제거했습니다. 


어차피 무버블이 아니기 때문에 어떤 힘을 가해도 의미가 없으니깐요 ㅎㅎ


다음은 조준 모드입니다.


먼저 프로젝트 세팅에서 마우스 오른쪽 클릭을 두 함수와 바인딩시켰습니다.





FollowCamera는 기본 FPS 카메라이며 ADSCamera는 조준 모드시의 카메라입니다.


함수 자체를 구현하는 것은 굉장히 쉬웠습니다. 점점 키 바인딩 함수에 대해 익숙해져 이런 것쯤은 별거 아니군요. 


하지만, 역시 애니메이션을 건드리는 건 무섭습니다....눈_눈


마지막으로 남은 탄환을 나타내는 위젯을 이용해 UI를 추가했습니다. 텍스트만 이용하면 됐기 때문에 매우 간단했습니다.


참고 : https://www.youtube.com/playlist?list=PLL0cLF8gjBprG6487lxqSq-aEo6ZXLDLg

Git : https://github.com/Titane22/FPS-Feature




'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #5  (0) 2018.08.21
Operation Indigo  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #4  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #2  (0) 2018.08.07
FPS 기능 만들기 프로젝트 #1  (0) 2018.08.01


지금까지 제작한 기능은 


앉기, 달리기 그리고 마우스의 위치에 따른 시점 변화입니다.


먼저, 앉기와 달리기 입니다. 

프로젝트 세팅에서 왼쪽 컨트롤 키를 액션 키로 설정해줘야 합니다.


하지만, 처음 설정을 FPS이다 보니 설정이 되어 있었습니다.


이후 캐릭터의 클래스에서 키를 Binding 해줍니다.


저는 아래와 같이 키를 바인딩 시켰습니다.




if문은 두 액션 키가 겹치지 않도록 하기 위함입니다. CharacterMovement에 접근하여 최대 스피드를 조정하였습니다.


애니메이션을 변경하기 위해 애니메이션의 애님 그래프를 이용하였습니다. 


각 상태를 생성하고 상태를 오가는 불 변수에 따라 애니메이션이 변경됩니다.


AnimInstance 클래스를 상속하여 Swap_Anim 클래스를 생성하였고, 


NativeUpdateAnimation 메소드를 가상함수로 상속받아 사용했습니다.


캐릭터의 방향 값을 계산하기 위해 캐릭터의 속도와 방향을 


float CalculateDirection(const FVector & Velocity, const FRotator & BaseRotation)  


의 매개변수로 입력하여 Direction에 저장하였습니다.


속도는 벡터의 크기를 나타내는 Size함수를 이용하여 Speed에 저장하였습니다.


 



계산한 변수들은 다음과 같이 세팅 하였습니다. 달리기 애니메이션은 Sprint_BS를 만들어 Crouch_BS와 같이 설정하였습니다.


아래 사진은 애니메이션 변경을 위해 애님 그래프의 Transition에서 설정했습니다.


다음은 캐릭터의 마우스에 따른 시점입니다.


다른 애니메이션과 같이 Swat_Anim 클래스의 NativeUpdateAnimation에서 작성하였습니다.


현재 마우스의 위치 값을 받는 GetControlRotation을 이용하여 최종적으로  AimDirection 변수에 반환하였습니다.


반환한 AimDirection 값은 애님 그래프에서 



이렇게 설정하였습니다. 본 트랜스 폼은 현재 설정된 Spine,Spine1,Spine2의 방향 값을 바꿔줌으로써 


시점에 따라 애니메이션의 방향을 변경하도록 해줍니다.


여기까지 진행하였는데요


강좌에는 없지만 FPS 매니아로써 좌,우 심지어 뒤로도 달릴수 있는게 맘에 안드는군요.


다음에는 오로지 대각선과 전방을 향해 움직일 때만 달릴 수 있도록 추가해보겠습니다. 


감사합니다.


참고 : https://www.youtube.com/playlist?list=PLL0cLF8gjBprG6487lxqSq-aEo6ZXLDLg

Git : https://github.com/Titane22/FPS-Feature


'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #5  (0) 2018.08.21
Operation Indigo  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #4  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #3  (0) 2018.08.09
FPS 기능 만들기 프로젝트 #1  (0) 2018.08.01

현재 FPS 게임의 각종 기능을 만들어보기 위해 새로운 프로젝트를 시작했습니다.


아래 사이트를 참조하여 c++을 이용해 9강까지 진행하였는데요.


아직 Actor클래스의 파생 클래스의 생성자에서 Static Mesh설정과 Material설정을 하지 못해 어려움을 겪었습니다.


일단, 코드를 작성했을 때 정상적으로 실행은 되었지만, 눈으로 보이는게 없으니 답답하여 주석처리하고 블루프린트로 작성하였습니다. ㅎㅎ;


구글링도 통달한 줄 알았더니 아직도 부족한가 봅니다.


언능 숙지하고 블루프린트를 삭제하고 저의 코드를 적용해보겠습니다. 


현재 생각 중인 기능은

-       앉기(c키를 눌러 앉기 모드)

-       눕기(z키를 눌러 눕기 모드)

-       점프(스페이스 키를 눌러 활성화)

-       줌인(오른쪽 키를 눌러 무기 줌 상태)

-       달리기(쉬프트 키를 눌러 활성화)

-       걷기(알트 키를 눌러 활성화)

-       기울이기(Q, E를 이용한 몸 기울이기)

-       이단 점프(점프 중 스페이스 키를 눌러 활성화)

-       벽 매달리기(난간에 가까울 시 벽에 매달려 올라가기)

-       벽 달리기(벽 옆에서 달릴 시 활성화)

이렇게 있습니다.


제가 보고 있는 강의에서 앉기, 달리기 등이 있는데 이러한 기능들은 강의를 보면서 c++로 변환해보겠습니다.

(솔직히 쉬워보이지만, 아직 애니메이션을 다루는 부분이 어렵네요;; ㅠㅠ)


기울이기는 레인보우식스 시즈를 모방하여 해보아야 겠습니다. (이것도 애니메이션이 필요한게 아닌지 ㅠㅠ 안되면 카메라만 기울여야 겠습니다.ㅋ)


이단 점프, 벽 매달리기, 벽 달리기는 제가 좋아하는 타이탄폴2를 생각하며 적어보았습니다. 


이것들도 애니메이션이 필요해서 구할 수 있다면 적용시켜보겠습니다.




동영상을 보아하니 에임에 따른 총구 위치 변화와 탄환의 삭제가 절실해 보이네요. 바로 DestroyActor를 이용해 삭제시켜버리겠습니다 ㅎㅎ













참고 : https://www.youtube.com/channel/UCz-eYJAUgSE-mqzKtit7m9g

Git : https://github.com/Titane22/FPS-Feature

'GameDev > Unreal' 카테고리의 다른 글

FPS 기능 만들기 프로젝트 #5  (0) 2018.08.21
Operation Indigo  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #4  (0) 2018.08.14
FPS 기능 만들기 프로젝트 #3  (0) 2018.08.09
FPS 기능 만들기 프로젝트 #2  (0) 2018.08.07

+ Recent posts