DirectX :: SpriteFont / SpriteBatch防止3D场景绘制 [英] DirectX::SpriteFont/SpriteBatch prevents 3D scene from drawing

查看:532
本文介绍了DirectX :: SpriteFont / SpriteBatch防止3D场景绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题使用 DirectX :: SpriteFont / DirectX :: SpriteBatch (从DirectXTK;完全相同问题:使用SpriteFont类绘制文本时的问题)。

  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_pSp​​riteBatch-> Begin();
// g_pSp​​riteFont-> DrawString(g_pSp​​riteBatch,buffer,XMFLOAT2(30,30));
// g_pSp​​riteBatch-> End();

//将backbuffer呈现到屏幕
hr = g_pSwapChain-> Present(0,0);
if(FAILED(hr))
{
ErrorBoxW(L无法显示没有错误。
}
}

没有调用 SpriteBatch :: Begin() SpriteFont :: DrawString SpriteBatch :: End()你会看到一个纹理的立方体旋转通过空间(笼子)。



我按照下面的教程从

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



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

  struct VS_OUTPUT 
{
float4 Pos:SV_POSITION;
float4颜色: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;
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 / .lib)到我的项目。多维数据集的图片是含有Alpha的.png。



注意:我创建了此重复的问题, >


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




另一个问题。

解决方案

使用DirectXTK,你不需要DirectXTex。 DirectXTex用于纹理处理工具,而DirectXTK纹理加载器更适合在应用程序中使用。请参见此博客post



其次,不要使用古老的 timeGetTime 函数。你可以使用 GetTickCount ,虽然 GetTickCount64 更好,因为它避免了溢出问题。然而,对于帧定时,这些并不真的足够精确。您应该查看 StepTimer.h ,在 DirectX工具包教程中使用。 Microsoft :: WRL :: ComPtr ,而不是所有的 SAFE_RELEASE 宏东西。有关详情,请参见此页


您的代码还包括 xinput.h 。您应该查看使用DirectX Tool Kit的 GamePad ,它具有许多优点。如果没有别的,它使用XInput比你可能会更强大。


InitScene 中为场景设置渲染状态,但是绘制任何 c $ c> 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);

//>>>>>这些从以上的INITSCENE移动!
//设置顶点和像素着色器
g_pDeviceContext-> VSSetShader(g_pVertexShader,0,0);
g_pDeviceContext-> PSSetShader(g_pPixel Shader,0,0);

//设置顶点缓冲区
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);

//设置输入布局
g_pDeviceContext-> IASetInputLayout(g_pVertexLayout);

//设置原始拓扑
g_pDeviceContext-> IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); //每个三角形3个顶点
// g_pDeviceContext-> IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); //每个点1个顶点
// g_pDeviceContext-> IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); //每行2个顶点

//创建视口

g_pDeviceContext-> RSSetState(g_pNoCullSolid);
//这些从以上的INITSCENE移动! <<<

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_pSp​​riteBatch-> Begin();
g_pSp​​riteFont-> DrawString(g_pSp​​riteBatch,buffer,XMFLOAT2(30,30));
g_pSp​​riteBatch-> End();

//将backbuffer呈现到屏幕
hr = g_pSwapChain-> Present(0,0);
//>>>>>此行为意味着如果您点击了DEVICE_REMOVED或DEVICE_RESET,应用程式会崩溃。
if(FAILED(hr))
{
ErrorBoxW(L无法显示没有错误。
}
}

您通常可以设置并忘记视口状态 RSSetViewports 也隐含地设置剪刀状态,但是更好的用法是在每个框架的开始设置它,当你执行你的初始清除。这是我在 Direct3D游戏模板中使用的模式。


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.

解决方案

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.

这篇关于DirectX :: SpriteFont / SpriteBatch防止3D场景绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆