我在使用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::DrawString
和SpriteBatch::End()
,您会看到一个纹理立方体在空间(笼子)中旋转。通过调用所描述的函数,您只能在左上角看到每秒帧数,但没有旋转立方体。
我在github DirectXTK上关注了来自 Chuck Walbourn 的教程,并使用SpriteFont
组合了2个教程Draw String并渲染了一个原始3D对象(一个简单的三角形)。在这个例子中,我将看到测试字符串绘制在三角形上。但我不明白为什么使用SpriteFont
类的DirectXTK绘制文本字符串时,我的示例中的旋转立方体是不可见的,我甚至找不到根本原因。
像素着色器文件(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。
注意:我创建了重复的问题,
避免 ...寻求帮助,澄清或回复其他答案。
关于另一个问题。
答案 0 :(得分:3)
首先,当您使用DirectXTK时,您不需要DirectXTex。 DirectXTex用于纹理处理工具,而DirectXTK纹理加载器更适合用于应用程序。请参阅this blog post。
其次,不要使用古老的timeGetTime
函数。您可以使用GetTickCount
,但GetTickCount64
更好,因为它可以避免溢出问题。然而,对于帧定时,这些不够精确。您应该查看StepTimer.h教程中使用的DirectX Tool Kit。
第三,您应该考虑使用Microsoft::WRL::ComPtr
而不是所有SAFE_RELEASE
宏内容。有关详细信息,请参阅this page。
您的代码也包括
xinput.h
。您应该看一下使用DirectX Tool Kit的GamePad而不是它有很多好处。如果不出意外,它会比你可能更强大地使用XInput。
尽管如此,您的问题非常简单:您在InitScene
中为场景设置了渲染状态,但是绘制任何 else会改变状态正是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
“设置并忘记它”,它也隐式设置剪刀状态,但更好的用法是在您执行初始时将其设置在每个帧的开头{ {1}}。这是我在Direct3D Game Templates中使用的模式。
答案 1 :(得分:0)