这是完整的代码:
#include <Windows.h>
#include <stdio.h>
#include <Xinput.h>
#include <DirectXMath.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXTex.h>
#include <SpriteFont.h>
#include "DDSTextureLoader.h"
#include "WICTextureLoader.h"
using namespace DirectX;
#define CAMERA_ROTATION_SPEED (110.0f)
#define CAMERA_TARGET_DISTANCE (3.0f)
#define CAMERA_TARGET_VIEW_Y_START (-15.0f)
#define CAMERA_TARGET_VIEW_XZ_START (0.0f)
#define CAMERA_TARGET_START (XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f))
#define CAMERA_UP_START (XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f))
#define CAMERA_POS_START (XMVectorSet(0.0f, 0.0f, 3.0f, 0.0f))
#define PLAYER_MOVEMENT_SPEED (5.0f)
#define SAFE_DELETE(p) if (p) { delete (p); (p) = NULL; }
#define SAFE_RELEASE(p) if (p) { (p)->Release(); (p) = NULL; }
#ifdef _DEBUG
#define ErrorBoxW(msg) MessageBox(NULL, (msg), L"Error", MB_OK | MB_ICONERROR)
#else // _DEBUG
#define ErrorBox(msg)
#endif // _DEBUG
#define NORMALIZE_ANGLE(ang) { while ((ang) > 360.0f) { (ang) -= 360.0f; } while ((ang) < -360.0f) { (ang) += 360.0f; } }
#define LIMIT_ANGLE(ang, val) { if ((ang) > (val)) { (ang) = (val); } if ((ang) < -(val)) { (ang) = -(val); } }
#define CHECK_CHANGE_F(curr, prev, flag) { (flag) = (curr) != (prev); }
typedef struct _Camera
{
XMFLOAT3 _target;
XMFLOAT3 _pos;
XMFLOAT3 _up;
float _viewRotXZ;
float _viewRotY;
XMFLOAT4X4 _cameraProjection;
} Camera;
typedef struct _FPS
{
_FPS(void)
: _elapsedTime(0.0f), _frames(0), _fps(0.0f) {}
void Calc(float timeDelta)
{
_elapsedTime += timeDelta;
_frames++;
if (_elapsedTime >= 1.0f)
{
_fps = (float)_frames / _elapsedTime;
_elapsedTime = 0.0f;
_frames = 0;
#ifdef _DEBUG
wchar_t buffer[32];
swprintf_s(buffer, 32, L"FPS: %.2f\n", _fps);
OutputDebugString(buffer);
#endif // _DEBUG
}
}
float _fps;
float _elapsedTime;
int _frames;
} FPS;
typedef struct _Player
{
_Player(void)
: _moveX(0.0f), _moveY(0.0f), _moveZ(0.0f) {}
float _moveX;
float _moveY;
float _moveZ;
} Player;
using namespace DirectX;
typedef struct _SimpleVertex
{
_SimpleVertex() {}
_SimpleVertex(float x, float y, float z, float cr, float cg, float cb, float ca, float cr2, float cg2, float cb2, float ca2, float u, float v)
: _pos(x, y, z), _color0(cr, cg, cb, ca), _color1(cr2, cg2, cb2, ca2), _tex(u, v) {}
XMFLOAT3 _pos;
XMFLOAT4 _color0;
XMFLOAT4 _color1;
XMFLOAT2 _tex;
} SimpleVertex;
// sizeof(ConstantBufferPerObject) = 80; multiple of 16
typedef struct _ConstantBufferPerObject
{
XMFLOAT4X4 _wvp; // sizeof(XMFLOAT4X4) = 64
float _colorAdjust; // sizeof(float) = 4; 68
int _mode; // sizeof(int) = 4; 72
int _pad[2]; // 2 * sizeof(int) = 8; 80
} ConstantBufferPerObject;
LPWSTR const g_windowClassName = L"dx11demo";
LPWSTR const g_windowTitle = L"DirectX11Demo";
HWND g_hwnd = NULL;
HINSTANCE g_hinstance = NULL;
const int g_width = 800;
const int g_height = 600;
IDXGISwapChain *g_pSwapChain = NULL;
ID3D11Device *g_pDevice = NULL;
ID3D11DeviceContext *g_pDeviceContext = NULL;
ID3D11RenderTargetView *g_pRenderTargetView = NULL;
ID3D11Buffer *g_pTriangleVertexBuffer = NULL;
ID3D11Buffer *g_pSquareIndexBuffer = NULL;
ID3D11VertexShader *g_pVertexShader = NULL;
ID3D11PixelShader *g_pPixelShader = NULL;
ID3DBlob *g_pVertexShaderBuffer = NULL;
ID3DBlob *g_pPixelShaderBuffer = NULL;
ID3D11DepthStencilView *g_pDepthStencilView = NULL;
ID3D11Buffer *g_pConstantBufferPerObject = NULL;
ID3D11Texture2D *g_pDepthStencilBuffer = NULL;
ID3D11InputLayout *g_pVertexLayout = NULL;
ID3D11ShaderResourceView *g_pCageTexture = NULL;
ID3D11ShaderResourceView *g_pBrickTexture = NULL;
ID3D11SamplerState *g_pCubeTextureSamplerState = NULL;
bool g_solid = true;
float g_rotBox2 = 0.0f;
ID3D11RasterizerState *g_pNoCullSolid = NULL;
ID3D11RasterizerState *g_pNoCullWireframe = NULL;
ID3D11RasterizerState *g_pCWCullSolid = NULL;
ID3D11RasterizerState *g_pCCWCullSolid = NULL;
ID3D11BlendState *g_pTransparency = NULL;
SpriteBatch *g_pSpriteBatch = NULL;
SpriteFont *g_pSpriteFont = NULL;
D3D11_INPUT_ELEMENT_DESC g_layout_a[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR_ZERO", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR_ONE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 44, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT g_numElements = ARRAYSIZE(g_layout_a);
bool g_isMoving = true;
ConstantBufferPerObject g_constantBufferPerObject;
bool g_enableDraw = true;
Player g_player;
Camera g_camera;
FPS g_fps;
void CleanUp(void);
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
bool InitD3D11(void);
bool InitScene(void);
void DrawScene(void);
void UpdateScene(float);
void UpdateScene(float timeDelta)
{
g_rotBox2 += 20.0f * timeDelta;
NORMALIZE_ANGLE(g_rotBox2);
}
void DrawScene(void)
{
HRESULT hr;
float bgColor_a[4] = { 0.0f, 0.4f, 0.8f, 0.0f };
g_pDeviceContext->ClearRenderTargetView(g_pRenderTargetView, bgColor_a);
g_pDeviceContext->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
XMMATRIX cameraProj = XMLoadFloat4x4(&g_camera._cameraProjection);
XMVECTOR pos = XMLoadFloat3(&g_camera._pos);
XMVECTOR target = XMLoadFloat3(&g_camera._target);
XMVECTOR up = XMLoadFloat3(&g_camera._up);
XMMATRIX cameraView = XMMatrixLookAtLH(pos, target, up);
XMMATRIX worldBox2 = XMMatrixIdentity() * (XMMatrixTranslation(2.0f, 0.0f, 0.0f) * XMMatrixRotationY(XMConvertToRadians(g_rotBox2)));
XMMATRIX wvp = worldBox2 * cameraView * cameraProj;
XMMATRIX transposeWvp = XMMatrixTranspose(wvp);
XMStoreFloat4x4(&g_constantBufferPerObject._wvp, transposeWvp);
g_pDeviceContext->UpdateSubresource(g_pConstantBufferPerObject, 0, NULL, &g_constantBufferPerObject, 0, 0);
g_pDeviceContext->VSSetConstantBuffers(0, 1, &g_pConstantBufferPerObject);
g_pDeviceContext->PSSetShaderResources(0, 1, &g_pCageTexture);
g_pDeviceContext->PSSetSamplers(0, 1, &g_pCubeTextureSamplerState);
// box
g_pDeviceContext->DrawIndexed(36, 0, 0);
wchar_t buffer[32];
swprintf_s(buffer, 32, L"%.2f", g_fps._fps);
//g_pSpriteBatch->Begin();
//g_pSpriteFont->DrawString(g_pSpriteBatch, buffer, XMFLOAT2(30, 30));
//g_pSpriteBatch->End();
// Present the backbuffer to the screen
hr = g_pSwapChain->Present(0, 0);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot present without error.");
}
}
bool InitScene(void)
{
HRESULT hr;
ID3DBlob *pErrorBlob = NULL;
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
#ifdef _DEBUG
flags |= D3DCOMPILE_DEBUG;
#endif // _DEBUG
const D3D_SHADER_MACRO defines_a[] =
{
{ NULL, NULL }
};
// Compile Shaders from shader file
// https://msdn.microsoft.com/de-de/library/windows/desktop/hh968107(v=vs.85).aspx
hr = D3DCompileFromFile(L"VertexShader.hlsl", defines_a, D3D_COMPILE_STANDARD_FILE_INCLUDE, "VS", "vs_5_0", flags, 0, &g_pVertexShaderBuffer, &pErrorBlob);
if (FAILED(hr))
{
SAFE_RELEASE(pErrorBlob);
ErrorBoxW(L"Cannot compile vertex shader VS vs_5_0.");
return false;
}
hr = D3DCompileFromFile(L"PixelShader.hlsl", defines_a, D3D_COMPILE_STANDARD_FILE_INCLUDE, "PS", "ps_5_0", flags, 0, &g_pPixelShaderBuffer, &pErrorBlob);
if (FAILED(hr))
{
SAFE_RELEASE(pErrorBlob);
ErrorBoxW(L"Cannot compile pixel shader PS ps_5_0.");
return false;
}
// Create the Shader Objects
hr = g_pDevice->CreateVertexShader(g_pVertexShaderBuffer->GetBufferPointer(), g_pVertexShaderBuffer->GetBufferSize(), NULL, &g_pVertexShader);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create vertex shader.");
return false;
}
hr = g_pDevice->CreatePixelShader(g_pPixelShaderBuffer->GetBufferPointer(), g_pPixelShaderBuffer->GetBufferSize(), NULL, &g_pPixelShader);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create pixel shader.");
return false;
}
// Set Vertex and Pixel Shaders
g_pDeviceContext->VSSetShader(g_pVertexShader, 0, 0);
g_pDeviceContext->PSSetShader(g_pPixelShader, 0, 0);
// Create the vertex buffer (vertices must be in clock-wise order)
SimpleVertex vertices_a[] =
{
// Front Face
/* 11 */ SimpleVertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 3.0f),
/* 12 */ SimpleVertex(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
/* 13 */ SimpleVertex(1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f),
/* 14 */ SimpleVertex(1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 3.0f),
// Back Face
/* 15 */ SimpleVertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 3.0f),
/* 16 */ SimpleVertex(1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 3.0f),
/* 17 */ SimpleVertex(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
/* 18 */ SimpleVertex(-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f),
// Top Face
/* 19 */ SimpleVertex(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 3.0f),
/* 20 */ SimpleVertex(-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
/* 21 */ SimpleVertex(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f),
/* 22 */ SimpleVertex(1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 3.0f),
// Bottom Face
/* 23 */ SimpleVertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 3.0f),
/* 24 */ SimpleVertex(1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 3.0f),
/* 25 */ SimpleVertex(1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
/* 26 */ SimpleVertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f),
// Left Face
/* 27 */ SimpleVertex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 3.0f),
/* 28 */ SimpleVertex(-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
/* 29 */ SimpleVertex(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f),
/* 30 */ SimpleVertex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 3.0f),
// Right Face
/* 31 */ SimpleVertex(1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 3.0f),
/* 32 */ SimpleVertex(1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f),
/* 33 */ SimpleVertex(1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 0.0f),
/* 34 */ SimpleVertex(1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 3.0f, 3.0f),
};
D3D11_BUFFER_DESC vertexBufferDesc;
ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(SimpleVertex) * 24;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vertexBufferData;
ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
vertexBufferData.pSysMem = vertices_a;
hr = g_pDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &g_pTriangleVertexBuffer);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create triangle buffer.");
return false;
}
// Set the vertex buffer
UINT stride = sizeof(SimpleVertex);
UINT offset = 0;
g_pDeviceContext->IASetVertexBuffers(0, 1, &g_pTriangleVertexBuffer, &stride, &offset);
DWORD indices_a[] =
{
// Front Face
/* 5 */ 0, 1, 2,
/* 6 */ 0, 2, 3,
// Back Face
/* 7 */ 4, 5, 6,
/* 8 */ 4, 6, 7,
// Top Face
/* 9 */ 8, 9, 10,
/* 10 */ 8, 10, 11,
// Bottom Face
/* 11 */ 12, 13, 14,
/* 12 */ 12, 14, 15,
// Left Face
/* 13 */ 16, 17, 18,
/* 14 */ 16, 18, 19,
// Right Face
/* 15 */ 20, 21, 22,
/* 16 */ 20, 22, 23,
};
D3D11_BUFFER_DESC indexBufferDesc;
ZeroMemory(&indexBufferDesc, sizeof(indexBufferDesc));
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(DWORD) * 12 * 3;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
ZeroMemory(&iinitData, sizeof(D3D11_SUBRESOURCE_DATA));
iinitData.pSysMem = indices_a;
hr = g_pDevice->CreateBuffer(&indexBufferDesc, &iinitData, &g_pSquareIndexBuffer);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create index buffer.");
return false;
}
g_pDeviceContext->IASetIndexBuffer(g_pSquareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
// Create the Input Layout
hr = g_pDevice->CreateInputLayout(g_layout_a, g_numElements, g_pVertexShaderBuffer->GetBufferPointer(), g_pVertexShaderBuffer->GetBufferSize(), &g_pVertexLayout);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create input layout.");
return false;
}
// Set the Input Layout
g_pDeviceContext->IASetInputLayout(g_pVertexLayout);
// Set Primitive Topology
g_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 3 vertices per triangle
//g_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); // 1 vertex per point
//g_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); // 2 vertices per line
// Create the Viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = g_width; // divide by 4 to only use 1/4 of client area (width)
viewport.Height = g_height; // divide by 4 to only use 1/4 of client area (height)
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
//Set the Viewport
g_pDeviceContext->RSSetViewports(1, &viewport);
// Create the buffer to send to the cbuffer in effect file
D3D11_BUFFER_DESC constantBufferDesc;
ZeroMemory(&constantBufferDesc, sizeof(D3D11_BUFFER_DESC));
constantBufferDesc.Usage = D3D11_USAGE_DEFAULT;
constantBufferDesc.ByteWidth = sizeof(ConstantBufferPerObject);
constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDesc.CPUAccessFlags = 0;
constantBufferDesc.MiscFlags = 0;
hr = g_pDevice->CreateBuffer(&constantBufferDesc, NULL, &g_pConstantBufferPerObject);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create constant buffer.");
return false;
}
D3D11_RASTERIZER_DESC rasterizerDesc;
ZeroMemory(&rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.CullMode = D3D11_CULL_NONE;
rasterizerDesc.FrontCounterClockwise = true;
hr = g_pDevice->CreateRasterizerState(&rasterizerDesc, &g_pNoCullSolid);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create rasterizer state (no culling, solid).");
return false;
}
rasterizerDesc.FillMode = D3D11_FILL_WIREFRAME;
hr = g_pDevice->CreateRasterizerState(&rasterizerDesc, &g_pNoCullWireframe);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create rasterizer state (no culling, wireframe).");
return false;
}
g_pDeviceContext->RSSetState(g_pNoCullSolid);
hr = CreateWICTextureFromFile(g_pDevice, L"tcage.png", NULL, &g_pCageTexture);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create shader resource view (cage).");
return false;
}
D3D11_SAMPLER_DESC sampDesc;
ZeroMemory(&sampDesc, sizeof(sampDesc));
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
sampDesc.MinLOD = 0;
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
hr = g_pDevice->CreateSamplerState(&sampDesc, &g_pCubeTextureSamplerState);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create sampler state.");
return false;
}
D3D11_BLEND_DESC blendDesc; // Define the Blending Equation
ZeroMemory(&blendDesc, sizeof(blendDesc));
D3D11_RENDER_TARGET_BLEND_DESC rtbd;
ZeroMemory(&rtbd, sizeof(rtbd));
rtbd.BlendEnable = true;
rtbd.SrcBlend = D3D11_BLEND_SRC_COLOR;
rtbd.DestBlend = D3D11_BLEND_BLEND_FACTOR;
rtbd.BlendOp = D3D11_BLEND_OP_ADD;
rtbd.SrcBlendAlpha = D3D11_BLEND_ONE;
rtbd.DestBlendAlpha = D3D11_BLEND_ZERO;
rtbd.BlendOpAlpha = D3D11_BLEND_OP_ADD;
rtbd.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
blendDesc.AlphaToCoverageEnable = false;
blendDesc.RenderTarget[0] = rtbd;
hr = g_pDevice->CreateBlendState(&blendDesc, &g_pTransparency);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create blend state.");
return false;
}
// Create the Counter Clockwise and Clockwise Culling States
D3D11_RASTERIZER_DESC cmdesc;
ZeroMemory(&cmdesc, sizeof(D3D11_RASTERIZER_DESC));
cmdesc.FillMode = D3D11_FILL_SOLID;
cmdesc.CullMode = D3D11_CULL_BACK;
cmdesc.FrontCounterClockwise = true;
hr = g_pDevice->CreateRasterizerState(&cmdesc, &g_pCCWCullSolid);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create ccw cull mode.");
return false;
}
cmdesc.FrontCounterClockwise = false;
hr = g_pDevice->CreateRasterizerState(&cmdesc, &g_pCWCullSolid);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create cw cull mode.");
return false;
}
g_pSpriteBatch = new SpriteBatch(g_pDeviceContext);
if (!g_pSpriteBatch)
{
ErrorBoxW(L"Cannot create sprite batch.");
return false;
}
g_pSpriteFont = new SpriteFont(g_pDevice, L"arial.font");
if (!g_pSpriteFont)
{
ErrorBoxW(L"Cannot create sprite font.");
return false;
}
XMStoreFloat3(&g_camera._target, CAMERA_TARGET_START);
XMStoreFloat3(&g_camera._pos, CAMERA_POS_START);
XMStoreFloat3(&g_camera._up, CAMERA_UP_START);
g_camera._viewRotXZ = CAMERA_TARGET_VIEW_XZ_START;
g_camera._viewRotY = CAMERA_TARGET_VIEW_Y_START;
// Set the Projection matrix
XMStoreFloat4x4(&g_camera._cameraProjection, XMMatrixPerspectiveFovLH(XMConvertToRadians(45.0f), (float)g_width / (float)g_height, 0.1f, 1000.0f));
return true;
}
bool InitD3D11(void)
{
HRESULT hr;
DXGI_MODE_DESC bufferDesc; // Describe our Buffer
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = g_width;
bufferDesc.Height = g_height;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
DXGI_SWAP_CHAIN_DESC swapChainDesc; // Describe our SwapChain
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc = bufferDesc;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = g_hwnd;
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
//Create our SwapChain
hr = D3D11CreateDeviceAndSwapChain(
NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
D3D11_CREATE_DEVICE_DEBUG,
NULL,
NULL,
D3D11_SDK_VERSION,
&swapChainDesc,
&g_pSwapChain,
&g_pDevice,
NULL,
&g_pDeviceContext);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create swap chain, device and device context.");
return false;
}
ID3D11Texture2D* backBuffer; // Create our BackBuffer
hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&backBuffer);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create back buffer.");
return false;
}
// Create our Render Target
hr = g_pDevice->CreateRenderTargetView(backBuffer, NULL, &g_pRenderTargetView);
SAFE_RELEASE(backBuffer); // release back buffer in any case
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create render target view.");
return false;
}
D3D11_TEXTURE2D_DESC depthStencilDesc; // Describe our Depth/Stencil Buffer
ZeroMemory(&depthStencilDesc, sizeof(D3D11_TEXTURE2D_DESC));
depthStencilDesc.Width = g_width;
depthStencilDesc.Height = g_height;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
// Create the Depth/Stencil View
hr = g_pDevice->CreateTexture2D(&depthStencilDesc, NULL, &g_pDepthStencilBuffer);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create depth stencil buffer.");
return false;
}
hr = g_pDevice->CreateDepthStencilView(g_pDepthStencilBuffer, NULL, &g_pDepthStencilView);
if (FAILED(hr))
{
ErrorBoxW(L"Cannot create depth stencil view.");
return false;
}
// Set our Render Target
g_pDeviceContext->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
return true;
}
void CleanUp(void)
{
SAFE_RELEASE(g_pDevice);
SAFE_RELEASE(g_pDeviceContext);
SAFE_RELEASE(g_pPixelShader);
SAFE_RELEASE(g_pPixelShaderBuffer);
SAFE_RELEASE(g_pRenderTargetView);
SAFE_RELEASE(g_pSwapChain);
SAFE_RELEASE(g_pTriangleVertexBuffer);
SAFE_RELEASE(g_pVertexLayout);
SAFE_RELEASE(g_pVertexShader);
SAFE_RELEASE(g_pVertexShaderBuffer);
SAFE_RELEASE(g_pSquareIndexBuffer);
SAFE_RELEASE(g_pDepthStencilBuffer);
SAFE_RELEASE(g_pDepthStencilView);
SAFE_RELEASE(g_pConstantBufferPerObject);
SAFE_RELEASE(g_pNoCullSolid);
SAFE_RELEASE(g_pNoCullWireframe);
SAFE_RELEASE(g_pCageTexture);
SAFE_RELEASE(g_pBrickTexture);
SAFE_RELEASE(g_pCubeTextureSamplerState);
SAFE_RELEASE(g_pTransparency);
SAFE_RELEASE(g_pCWCullSolid);
SAFE_RELEASE(g_pCCWCullSolid);
SAFE_DELETE(g_pSpriteBatch);
SAFE_DELETE(g_pSpriteFont);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
// Check message
switch (msg)
{
case WM_KEYDOWN:
// if escape key was pressed, display popup box
if (wParam == VK_ESCAPE)
{
if (MessageBox(0, L"Are you sure you want to exit?", L"Really?", MB_YESNO | MB_ICONQUESTION) == IDYES)
{
// Release the windows allocated memory
DestroyWindow(hwnd);
}
}
return 0;
case WM_DESTROY:
// if x button in top right was pressed
PostQuitMessage(0);
return 0;
}
// return the message for windows to handle it
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(hPrevInstance);
g_hinstance = hInstance;
WNDCLASSEX wc; // Create a new extended windows class
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX); // Size of our windows class
wc.style = CS_HREDRAW | CS_VREDRAW; // class styles
wc.lpfnWndProc = WndProc; // Default windows procedure function
wc.cbClsExtra = NULL; // Extra bytes after our wc structure
wc.cbWndExtra = NULL; // Extra bytes after our windows instance
wc.hInstance = hInstance; // Instance to current application
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Title bar Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Default mouse Icon
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2); // Window bg color
wc.lpszMenuName = NULL; // Name of the menu attached to our window
wc.lpszClassName = g_windowClassName; // Name of our windows class
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // Icon in your taskbar
if (!RegisterClassEx(&wc)) // Register our windows class
{
ErrorBoxW(L"Error registering class");
return 1;
}
// Create our Extended Window
g_hwnd = CreateWindowEx(
NULL, // Extended style
g_windowClassName, // Name of our windows class
g_windowTitle, // Name in the title bar of our window
WS_OVERLAPPEDWINDOW ^ (WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX), // style of our window
CW_USEDEFAULT, CW_USEDEFAULT, // Top left corner of window
g_width, // Width of our window
g_height, // Height of our window
NULL, // Handle to parent window
NULL, // Handle to a Menu
hInstance, // Specifies instance of current program
NULL // used for an MDI client window
);
// Make sure our window has been created
if (!g_hwnd)
{
ErrorBoxW(L"Error creating window");
return 1;
}
ShowWindow(g_hwnd, nShowCmd); // Shows our window
UpdateWindow(g_hwnd); // Its good to update our window
bool result;
result = InitD3D11();
if (result)
{
result = InitScene();
if (result)
{
MSG msg; // Create a new message structure
ZeroMemory(&msg, sizeof(MSG));
DWORD timeLast = timeGetTime();
DWORD timeCurr = timeLast;
float timeDelta = 0.0f;
bool run = true;
//float elapsed = 0.0f;
//float frameLimit = 1.0f / 60.0f;
while (run)
{
// if there was a windows message
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// if the message was WM_QUIT
if (msg.message == WM_QUIT)
{
run = false; // Exit the message loop
}
TranslateMessage(&msg); // Translate the message
DispatchMessage(&msg); // Send the message to default windows procedure
}
timeCurr = timeGetTime();
timeDelta = (float)(timeCurr - timeLast) / 1000.0f;
//elapsed += timeDelta;
//if (elapsed >= frameLimit)
//{
g_fps.Calc(timeDelta);
UpdateScene(timeDelta);
DrawScene();
//elapsed = 0.0f;
//}
timeLast = timeCurr;
}
}
}
CleanUp();
return 0; // return the message
}
没有 SpriteFont 的场景
使用 SpriteFont 的场景