c++ - DirectX::SpriteFont/SpriteBatch 阻止绘制 3D 场景

标签 c++ 3d directx-11 spritefont

我在使用 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 Community Edition。我在我的项目中添加了 DirectXTK (.lib) 和 DirectXTex (WICTextureLoader .cpp/.h, DDSTextureLoader .cpp/.h, .lib)。立方体的图像是带有 alpha 的 .png。

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

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

关于另一个问题。

最佳答案

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

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

第三,您应该考虑使用 Microsoft::WRL::ComPtr 而不是所有的 SAFE_RELEASE 宏。参见 this page了解详情。

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.

综上所述,您的问题很简单:您在 InitScene 中为您的场景设置了渲染状态,但是绘制任何东西 else 改变状态,这正是 SpriteBatch 所做的。我记录了 DirectX 工具包中每个对象在 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.");
    }
}

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

关于c++ - DirectX::SpriteFont/SpriteBatch 阻止绘制 3D 场景,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35558178/

相关文章:

java - 将 opengl 纹理句柄从 Android Java 传递到 C++?

c++ - 在不破坏现有内容的情况下绘制 Present() 钩子(Hook)

c++ - DX11 Sprite 问题

c++ - "Packing"结构对性能有何影响

c++ - 关于行进立方体算法的说明

java - 动态内存处理 Java 与 C++

algorithm - 如何绕任意轴旋转?

c++ - DirectX 11调试器需要Windows SDK 10,但已在IDE中选择并在系统中显示

c++ - C++语言的两道题

c++ - Operator= 除非对象已经初始化,否则重载不起作用