Thinking Different




Terrain 01 - 그리드 및 카메라 이동



원문 : http://www.rastertek.com/tertut01.html



 이 튜토리얼은 DirectX 11을 사용하여 지형 그리드 렌더링의 기본 사항을 다룹니다. 이 튜토리얼의 목적은 고급 지형 개념을 익히기 전에 기본 격자 지형을 렌더링하고 좋은 카메라 기능을 사용할 수 있도록 하는 것입니다. 지형을 쉽게 이동할 수 있는 우수한 카메라를 사용하면 개발 중에 발생하는 문제를 디버깅하는 데 도움이 됩니다. 우수한 디버깅 도구를 갖추는 것이 개발 속도를 높이고 품질을 보장하는 핵심 요소입니다. 또한이 듀토리얼은 DirectX 11 Basic 듀토리얼의 지식과 프레임 워크를 기반으로 합니다. 만약 기본이 갖추어져 있지 않다면 DirectX 11 Basic 듀토리얼 강좌란으로 이동하여 필요한 부분을 선행학습 하신 다음 진행하시기 바랍니다.


이 듀토리얼의 격자는 기본 100x100 단위 평면 지형입니다. TerrainClass라는 새로운 클래스는 라인으로 만들어진 쿼드를 구성하기 위해 캡슐화 하였습니다. 카메라는 또한 PositionClass라는 새로운 클래스를 기반으로 합니다 (CameraClass는 여전히 뷰 매트릭스를 만드는 데 사용되며 기능을 분리했습니다). PositionClass는 카메라가 지형 주위를 부드럽게 움직일 수 있도록 카메라의 위치와 회전 및 가속과 감속을 유지합니다. 마지막으로 TextClass를 다시 사용하여 FPS, CPU 사용량, 비디오 카드 정보 및 카메라의 위치 / 회전을 표시합니다.



프레임워크




프레임 작업에는 새로운 TerrainClass 및 PositionClass가 포함됩니다. 나머지 클래스는 이미 DirectX 11 튜토리얼 섹션에서 다루었습니다.



지형 클래스는 100x100 선 그리기를 위한 모델 데이터 및 렌더링 기능을 캡슐화합니다. 이 튜토리얼은 매우 기본적인 지형을 먼저 얻는데 중점을 둡니다.


Terrainclass.h


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#pragma once
 
class TerrainClass
{
private:
    struct VertexType
    {
        XMFLOAT3 position;
        XMFLOAT4 color;
    };
 
public:
    TerrainClass();
    TerrainClass(const TerrainClass&);
    ~TerrainClass();
 
    bool Initialize(ID3D11Device*intint);
    void Shutdown();
    void Render(ID3D11DeviceContext*);
 
    int GetIndexCount();
 
private:
    bool InitializeBuffers(ID3D11Device*);
    void ShutdownBuffers();
    void RenderBuffers(ID3D11DeviceContext*);
    
private:
    int m_terrainWidth = 0;
    int m_terrainHeight = 0;
    int m_vertexCount = 0;
    int m_indexCount = 0;
    ID3D11Buffer* m_vertexBuffer = nullptr;
    ID3D11Buffer* m_indexBuffer = nullptr;
};
cs



Terrainclass.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#include "stdafx.h"
#include "terrainclass.h"
 
 
TerrainClass::TerrainClass()
{
}
 
 
TerrainClass::TerrainClass(const TerrainClass& other)
{
}
 
 
TerrainClass::~TerrainClass()
{
}
 
 
bool TerrainClass::Initialize(ID3D11Device* device, int terrainWidth, int terrainHeight)
{
    // 지형의 너비와 높이를 설정합니다.
    m_terrainWidth = terrainWidth;
    m_terrainHeight = terrainHeight;
 
    // 지형에 대한 지오 메트릭을 포함하는 정점 및 인덱스 버퍼를 초기화합니다.
    return InitializeBuffers(device);
}
 
 
void TerrainClass::Shutdown()
{
    // 버텍스와 인덱스 버퍼를 해제합니다.
    ShutdownBuffers();
}
 
 
void TerrainClass::Render(ID3D11DeviceContext* deviceContext)
{
    // 그리기를 준비하기 위해 그래픽 파이프 라인에 꼭지점과 인덱스 버퍼를 놓습니다.
    RenderBuffers(deviceContext);
}
 
 
int TerrainClass::GetIndexCount()
{
    return m_indexCount;
}
 
 
bool TerrainClass::InitializeBuffers(ID3D11Device* device)
{
    // 지형 메쉬의 정점 수를 계산합니다.
    m_vertexCount = (m_terrainWidth - 1* (m_terrainHeight - 1* 8;
 
    // 인덱스 수를 꼭지점 수와 같게 설정합니다.
    m_indexCount = m_vertexCount;
 
    // 정점 배열을 만듭니다.
    VertexType* vertices = new VertexType[m_vertexCount];
    if(!vertices)
    {
        return false;
    }
 
    // 인덱스 배열을 만듭니다.
    unsigned long* indices = new unsigned long[m_indexCount];
    if(!indices)
    {
        return false;
    }
 
    // 정점 배열에 대한 인덱스를 초기화합니다.
    int index = 0;
 
    // 지형 데이터로 정점 및 인덱스 배열을 로드합니다.
    for(int j=0; j<(m_terrainHeight-1); j++)
    {
        for(int i=0; i<(m_terrainWidth-1); i++)
        {
            // LINE 1
            // 왼쪽 위.
            float positionX = (float)i;
            float positionZ = (float)(j+1);
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // 오른쪽 위.
            positionX = (float)(i+1);
            positionZ = (float)(j+1);
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // LINE 2
            // 오른쪽 위.
            positionX = (float)(i+1);
            positionZ = (float)(j+1);
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // 오른쪽 아래.
            positionX = (float)(i+1);
            positionZ = (float)j;
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // LINE 3
            // 오른쪽 아래.
            positionX = (float)(i+1);
            positionZ = (float)j;
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // 왼쪽 아래.
            positionX = (float)i;
            positionZ = (float)j;
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // LINE 4
            // 왼쪽 아래.
            positionX = (float)i;
            positionZ = (float)j;
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;
 
            // 왼쪽 위.
            positionX = (float)i;
            positionZ = (float)(j+1);
 
            vertices[index].position = XMFLOAT3(positionX, 0.0f, positionZ);
            vertices[index].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
            indices[index] = index;
            index++;            
        }
    }
 
    // 정적 정점 버퍼의 구조체를 설정한다.
    D3D11_BUFFER_DESC vertexBufferDesc;
    vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount;
    vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexBufferDesc.CPUAccessFlags = 0;
    vertexBufferDesc.MiscFlags = 0;
    vertexBufferDesc.StructureByteStride = 0;
 
    // subresource 구조에 정점 데이터에 대한 포인터를 제공합니다.
    D3D11_SUBRESOURCE_DATA vertexData;
    vertexData.pSysMem = vertices;
    vertexData.SysMemPitch = 0;
    vertexData.SysMemSlicePitch = 0;
 
    // 이제 정점 버퍼를 만듭니다.
    if(FAILED(device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer)))
    {
        return false;
    }
 
    // 정적 인덱스 버퍼의 구조체를 설정합니다.
    D3D11_BUFFER_DESC indexBufferDesc;
    indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    indexBufferDesc.ByteWidth = sizeof(unsigned long* m_indexCount;
    indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
    indexBufferDesc.CPUAccessFlags = 0;
    indexBufferDesc.MiscFlags = 0;
    indexBufferDesc.StructureByteStride = 0;
 
    // 하위 리소스 구조에 인덱스 데이터에 대한 포인터를 제공합니다.
    D3D11_SUBRESOURCE_DATA indexData;
    indexData.pSysMem = indices;
    indexData.SysMemPitch = 0;
    indexData.SysMemSlicePitch = 0;
 
    // 인덱스 버퍼를 만듭니다.
    if(FAILED(device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer)))
    {
        return false;
    }
 
    // 이제 버퍼가 생성되고 로드된 배열을 해제하십시오.
    delete [] vertices;
    vertices = 0;
 
    delete [] indices;
    indices = 0;
 
    return true;
}
 
 
void TerrainClass::ShutdownBuffers()
{
    // 인덱스 버퍼를 해제합니다.
    if(m_indexBuffer)
    {
        m_indexBuffer->Release();
        m_indexBuffer = 0;
    }
 
    // 버텍스 버퍼를 해제합니다.
    if(m_vertexBuffer)
    {
        m_vertexBuffer->Release();
        m_vertexBuffer = 0;
    }
}
 
 
void TerrainClass::RenderBuffers(ID3D11DeviceContext* deviceContext)
{
    // 정점 버퍼 보폭 및 오프셋을 설정합니다.
    unsigned int stride = sizeof(VertexType); 
    unsigned int offset = 0;
    
    // 렌더링 할 수 있도록 입력 어셈블러에서 정점 버퍼를 활성으로 설정합니다.
    deviceContext->IASetVertexBuffers(01&m_vertexBuffer, &stride, &offset);
 
    // 렌더링 할 수 있도록 입력 어셈블러에서 인덱스 버퍼를 활성으로 설정합니다.
    deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
 
    // 이 버텍스 버퍼에서 렌더링되어야하는 프리미티브의 타입을 설정한다.이 경우 라인리스트이다.
    deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
}
cs



PositionClass는 카메라 / 뷰어 위치와 카메라 이동 기능을 캡슐화하는 클래스입니다.


Positionclass.h


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#pragma once
 
class PositionClass
{
public:
    PositionClass();
    PositionClass(const PositionClass&);
    ~PositionClass();
 
    void SetPosition(XMFLOAT3);
    void SetRotation(XMFLOAT3);
 
    void GetPosition(XMFLOAT3&);
    void GetRotation(XMFLOAT3&);
 
    void SetFrameTime(float);
 
    void MoveForward(bool);
    void MoveBackward(bool);
    void MoveUpward(bool);
    void MoveDownward(bool);
    void TurnLeft(bool);
    void TurnRight(bool);
    void LookUpward(bool);
    void LookDownward(bool);
 
private:
    XMFLOAT3 m_position = XMFLOAT3(0.0f, 0.0f, 0.0f);
    XMFLOAT3 m_rotation = XMFLOAT3(0.0f, 0.0f, 0.0f);
 
    float m_frameTime = 0;
 
    float m_forwardSpeed = 0;
    float m_backwardSpeed = 0;
    float m_upwardSpeed = 0;
    float m_downwardSpeed = 0;
    float m_leftTurnSpeed = 0;
    float m_rightTurnSpeed = 0;
    float m_lookUpSpeed = 0;
    float m_lookDownSpeed = 0;
};
cs



Positionclass.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#include "stdafx.h"
#include "PositionClass.h"
 
 
PositionClass::PositionClass()
{
}
 
 
PositionClass::PositionClass(const PositionClass& other)
{
}
 
 
PositionClass::~PositionClass()
{
}
 
 
void PositionClass::SetPosition(XMFLOAT3 pos)
{
    m_position = pos;
}
 
 
void PositionClass::SetRotation(XMFLOAT3 rot)
{
    m_rotation = rot;
}
 
 
void PositionClass::GetPosition(XMFLOAT3& p)
{
    p = m_position;
}
 
 
void PositionClass::GetRotation(XMFLOAT3& p)
{
    p = m_rotation;
}
 
 
void PositionClass::SetFrameTime(float time)
{
    m_frameTime = time;
}
 
 
void PositionClass::MoveForward(bool keydown)
{
    // 키를 누르면 카메라가 왼쪽으로 돌아는 속도가 증가합니다. 회전 속도를 늦추지 않으면.
    if (keydown)
    {
        m_forwardSpeed += m_frameTime * 0.001f;
 
        if(m_forwardSpeed > (m_frameTime * 0.03f))
        {
            m_forwardSpeed = m_frameTime * 0.03f;
        }
    }
    else
    {
        m_forwardSpeed -= m_frameTime * 0.0007f;
 
        if(m_forwardSpeed < 0.0f)
        {
            m_forwardSpeed = 0.0f;
        }
    }
 
    // 값을 라디안으로 변환하십시오.
    float radians = m_rotation.y * 0.0174532925f;
 
    // 위치를 업데이트 합니다.
    m_position.x += sinf(radians) * m_forwardSpeed;
    m_position.z += cosf(radians) * m_forwardSpeed;
}
 
 
void PositionClass::MoveBackward(bool keydown)
{
    // 키를 누르면 카메라가 오른쪽으로 회전하는 속도가 증가합니다. 회전 속도를 늦추지 않으면.
    if (keydown)
    {
        m_backwardSpeed += m_frameTime * 0.001f;
 
        if(m_backwardSpeed > (m_frameTime * 0.03f))
        {
            m_backwardSpeed = m_frameTime * 0.03f;
        }
    }
    else
    {
        m_backwardSpeed -= m_frameTime * 0.0007f;
        
        if(m_backwardSpeed < 0.0f)
        {
            m_backwardSpeed = 0.0f;
        }
    }
 
    // 값을 라디안으로 변환하십시오.
    float radians = m_rotation.y * 0.0174532925f;
 
    // 위치를 업데이트 합니다.
    m_position.x -= sinf(radians) * m_backwardSpeed;
    m_position.z -= cosf(radians) * m_backwardSpeed;
}
 
 
void PositionClass::MoveUpward(bool keydown)
{
    // 사용자가 키를 누르고 있는 프레임 시간에 따라 상향 이동 속도를 갱신합니다.
    if(keydown)
    {
        m_upwardSpeed += m_frameTime * 0.003f;
 
        if(m_upwardSpeed > (m_frameTime * 0.03f))
        {
            m_upwardSpeed = m_frameTime * 0.03f;
        }
    }
    else
    {
        m_upwardSpeed -= m_frameTime * 0.002f;
 
        if(m_upwardSpeed < 0.0f)
        {
            m_upwardSpeed = 0.0f;
        }
    }
 
    // 높이 위치를 업데이트 합니다.
    m_position.y += m_upwardSpeed;
}
 
 
void PositionClass::MoveDownward(bool keydown)
{
    // 사용자가 키를 누르고 있는 프레임 시간에 따라 하향 이동 속도를 갱신합니다.
    if(keydown)
    {
        m_downwardSpeed += m_frameTime * 0.003f;
 
        if(m_downwardSpeed > (m_frameTime * 0.03f))
        {
            m_downwardSpeed = m_frameTime * 0.03f;
        }
    }
    else
    {
        m_downwardSpeed -= m_frameTime * 0.002f;
 
        if(m_downwardSpeed < 0.0f)
        {
            m_downwardSpeed = 0.0f;
        }
    }
 
    // 높이 위치를 업데이트 합니다.
    m_position.y -= m_downwardSpeed;
}
 
 
void PositionClass::TurnLeft(bool keydown)
{
    // 사용자가 키를 누르고 있는 프레임 시간에 따라 왼쪽 회전 속도를 갱신합니다.
    if(keydown)
    {
        m_leftTurnSpeed += m_frameTime * 0.01f;
 
        if(m_leftTurnSpeed > (m_frameTime * 0.15f))
        {
            m_leftTurnSpeed = m_frameTime * 0.15f;
        }
    }
    else
    {
        m_leftTurnSpeed -= m_frameTime* 0.005f;
 
        if(m_leftTurnSpeed < 0.0f)
        {
            m_leftTurnSpeed = 0.0f;
        }
    }
 
    // 회전을 업데이트 합니다.
    m_rotation.y -= m_leftTurnSpeed;
 
    // 회전값의 범위를 0 ~360 에서 유지합니다.
    if(m_rotation.y < 0.0f)
    {
        m_rotation.y += 360.0f;
    }
}
 
 
void PositionClass::TurnRight(bool keydown)
{
    // 사용자가 키를 누르고 있는 프레임 시간에 따라 오른쪽 회전 속도를 갱신합니다.
    if(keydown)
    {
        m_rightTurnSpeed += m_frameTime * 0.01f;
 
        if(m_rightTurnSpeed > (m_frameTime * 0.15f))
        {
            m_rightTurnSpeed = m_frameTime * 0.15f;
        }
    }
    else
    {
        m_rightTurnSpeed -= m_frameTime* 0.005f;
 
        if(m_rightTurnSpeed < 0.0f)
        {
            m_rightTurnSpeed = 0.0f;
        }
    }
 
    // 회전을 업데이트 합니다.
    m_rotation.y += m_rightTurnSpeed;
 
    // 회전값의 범위를 0 ~360 에서 유지합니다.
    if(m_rotation.y > 360.0f)
    {
        m_rotation.y -= 360.0f;
    }
}
 
 
void PositionClass::LookUpward(bool keydown)
{
    // 사용자가 키를 누르고 있는 프레임 시간에 따라 위쪽 회전 속도를 갱신합니다.
    if(keydown)
    {
        m_lookUpSpeed += m_frameTime * 0.01f;
 
        if(m_lookUpSpeed > (m_frameTime * 0.15f))
        {
            m_lookUpSpeed = m_frameTime * 0.15f;
        }
    }
    else
    {
        m_lookUpSpeed -= m_frameTime* 0.005f;
 
        if(m_lookUpSpeed < 0.0f)
        {
            m_lookUpSpeed = 0.0f;
        }
    }
 
    // 회전을 업데이트 합니다.
    m_rotation.x -= m_lookUpSpeed;
 
    // 회전은 최대 90 도로 유지 합니다.
    if(m_rotation.x > 90.0f)
    {
        m_rotation.x = 90.0f;
    }
}
 
 
void PositionClass::LookDownward(bool keydown)
{
    // 사용자가 키를 누르고 있는 프레임 시간에 따라 아래쪽 회전 속도를 갱신합니다.
    if(keydown)
    {
        m_lookDownSpeed += m_frameTime * 0.01f;
 
        if(m_lookDownSpeed > (m_frameTime * 0.15f))
        {
            m_lookDownSpeed = m_frameTime * 0.15f;
        }
    }
    else
    {
        m_lookDownSpeed -= m_frameTime* 0.005f;
 
        if(m_lookDownSpeed < 0.0f)
        {
            m_lookDownSpeed = 0.0f;
        }
    }
 
    // 회전을 업데이트 합니다.
    m_rotation.x += m_lookDownSpeed;
 
    //회전은 최대 90 도로 유지 합니다.
    if(m_rotation.x < -90.0f)
    {
        m_rotation.x = -90.0f;
    }
}
cs




SystemClass는 DirectX 튜토리얼 버전에서 약간 수정되었습니다. 이제는 Windows 초기화 및 새 ApplicationClass 만 포함됩니다.


Systemclass.h


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma once
 
 
class ApplicationClass;
 
 
class SystemClass
{
public:
    SystemClass();
    SystemClass(const SystemClass&);
    ~SystemClass();
 
    bool Initialize();
    void Shutdown();
    void Run();
 
    LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);
 
private:
    bool Frame();
    void InitializeWindows(int&int&);
    void ShutdownWindows();
 
private:
    LPCWSTR m_applicationName;
    HINSTANCE m_hinstance;
    HWND m_hwnd;
 
    ApplicationClass* m_Application = nullptr;
};
 
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static SystemClass* ApplicationHandle = 0;
cs



Systemclass.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
#include "stdafx.h"
#include "ApplicationClass.h"
#include "systemclass.h"
 
 
SystemClass::SystemClass()
{
}
 
 
SystemClass::SystemClass(const SystemClass& other)
{
}
 
 
SystemClass::~SystemClass()
{
}
 
 
bool SystemClass::Initialize()
{
    // 윈도우 창 가로, 세로 넓이 변수 초기화
    int screenWidth = 0;
    int screenHeight = 0;
 
    // 윈도우 생성 초기화
    InitializeWindows(screenWidth, screenHeight);
 
    // 응용 프로그램 객체를 생성합니다.
    m_Application = new ApplicationClass;
    if(!m_Application)
    {
        return false;
    }
 
    // 응용 프로그램 객체를 초기화 합니다.
    if(!m_Application->Initialize(m_hinstance, m_hwnd, screenWidth, screenHeight))
    {
        MessageBox(m_hwnd, L"Could not initialize the application object.", L"Error", MB_OK);
        return false;
    }
    
    return true;
}
 
 
void SystemClass::Shutdown()
{
    // 응용 프로그램 객체를 해제합니다.
    if(m_Application)
    {
        m_Application->Shutdown();
        delete m_Application;
        m_Application = 0;
    }
 
    // 윈도우를 종료합니다.
    ShutdownWindows();
}
 
 
void SystemClass::Run()
{
    // 메시지 구조체 생성 및 초기화
    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));
 
    // 사용자로부터 종료 메시지를 받을때까지 메시지루프를 돕니다
    while (true)
    {
        // 윈도우 메시지를 처리합니다
        if (PeekMessage(&msg, NULL00, PM_REMOVE))
        {
            // 종료 메시지를 받을 경우 메시지 루프를 탈출합니다
            if (msg.message == WM_QUIT)
                break;
 
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            // 그 외에는 Frame 함수를 처리합니다.
            if (!Frame())
                break;
        }
    }
}
 
 
bool SystemClass::Frame()
{
    // 응용 프로그램 개체에 대한 프레임 처리를 수행합니다.
    return m_Application->Frame();
}
 
 
LRESULT CALLBACK SystemClass::MessageHandler(HWND hwnd, UINT umsg, WPARAM wparam, LPARAM lparam)
{
    return DefWindowProc(hwnd, umsg, wparam, lparam);
}
 
 
void SystemClass::InitializeWindows(int& screenWidth, int& screenHeight)
{
    // 외부 포인터를 이 객체로 지정합니다
    ApplicationHandle = this;
 
    // 이 프로그램의 인스턴스를 가져옵니다
    m_hinstance = GetModuleHandle(NULL);
 
    // 프로그램 이름을 지정합니다
    m_applicationName = L"Dx11Terrain_01";
 
    // windows 클래스를 아래와 같이 설정합니다.
    WNDCLASSEX wc;
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = m_hinstance;
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wc.hIconSm = wc.hIcon;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = m_applicationName;
    wc.cbSize = sizeof(WNDCLASSEX);
 
    // windows class를 등록합니다
    RegisterClassEx(&wc);
 
    // 모니터 화면의 해상도를 읽어옵니다
    screenWidth = GetSystemMetrics(SM_CXSCREEN);
    screenHeight = GetSystemMetrics(SM_CYSCREEN);
 
    int posX = 0;
    int posY = 0;
 
    // FULL_SCREEN 변수 값에 따라 화면을 설정합니다.
    if (FULL_SCREEN)
    {
        // 풀스크린 모드로 지정했다면 모니터 화면 해상도를 데스크톱 해상도로 지정하고 색상을 32bit로 지정합니다.
        DEVMODE dmScreenSettings;
        memset(&dmScreenSettings, 0sizeof(dmScreenSettings));
        dmScreenSettings.dmSize = sizeof(dmScreenSettings);
        dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
        dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
        dmScreenSettings.dmBitsPerPel = 32;
        dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
        // 풀스크린으로 디스플레이 설정을 변경합니다.
        ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
    }
    else
    {
        // 윈도우 모드의 경우 800 * 600 크기를 지정합니다.
        screenWidth = 800;
        screenHeight = 600;
 
        // 윈도우 창을 가로, 세로의 정 가운데 오도록 합니다.
        posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
        posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
    }
 
    // 윈도우를 생성하고 핸들을 구합니다.
    m_hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_applicationName, m_applicationName,
                            WS_POPUP,
                            posX, posY, screenWidth, screenHeight, NULLNULL, m_hinstance, NULL);
 
    // 윈도우를 화면에 표시하고 포커스를 지정합니다
    ShowWindow(m_hwnd, SW_SHOW);
    SetForegroundWindow(m_hwnd);
    SetFocus(m_hwnd);
 
    // Hide the mouse cursor.
    ShowCursor(false);
}
 
 
void SystemClass::ShutdownWindows()
{
    // Show the mouse cursor.
    ShowCursor(true);
    
    // 풀스크린 모드였다면 디스플레이 설정을 초기화합니다.
    if (FULL_SCREEN)
    {
        ChangeDisplaySettings(NULL0);
    }
 
    // 창을 제거합니다
    DestroyWindow(m_hwnd);
    m_hwnd = NULL;
 
    // 프로그램 인스턴스를 제거합니다
    UnregisterClass(m_applicationName, m_hinstance);
    m_hinstance = NULL;
 
    // 외부포인터 참조를 초기화합니다
    ApplicationHandle = NULL;
}
 
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
    switch (umessage)
    {
        // 윈도우 종료를 확인합니다
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    }
 
    // 윈도우가 닫히는지 확인합니다
    case WM_CLOSE:
    {
        PostQuitMessage(0);
        return 0;
    }
 
    // 그 외의 모든 메시지들은 시스템 클래스의 메시지 처리로 넘깁니다.
    default:
    {
        return ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
    }
    }
}
cs



ApplicationClass는 전체 지형 응용 프로그램의 기본 래퍼 클래스입니다. 그것은 모든 그래픽, 입력 및 처리를 처리합니다.


Applicationclass.h


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#pragma once
 
/////////////
// GLOBALS //
/////////////
const bool FULL_SCREEN = false;
const bool VSYNC_ENABLED = true;
const float SCREEN_DEPTH = 1000.0f;
const float SCREEN_NEAR = 0.1f;
 
 
class D3DClass;
class InputClass;
class CameraClass;
class TerrainClass;
class ColorShaderClass;
class TimerClass;
class PositionClass;
class FpsClass;
class CpuClass;
class FontShaderClass;
class TextClass;
 
 
class ApplicationClass
{
public:
    ApplicationClass();
    ApplicationClass(const ApplicationClass&);
    ~ApplicationClass();
 
    bool Initialize(HINSTANCE, HWND, intint);
    void Shutdown();
    bool Frame();
 
private:
    bool HandleInput(float);
    bool RenderGraphics();
 
private:
    InputClass* m_Input = nullptr;
    D3DClass* m_Direct3D = nullptr;
    CameraClass* m_Camera = nullptr;
    TerrainClass* m_Terrain = nullptr;
    ColorShaderClass* m_ColorShader = nullptr;
    TimerClass* m_Timer = nullptr;
    PositionClass* m_Position = nullptr;
    FpsClass* m_Fps = nullptr;
    CpuClass* m_Cpu = nullptr;
    FontShaderClass* m_FontShader = nullptr;
    TextClass* m_Text = nullptr;
};
cs



Applicationclass.cpp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
#include "stdafx.h"
#include "inputclass.h"
#include "d3dclass.h"
#include "cameraclass.h"
#include "terrainclass.h"
#include "colorshaderclass.h"
#include "timerclass.h"
#include "positionclass.h"
#include "fpsclass.h"
#include "cpuclass.h"
#include "fontshaderclass.h"
#include "textclass.h"
#include "ApplicationClass.h"
 
 
ApplicationClass::ApplicationClass()
{
}
 
 
ApplicationClass::ApplicationClass(const ApplicationClass& other)
{
}
 
 
ApplicationClass::~ApplicationClass()
{
}
 
 
bool ApplicationClass::Initialize(HINSTANCE hinstance, HWND hwnd, int screenWidth, int screenHeight)
{
    // 입력 개체를 생성합니다.
    m_Input = new InputClass;
    if(!m_Input)
    {
        return false;
    }
 
    // 입력 개체를 초기화합니다.
    bool result = m_Input->Initialize(hinstance, hwnd, screenWidth, screenHeight);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize the input object.", L"Error", MB_OK);
        return false;
    }
 
    // Direct3D 개체를 생성합니다.
    m_Direct3D = new D3DClass;
    if(!m_Direct3D)
    {
        return false;
    }
 
    // Direct3D 개체를 초기화합니다.
    result = m_Direct3D->Initialize(screenWidth, screenHeight, VSYNC_ENABLED, hwnd, FULL_SCREEN, SCREEN_DEPTH, SCREEN_NEAR);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize DirectX 11.", L"Error", MB_OK);
        return false;
    }
 
    // 카메라 객체를 생성합니다.
    m_Camera = new CameraClass;
    if(!m_Camera)
    {
        return false;
    }
 
    // 2D 사용자 인터페이스 렌더링을 위해 카메라로 기본 뷰 행렬을 초기화합니다.
    XMMATRIX baseViewMatrix;
    m_Camera->SetPosition(XMFLOAT3(0.0f, 0.0f, -1.0f));
    m_Camera->Render();
    m_Camera->GetViewMatrix(baseViewMatrix);
 
    // 카메라의 초기 위치를 설정합니다.
    XMFLOAT3 camera = XMFLOAT3(50.0f, 2.0f, -7.0f);
    m_Camera->SetPosition(camera);
 
    // 지형 객체를 생성합니다.
    m_Terrain = new TerrainClass;
    if(!m_Terrain)
    {
        return false;
    }
 
    // 지형 객체를 초기화 합니다.
    result = m_Terrain->Initialize(m_Direct3D->GetDevice(), 100100);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize the terrain object.", L"Error", MB_OK);
        return false;
    }
 
    // 색상 쉐이더 객체를 생성합니다.
    m_ColorShader = new ColorShaderClass;
    if(!m_ColorShader)
    {
        return false;
    }
 
    // 색상 쉐이더 객체를 초기화합니다.
    result = m_ColorShader->Initialize(m_Direct3D->GetDevice(), hwnd);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize the color shader object.", L"Error", MB_OK);
        return false;
    }
 
    // 타이머 객체를 생성합니다.
    m_Timer = new TimerClass;
    if(!m_Timer)
    {
        return false;
    }
 
    // 타이머 객체를 초기화 합니다.
    result = m_Timer->Initialize();
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize the timer object.", L"Error", MB_OK);
        return false;
    }
 
    // 위치 개체를 생성합니다.
    m_Position = new PositionClass;
    if(!m_Position)
    {
        return false;
    }
 
    // 뷰어의 초기 위치를 초기 카메라 위치와 동일하게 설정합니다.
    m_Position->SetPosition(camera);
 
    // fps 객체를 생성합니다.
    m_Fps = new FpsClass;
    if(!m_Fps)
    {
        return false;
    }
 
    // fps 객체를 초기화합니다.
    m_Fps->Initialize();
 
    // cpu 객체를 생성합니다.
    m_Cpu = new CpuClass;
    if(!m_Cpu)
    {
        return false;
    }
 
    // cpu 객체를 초기화 합니다.
    m_Cpu->Initialize();
 
    // 폰트 셰이더 객체를 생성합니다.
    m_FontShader = new FontShaderClass;
    if(!m_FontShader)
    {
        return false;
    }
 
    // 폰트 셰이더 객체를 초기화합니다.
    result = m_FontShader->Initialize(m_Direct3D->GetDevice(), hwnd);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize the font shader object.", L"Error", MB_OK);
        return false;
    }
 
    // 텍스트 객체를 생성합니다.
    m_Text = new TextClass;
    if(!m_Text)
    {
        return false;
    }
 
    // 텍스트 객체를 초기화합니다.
    result = m_Text->Initialize(m_Direct3D->GetDevice(), m_Direct3D->GetDeviceContext(), hwnd, screenWidth, screenHeight,
 baseViewMatrix);
    if(!result)
    {
        MessageBox(hwnd, L"Could not initialize the text object.", L"Error", MB_OK);
        return false;
    }
 
    // 비디오 카드 정보를 가져옵니다.
    char videoCard[128= { 0, };
    int videoMemory = 0;
    m_Direct3D->GetVideoCardInfo(videoCard, videoMemory);
 
    // 텍스트 객체에 비디오 카드 정보를 설정합니다.
    result = m_Text->SetVideoCardInfo(videoCard, videoMemory, m_Direct3D->GetDeviceContext());
    if(!result)
    {
        MessageBox(hwnd, L"Could not set video card info in the text object.", L"Error", MB_OK);
        return false;
    }
 
    return true;
}
 
 
void ApplicationClass::Shutdown()
{
    // 텍스트 객체를 해제합니다.
    if(m_Text)
    {
        m_Text->Shutdown();
        delete m_Text;
        m_Text = 0;
    }
 
    // 폰트 쉐이더 객체를 해제합니다..
    if(m_FontShader)
    {
        m_FontShader->Shutdown();
        delete m_FontShader;
        m_FontShader = 0;
    }
 
    // cpu 객체를 해제합니다.
    if(m_Cpu)
    {
        m_Cpu->Shutdown();
        delete m_Cpu;
        m_Cpu = 0;
    }
 
    // fps 객체를 해제합니다.
    if(m_Fps)
    {
        delete m_Fps;
        m_Fps = 0;
    }
 
    // 위치 객체를 해제합니다.
    if(m_Position)
    {
        delete m_Position;
        m_Position = 0;
    }
 
    // 타이머 객체를 해제합니다.
    if(m_Timer)
    {
        delete m_Timer;
        m_Timer = 0;
    }
 
    // 색상 셰이더 객체를 해제합니다.
    if(m_ColorShader)
    {
        m_ColorShader->Shutdown();
        delete m_ColorShader;
        m_ColorShader = 0;
    }
 
    // 지형 객체를 해제합니다.
    if(m_Terrain)
    {
        m_Terrain->Shutdown();
        delete m_Terrain;
        m_Terrain = 0;
    }
 
    // 카메라 객체를 해제합니다.
    if(m_Camera)
    {
        delete m_Camera;
        m_Camera = 0;
    }
 
    // D3D 객체를 해제합니다.
    if (m_Direct3D)
    {
        m_Direct3D->Shutdown();
        delete m_Direct3D;
        m_Direct3D = 0;
    }
 
    // 입력 객체를 해제합니다.
    if(m_Input)
    {
        m_Input->Shutdown();
        delete m_Input;
        m_Input = 0;
    }
}
 
 
bool ApplicationClass::Frame()
{
    // 사용자 입력을 읽습니다.
    bool result = m_Input->Frame();
    if(!result)
    {
        return false;
    }
    
    // 사용자가 ESC를 눌렀을 때 응용 프로그램을 종료 할 것인지 확인합니다.
    if(m_Input->IsEscapePressed() == true)
    {
        return false;
    }
 
    // 시스템 통계를 업데이트 합니다.
    m_Timer->Frame();
    m_Fps->Frame();
    m_Cpu->Frame();
 
    // 텍스트 개체에서 FPS 값을 업데이트 합니다.
    result = m_Text->SetFps(m_Fps->GetFps(), m_Direct3D->GetDeviceContext());
    if(!result)
    {
        return false;
    }
    
    // 텍스트 개체의 CPU 사용값을 업데이트 합니다.
    result = m_Text->SetCpu(m_Cpu->GetCpuPercentage(), m_Direct3D->GetDeviceContext());
    if(!result)
    {
        return false;
    }
 
    // 프레임 입력 처리를 수행합니다.
    result = HandleInput(m_Timer->GetTime());
    if(!result)
    {
        return false;
    }
 
    // 그래픽을 렌더링 합니다.
    result = RenderGraphics();
    if(!result)
    {
        return false;
    }
 
    return result;
}
 
 
bool ApplicationClass::HandleInput(float frameTime)
{
    XMFLOAT3 pos = XMFLOAT3(0.0f, 0.0f, 0.0f);
    XMFLOAT3 rot = XMFLOAT3(0.0f, 0.0f, 0.0f);
 
 
    // 갱신된 위치를 계산하기 위한 프레임 시간을 설정합니다.
    m_Position->SetFrameTime(frameTime);
 
    // 입력을 처리합니다.
    m_Position->TurnLeft(m_Input->IsLeftPressed());
    m_Position->TurnRight(m_Input->IsRightPressed());
    m_Position->MoveForward(m_Input->IsUpPressed());
    m_Position->MoveBackward(m_Input->IsDownPressed());
    m_Position->MoveUpward(m_Input->IsAPressed());
    m_Position->MoveDownward(m_Input->IsZPressed());
    m_Position->LookUpward(m_Input->IsPgUpPressed());
    m_Position->LookDownward(m_Input->IsPgDownPressed());
    
    // 시점 위치 / 회전을 가져옵니다.
    m_Position->GetPosition(pos);
    m_Position->GetRotation(rot);
 
    // 카메라의 위치를 ​​설정합니다.
    m_Camera->SetPosition(pos);
    m_Camera->SetRotation(rot);
 
    // 텍스트 개체의 위치 값을 업데이트 합니다.
    if(!m_Text->SetCameraPosition(pos, m_Direct3D->GetDeviceContext()))
    {
        return false;
    }
 
    // 텍스트 객체의 회전 값을 업데이트 합니다.
    if(!m_Text->SetCameraRotation(rot, m_Direct3D->GetDeviceContext()))
    {
        return false;
    }
 
    return true;
}
 
 
bool ApplicationClass::RenderGraphics()
{
    XMMATRIX worldMatrix, viewMatrix, projectionMatrix, orthoMatrix;
 
    // 장면을 지웁니다.
    m_Direct3D->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);
 
    // 카메라의 위치에 따라 뷰 행렬을 생성합니다.
    m_Camera->Render();
 
    // 카메라 및 Direct3D 객체에서 월드, 뷰, 투영 및 ortho 행렬을 가져옵니다.
    m_Direct3D->GetWorldMatrix(worldMatrix);
    m_Camera->GetViewMatrix(viewMatrix);
    m_Direct3D->GetProjectionMatrix(projectionMatrix);
    m_Direct3D->GetOrthoMatrix(orthoMatrix);
 
    // 지형 버퍼를 렌더링 합니다.
    m_Terrain->Render(m_Direct3D->GetDeviceContext());
 
    // 색상 쉐이더를 사용하여 모델을 렌더링 합니다.
    if(!m_ColorShader->Render(m_Direct3D->GetDeviceContext(), m_Terrain->GetIndexCount(), worldMatrix, viewMatrix,
 projectionMatrix))
    {
        return false;
    }
 
    // 모든 2D 렌더링을 시작하려면 Z 버퍼를 끕니다.
    m_Direct3D->TurnZBufferOff();
        
    // 텍스트를 렌더링하기 전에 알파 블렌딩을 켭니다.
    m_Direct3D->TurnOnAlphaBlending();
 
    // 텍스트 사용자 인터페이스 요소를 렌더링 합니다.
    if(!m_Text->Render(m_Direct3D->GetDeviceContext(), m_FontShader, worldMatrix, orthoMatrix))
    {
        return false;
    }
 
    // 텍스트를 렌더링 한 후 알파 블렌딩을 끕니다.
    m_Direct3D->TurnOffAlphaBlending();
 
    // 모든 2D 렌더링이 완료되었으므로 Z 버퍼를 다시 켭니다.
    m_Direct3D->TurnZBufferOn();
 
    // 렌더링 된 장면을 화면에 표시합니다.
    m_Direct3D->EndScene();
 
    return true;
}
cs



출력 화면




마치면서


이제 100x100 사이즈의 지형 그리드를 움직이는 매우 반응이 빠른 카메라를 갖게되었습니다. 또한 디버깅을 위해 사용자 인터페이스에 위치 및 회전이 표시됩니다.



연습문제


1. 코드를 다시 컴파일하고 지형 그리드를 따라 이동하십시오. 화살표 키와 A 및 Z 키를 사용하여 위아래로 이동하십시오. PgUp 및 PgDn을 사용하여 뷰를 위아래로 회전합니다.


2. 입력 키를 원하는 설정으로 변경하십시오.


3. strafing 기능을 포지션 클래스에 추가하십시오.



소스코드


소스코드 : Dx11Terrain_01.zip