DirectX::SpriteFont/SpriteBatch prevents 3D scene from drawing

这一生的挚爱 提交于 2019-12-04 05:27:02

问题


I have a problem using DirectX::SpriteFont/DirectX::SpriteBatch (from DirectXTK; exactly the same problem as discussed here: 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.");
    }
}

Without the calls to SpriteBatch::Begin(), SpriteFont::DrawString and SpriteBatch::End() you will see a textured cube rotating through space (a cage). With the calls to the described functions, you will only see the frames per second in the upper left corner, but no rotating cube.

I followed the tutorials from Chuck Walbourn on github DirectXTK and combined the 2 tutorials Draw String using SpriteFont and rendering a primitive 3D object (a simple triangle). In this example I will see the test string drawing over the triangle. But I do not understand why the rotating cube from my example is not visible while drawing a text string using SpriteFont class of DirectXTK and I cannot even find the root cause.

Pixel shader file (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;
}

Vertex shader file (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;
}

To reproduce the issue: I am working with Visual Studio 2015 Community Edition. I added DirectXTK (.lib) and DirectXTex (WICTextureLoader .cpp/.h, DDSTextureLoader .cpp/.h, .lib) to my project. Image for cube is .png with alpha.

Note: I created this duplicated question, to

avoid ... Asking for help, clarification, or responding to other answers.

on the other question.


回答1:


First, as you are using DirectXTK, you don't need DirectXTex. DirectXTex is intended for texture processing tools, while DirectXTK texture loaders are more suited to use in applications. See this blog post.

Second, don't use the ancient timeGetTime function. You can use GetTickCount, although GetTickCount64 is better as it avoids overflow problems. For frame timing, however, these are not really precise enough. You should take a look at the StepTimer.h used in the DirectX Tool Kit tutorials.

Third, you should look at using Microsoft::WRL::ComPtr rather than all the SAFE_RELEASE macro stuff. See this page for details.

Your code was including xinput.h as well. You should take a look at using DirectX Tool Kit's GamePad instead which has a number of benefits. If nothing else, it uses XInput more robustly than you likely would.

With all that said, your problem is quite simple: You set the render state up for your scene in InitScene, but drawing anything else changes the state which is exactly what SpriteBatch does. I document which render states each object in DirectX Toolkit manipulates on the wiki.

You need to set all the state your Draw requires each frame, not assume it is set forever, if you do more than a single 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.");
    }
}

You can generally 'set it and forget it' for the viewport state RSSetViewports which also implicitly sets the scissors state, but a better usage is to set it at the start of each frame when you do your initial Clear. This is the pattern I use in the Direct3D Game Templates.




回答2:


Here is the complete code:

#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



来源:https://stackoverflow.com/questions/35558178/directxspritefont-spritebatch-prevents-3d-scene-from-drawing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!