我有一个c++/cx项目,我正在使用DirectX-11渲染程序网格,看起来一切都很好,但现在我想从文件(确切地说是从fbx )导入和渲染网格。我被告知要使用DirectX工具包来做这件事。
我遵循了工具包的教程,这一切都起作用了,但后来我尝试在我的项目中这样做,但它似乎不起作用。导入的网格不可见,并且现有的程序网格渲染不正确(就像没有深度缓冲区一样)。
然后我尝试手动渲染导入的网格(与程序网格相同,不使用DirectXTK的绘制功能)。这种方法效果更好,现有网格都是正确的,但导入的网格颜色是错误的;我使用了自定义的顶点和片段着色器,它只使用顶点位置和颜色数据,但由于某种原因,导入的网格的法线被发送到着色器,而不是顶点颜色。
(我甚至不希望法线存储在网格中,但我似乎没有选项来导出到没有法线的fbx,即使我手动从fbx中删除它们,在导入时DirectXTK似乎会重新计算法线)
有人知道我做错了什么吗?这一切对我来说都是相对较新的,所以感谢任何帮助。如果你需要更多信息,请让我知道。
下面是我渲染网格的代码:
首先是主渲染函数(每次更新都会调用一次):
void Track3D::Render()
{
if (!_loadingComplete)
{
return;
}
static const XMVECTORF32 up = { 0.0f, 1.0f, 0.0f, 0.0f };
// Prepare to pass the view matrix, and updated model matrix, to the shader
XMStoreFloat4x4(&_constantBufferData.view, XMMatrixTranspose(XMMatrixLookAtRH(_CameraPosition, _CameraLookat, up)));
// Clear the back buffer and depth stencil view.
_d3dContext->ClearRenderTargetView(_renderTargetView.Get(), DirectX::Colors::Transparent);
_d3dContext->ClearDepthStencilView(_depthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
// Set render targets to the screen.
ID3D11RenderTargetView *const targets[1] = { _renderTargetView.Get() };
_d3dContext->OMSetRenderTargets(1, targets, _depthStencilView.Get());
// Here I render everything:
_TrackMesh->Render(_constantBufferData);
RenderExtra();
_ImportedMesh->Render(_constantBufferData);
Present();
}Present-函数:
void Track3D::Present()
{
DXGI_PRESENT_PARAMETERS parameters = { 0 };
parameters.DirtyRectsCount = 0;
parameters.pDirtyRects = nullptr;
parameters.pScrollRect = nullptr;
parameters.pScrollOffset = nullptr;
HRESULT hr = S_OK;
hr = _swapChain->Present1(1, 0, ¶meters);
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
OnDeviceLost();
}
else
{
if (FAILED(hr))
{
throw Platform::Exception::CreateException(hr);
}
}
}下面是我在每个网格上调用的渲染函数:(所有特定于网格的数据都是从导入的网格中获取的)
void Mesh::Render(ModelViewProjectionConstantBuffer constantBufferData)
{
if (!_loadingComplete)
{
return;
}
XMStoreFloat4x4(&constantBufferData.model, XMLoadFloat4x4(&_modelMatrix));
// Prepare the constant buffer to send it to the Graphics device.
_d3dContext->UpdateSubresource(
_constantBuffer.Get(),
0,
NULL,
&constantBufferData,
0,
0
);
UINT offset = 0;
_d3dContext->IASetVertexBuffers(
0,
1,
_vertexBuffer.GetAddressOf(),
&_stride,
&_offset
);
_d3dContext->IASetIndexBuffer(
_indexBuffer.Get(),
DXGI_FORMAT_R16_UINT, // Each index is one 16-bit unsigned integer (short).
0
);
_d3dContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_d3dContext->IASetInputLayout(_inputLayout.Get());
// Attach our vertex shader.
_d3dContext->VSSetShader(
_vertexShader.Get(),
nullptr,
0
);
// Send the constant buffer to the Graphics device.
_d3dContext->VSSetConstantBuffers(
0,
1,
_constantBuffer.GetAddressOf()
);
// Attach our pixel shader.
_d3dContext->PSSetShader(
_pixelShader.Get(),
nullptr,
0
);
SetTexture();
// Draw the objects.
_d3dContext->DrawIndexed(
_indexCount,
0,
0
);
}这是顶点着色器:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
float3 pos : POSITION;
//float3 normal : NORMAL0; //uncommenting these changes the color data for some reason (but always wrong)
//float2 uv1 : TEXCOORD0;
//float2 uv2 : TEXCOORD1;
float3 color : COLOR0;
};
struct VertexShaderOutput
{
float3 color : COLOR0;
float4 pos : SV_POSITION;
};
VertexShaderOutput main(VertexShaderInput input)
{
VertexShaderOutput output;
float4 pos = float4(input.pos, 1.0f);
// Transform the vertex position into projected space.
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
output.color = input.color;
return output;
}这是像素着色器:
struct PixelShaderInput
{
float3 color: COLOR0;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
return float4(input.color.r, input.color.g, input.color.b, 1);
}发布于 2017-06-24 13:30:07
最有可能的问题是,您没有为绘图设置足够的状态,并且DirectX工具包绘图函数设置的状态与现有代码所需的状态不匹配。
出于性能原因,DirectX工具包不会“保存和恢复”状态。相反,每个绘制函数完全设置它需要的状态,然后离开它。我在每个类的状态管理部分下的wiki中记录了受影响的状态。
上面的代码在插槽0中设置顶点缓冲区、索引缓冲区、输入布局、顶点着色器、像素着色器、基本体拓扑和VS常量缓冲区。
您未设置混合状态、深度/模具状态或光栅化状态。您没有提供像素着色器,所以我不知道您是否需要任何PS常量缓冲区、采样器或着色器资源。
在绘制程序网格之前,请尝试显式设置混合状态、深度/模具状态和光栅化器状态。如果您只想返回到定义的默认值,而不是DirectX工具包所做的,调用:
_d3dContext->RSSetState(nullptr);
_d3dContext->OMSetBlendState(nullptr, nullptr, 0);
_d3dContext->OMSetDepthStencilState(nullptr, 0xffffffff);另请参阅CommonStates类。
在C++中使用以
_开头的标识符通常不是一个好主意。按照官方说法,所有以_X开头的标识符,其中X是大写字母或__,都是为编译器和库实现者保留的,因此它可能会与某些编译器内容冲突。m_或类似的东西更好。
https://stackoverflow.com/questions/44716922
复制相似问题