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

后端 未结 2 1050
一个人的身影
一个人的身影 2021-01-27 03:45

I have a problem using DirectX::SpriteFont/DirectX::SpriteBatch (from DirectXTK; exactly the same problem as discussed here: Problems when drawing text

2条回答
  •  旧巷少年郎
    2021-01-27 04:31

    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.

提交回复
热议问题