【DX11地形篇】13-小地图

参考教程

Tutorial 12: Terrain Mini-Maps

学习记录

  这篇文章中我们介绍小地图的实现,我们将在右上角显示一个小地图并且在地图上实时显示我们摄像机的当前位置,本篇代码基于上一篇,新增 MiniMapClass ,并且使用了 BitmapClass

  小地图的核心内容只是简单的渲染一个二维的纹理贴图在显示区右上角,然后计算使用当前摄像机的 x , z 坐标来渲染代表摄像机的小点。其类声明如下:

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
////////////////////////////////////////////////////////////////////////////////
// Filename: minimapclass.h
////////////////////////////////////////////////////////////////////////////////
#ifndef _MINIMAPCLASS_H_
#define _MINIMAPCLASS_H_


///////////////////////
// MY CLASS INCLUDES //
///////////////////////
#include "bitmapclass.h"
#include "shadermanagerclass.h"

////////////////////////////////////////////////////////////////////////////////
// Class name: MiniMapClass
////////////////////////////////////////////////////////////////////////////////
class MiniMapClass
{
public:
MiniMapClass();
MiniMapClass(const MiniMapClass&);
~MiniMapClass();

bool Initialize(ID3D11Device*, ID3D11DeviceContext*, int, int, float, float);
void Shutdown();
bool Render(ID3D11DeviceContext*, ShaderManagerClass*, DirectX::XMMATRIX, DirectX::XMMATRIX, DirectX::XMMATRIX);

void PositionUpdate(float, float);

private:
int m_mapLocationX, m_mapLocationY, m_pointLocationX, m_pointLocationY;
float m_mapSizeX, m_mapSizeY, m_terrainWidth, m_terrainHeight;
BitmapClass *m_MiniMapBitmap, *m_PointBitmap;
};

#endif

  可以看到我们要渲染的其实就是两个 BitmapClass 的对象,具体渲染在 Render 方法里:

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
bool MiniMapClass::Render(ID3D11DeviceContext* deviceContext, ShaderManagerClass* ShaderManager, XMMATRIX worldMatrix, 
XMMATRIX viewMatrix, XMMATRIX orthoMatrix)
{
bool result;


// Put the mini-map bitmap vertex and index buffers on the graphics pipeline to prepare them for drawing.
result = m_MiniMapBitmap->Render(deviceContext, m_mapLocationX, m_mapLocationY);
if(!result)
{
return false;
}

// Render the mini-map bitmap using the texture shader.
result = ShaderManager->RenderTextureShader(deviceContext, m_MiniMapBitmap->GetIndexCount(), worldMatrix, viewMatrix,
orthoMatrix, m_MiniMapBitmap->GetTexture());
if(!result)
{
return false;
}

// Put the point bitmap vertex and index buffers on the graphics pipeline to prepare them for drawing.
result = m_PointBitmap->Render(deviceContext, m_pointLocationX, m_pointLocationY);
if(!result)
{
return false;
}

// Render the point bitmap using the texture shader.
result = ShaderManager->RenderTextureShader(deviceContext, m_PointBitmap->GetIndexCount(), worldMatrix, viewMatrix,
orthoMatrix, m_PointBitmap->GetTexture());
if(!result)
{
return false;
}

return true;
}

  在 PositionUpdate 方法里,我们根据实时的摄像机 x , z 坐标来计算我们的 point 在小地图上的位置:

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
void MiniMapClass::PositionUpdate(float positionX, float positionZ)
{
float percentX, percentY;


// Ensure the point does not leave the minimap borders even if the camera goes past the terrain borders.
if(positionX < 0)
{
positionX = 0;
}

if(positionZ < 0)
{
positionZ = 0;
}

if(positionX > m_terrainWidth)
{
positionX = m_terrainWidth;
}

if(positionZ > m_terrainHeight)
{
positionZ = m_terrainHeight;
}

// Calculate the position of the camera on the minimap in terms of percentage.
percentX = positionX / m_terrainWidth;
percentY = 1.0f - (positionZ / m_terrainHeight);

// Determine the pixel location of the point on the mini-map.
m_pointLocationX = (m_mapLocationX + 2) + (int)(percentX * m_mapSizeX);
m_pointLocationY = (m_mapLocationY + 2) + (int)(percentY * m_mapSizeY);

// Subtract one from the location to center the point on the mini-map according to the 3x3 point pixel image size.
m_pointLocationX = m_pointLocationX - 1;
m_pointLocationY = m_pointLocationY - 1;

return;
}

  最后,我们在 UserInterfaceClass 里新增 MiniMapClass 类的对象,并实现对其的渲染:

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
class UserInterfaceClass
{
public:
UserInterfaceClass();
UserInterfaceClass(const UserInterfaceClass&);
~UserInterfaceClass();

bool Initialize(D3DClass*, int, int);
void Shutdown();

bool Frame(ID3D11DeviceContext*, int, float, float, float, float, float, float);
bool Render(D3DClass*, ShaderManagerClass*, XMMATRIX, XMMATRIX, XMMATRIX);
bool UpdateRenderCounts(ID3D11DeviceContext*, int, int, int);

private:
bool UpdateFpsString(ID3D11DeviceContext*, int);
bool UpdatePositionStrings(ID3D11DeviceContext*, float, float, float, float, float, float);
private:
FontClass* m_Font1;
TextClass *m_FpsString, *m_VideoStrings, *m_PositionStrings , *m_RenderCountStrings;
MiniMapClass* m_MiniMap;

int m_previousFps;
int m_previousPosition[6];
};

bool UserInterfaceClass::Render(D3DClass* Direct3D, ShaderManagerClass* ShaderManager, XMMATRIX worldMatrix, XMMATRIX viewMatrix,
XMMATRIX orthoMatrix)
{
int i;
bool result;

// Turn off the Z buffer and enable alpha blending to begin 2D rendering.
Direct3D->TurnZBufferOff();
Direct3D->EnableAlphaBlending();

// Render the fps string.
m_FpsString->Render(Direct3D->GetDeviceContext(), ShaderManager, worldMatrix, viewMatrix, orthoMatrix, m_Font1->GetTexture());

// Render the video card strings.
m_VideoStrings[0].Render(Direct3D->GetDeviceContext(), ShaderManager, worldMatrix, viewMatrix, orthoMatrix, m_Font1->GetTexture());
m_VideoStrings[1].Render(Direct3D->GetDeviceContext(), ShaderManager, worldMatrix, viewMatrix, orthoMatrix, m_Font1->GetTexture());

// Render the position and rotation strings.
for(i=0; i<6; i++)
{
m_PositionStrings[i].Render(Direct3D->GetDeviceContext(), ShaderManager, worldMatrix, viewMatrix, orthoMatrix, m_Font1->GetTexture());
}

// Render the render count strings.
for(i=0; i<3; i++)
{
m_RenderCountStrings[i].Render(Direct3D->GetDeviceContext(), ShaderManager, worldMatrix, viewMatrix, orthoMatrix, m_Font1->GetTexture());
}

// Turn off alpha blending now that the text has been rendered.
Direct3D->DisableAlphaBlending();

// Render the mini-map.
result = m_MiniMap->Render(Direct3D->GetDeviceContext(), ShaderManager, worldMatrix, viewMatrix, orthoMatrix);
if(!result)
{
return false;
}

// Turn the Z buffer back on now that the 2D rendering has completed.
Direct3D->TurnZBufferOn();

return true;
}

  在 Frame 方法里我们调用 PositionUpdate 方法:

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
bool UserInterfaceClass::Frame(ID3D11DeviceContext* deviceContext, int fps, float posX, float posY, float posZ, 
float rotX, float rotY, float rotZ)
{
bool result;


// Update the fps string.
result = UpdateFpsString(deviceContext, fps);
if(!result)
{
return false;
}

// Update the position strings.
result = UpdatePositionStrings(deviceContext, posX, posY, posZ, rotX, rotY, rotZ);
if(!result)
{
return false;
}

// Update the mini-map position indicator.
m_MiniMap->PositionUpdate(posX, posZ);

return true;
}

  最终效果:

1

  源代码:DX11TerrainTutorial-MiniMaps

0%