【问题标题】:DirectX::SpriteFont/SpriteBatch prevents 3D scene from drawingDirectX::SpriteFont/SpriteBatch 阻止绘制 3D 场景
【发布时间】:2016-02-22 16:00:09
【问题描述】:

我在使用 DirectX::SpriteFont/DirectX::SpriteBatch 时遇到问题(来自 DirectXTK;与此处讨论的问题完全相同:Problems when drawing text using the SpriteFont class)。

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.");
    }
}

如果不调用SpriteBatch::Begin()SpriteFont::DrawStringSpriteBatch::End(),您将看到一个带纹理的立方体在空间(笼子)中旋转。通过调用所描述的函数,您将只能在左上角看到每秒帧数,但看不到旋转立方体。

我按照 github DirectXTK 上 Chuck Walbourn 的教程,结合使用 SpriteFont 绘制字符串和渲染原始 3D 对象(一个简单的三角形)的 2 个教程。在此示例中,我将看到测试字符串绘制在三角形上。但我不明白为什么我的示例中的旋转立方体在使用 DirectXTK 的SpriteFont 类绘制文本字符串时不可见,我什至找不到根本原因。

像素着色器文件(PixelShader.hlsl):

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR;
    float2 TexCoord : TEXCOORD;
};

Texture2D ObjTexture;
SamplerState ObjSamplerState;

float4 PS( VS_OUTPUT input ) : SV_TARGET
{
    float4 diffuse = ObjTexture.Sample(ObjSamplerState, input.TexCoord);
    clip(diffuse.a - 0.25);
    return diffuse;
}

顶点着色器文件(VertexShader.hlsl):

cbuffer constantBufferPerObject
{
    float4x4 WVP;
    float ColorAdjust;
    int Mode;
    int Pad[2];
};

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR;
    float2 TexCoord : TEXCOORD;
};

VS_OUTPUT VS( float4 pos : POSITION, float4 color : COLOR_ZERO, float4 color2 : COLOR_ONE, float2 texCoord : TEXCOORD )
{
    VS_OUTPUT output;
    float4 temp;
    output.Pos = mul(pos, WVP);  
    temp = color;
    output.Color.r = temp.r * color2.r * (1.0f - ColorAdjust);
    output.Color.g = temp.g * color2.g * (1.0f - ColorAdjust);
    output.Color.b = temp.b * color2.b * (1.0f - ColorAdjust);
    output.Color.a = color.a * color2.a;
    output.TexCoord = texCoord;
    return output;
}

重现问题:我正在使用 Visual Studio 2015 社区版。我将 DirectXTK (.lib) 和 DirectXTex (WICTextureLoader .cpp/.h, DDSTextureLoader .cpp/.h, .lib) 添加到我的项目中。立方体的图像是带有 alpha 的 .png。

注意:我创建了这个重复问题,以

避免 ...寻求帮助、澄清或回应其他答案。

关于另一个问题。

【问题讨论】:

  • 添加了 main.cpp 的源代码作为下面的答案。来源和问题包含超过 30000 个字符。对不起!

标签: c++ 3d directx-11 spritefont


【解决方案1】:

首先,由于您使用的是 DirectXTK,因此不需要 DirectXTex。 DirectXTex 适用于纹理处理工具,而 DirectXTK 纹理加载器更适合在应用程序中使用。见this blog post

第二,不要使用古老的timeGetTime函数。您可以使用GetTickCount,尽管GetTickCount64 更好,因为它可以避免溢出问题。然而,对于帧定时,这些还不够精确。您应该看看DirectX Tool Kit 教程中使用的StepTimer.h

第三,您应该考虑使用Microsoft::WRL::ComPtr 而不是所有SAFE_RELEASE 宏的东西。有关详细信息,请参阅this page

您的代码也包含xinput.h。您应该看看使用 DirectX Tool Kit 的 GamePad,它有很多好处。如果不出意外,它使用 XInput 的能力可能比你想象的要强。

说了这么多,你的问题很简单:你在InitScene中为你的场景设置了渲染状态,但是绘制任何东西会改变状态正是SpriteBatch 所做的。我记录了 DirectX Toolkit 中每个对象在 wiki 上操作的渲染状态。

你需要设置你的 Draw 需要每一帧的所有状态,而不是假设它是永久设置的,如果你做的不止一次。

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);

//>>>> THESE WERE MOVED FROM INITSCENE ABOVE!
    // Set Vertex and Pixel Shaders
    g_pDeviceContext->VSSetShader(g_pVertexShader, 0, 0);
    g_pDeviceContext->PSSetShader(g_pPixelShader, 0, 0);

    // Set the vertex buffer
    UINT stride = sizeof(SimpleVertex);
    UINT offset = 0;
    g_pDeviceContext->IASetVertexBuffers(0, 1, &g_pTriangleVertexBuffer, &stride, &offset);

    g_pDeviceContext->IASetIndexBuffer(g_pSquareIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

    // 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

    g_pDeviceContext->RSSetState(g_pNoCullSolid);
//THESE WERE MOVED FROM INITSCENE ABOVE! <<<<

    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);
//>>>> This behavior means the app crashes if you hit a DEVICE_REMOVED or DEVICE_RESET.
    if (FAILED(hr))
    {
        ErrorBoxW(L"Cannot present without error.");
    }
}

您通常可以为视口状态RSSetViewports“设置它并忘记它”,这也隐式设置剪刀状态,但更好的用法是在您执行初始Clear 时在每一帧的开头设置它.这是我在Direct3D Game Templates 中使用的模式。

【讨论】:

  • 首先:我使用 DirectXTex 库将我的图像文件包含在代码中 (hr = CreateWICTextureFromFile(g_pDevice, L"tcage.png", NULL, &amp;g_pCageTexture); if (FAILED(hr)) {})
  • 第二:我很久以前就开始学习DirectX 9,在我当时使用的教程中timeGetTime 还可以。所以我只是把它带到我目前的 DirectX 11 课程中;第三个也是一样。总结:我会在学习过程中改变所有的旧东西。最后我在文件中包含了xinput.h,因为我有一个使用XINPUT 的包装类,并获得了我的Xbox 控制器的状态。只是尽可能地删除了示例和 30000 个字符大小。 :-)
  • 我刚刚测试了您的解决方案,它运行良好。非常感谢你!还有详细的提示和附加链接。我将阅读您的教程和 wiki 以了解有关 DirectX 11 的更多信息。
【解决方案2】:

完整代码如下:

#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
}

Scene without SpriteFont

Scene with SpriteFont

【讨论】:

  • 您没有包含您的 HLSL 源代码,因此这可能是错误的。使用COLOR_ZEROCOLOR_ONE 作为语义也很奇怪。你的意思是COLOR0COLOR1?如果是这样,您需要使用COLOR,然后提供0和1的语义索引。
  • 问题中显示了两个 hlsl 文件的源代码,并在运行时通过 D3DCompileFromFile in InitScene 编译。我还尝试将布局的颜色描述命名为COLOR0COLOR1,但每次我在布局描述中使用数字时,都无法编译着色器文件。所以我切换到_ZERO_ONE。我不知道这可以用语义索引来完成。我会改变的。
猜你喜欢
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 2014-06-23
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多