【问题标题】:How to manually render a mesh loaded with the DirectX Toolkit如何手动渲染使用 DirectX Toolkit 加载的网格
【发布时间】:2017-11-26 18:25:10
【问题描述】:

我有一个 c++/cx 项目,我在其中使用 DirectX-11 渲染程序网格,一切似乎都工作正常,但现在我还想从文件中导入和渲染网格(确切地说是从 fbx)。 有人告诉我为此使用 DirectX 工具包。

我按照工具包的教程进行操作,一切正常, 但后来我尝试在我的项目中这样做,但它似乎没有用。导入的网格不可见,并且现有的程序网格渲染不正确(好像没有深度缓冲区)。

然后我尝试手动渲染导入的网格(与程序网格相同,不使用 DirectXTK 的 Draw 功能) 这样效果更好,现有的网格都是正确的,但是导入的网格颜色是错误的;我使用定制的顶点和片段着色器,它只使用顶点位置和颜色数据,但由于某种原因,导入的网格的法线被发送到着色器而不是顶点颜色。

(我什至不希望将法线存储在网格中,但我似乎没有选择在没有法线的情况下导出到 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();
}

礼物功能:

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, &parameters);

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);
}

【问题讨论】:

    标签: directx shader directx-11 c++-cx directxtk


    【解决方案1】:

    最可能的问题是您没有为绘图设置足够的状态,并且 DirectX 工具包 绘图函数设置的状态与您现有代码所需的不匹配。 p>

    出于性能原因,DirectX Tool Kit 不会“保存和恢复”状态。取而代之的是,每个绘图函数都会设置它完全需要的状态,然后离开它。我在每个类的状态管理部分下的wiki 中记录了哪个状态受到影响。

    上面的代码在 slot 0 中设置了顶点缓冲区、索引缓冲区、输入布局、顶点着色器、像素着色器、图元拓扑和 VS 常量缓冲区。

    没有设置混合状态、深度/模板状态或光栅化状态。您没有提供像素着色器,所以我不知道您是否需要任何 PS 常量缓冲区、采样器或着色器资源。

    在绘制程序网格之前,请尝试明确设置混合状态、深度/模板状态和光栅化状态。如果您只想返回定义的默认值而不是 DirectX Tool Kit 所做的任何事情,请调用:

    _d3dContext->RSSetState(nullptr);
    _d3dContext->OMSetBlendState(nullptr, nullptr, 0);
    _d3dContext->OMSetDepthStencilState(nullptr, 0xffffffff);
    

    另请参阅CommonStates 类。

    在 C++ 中使用以_ 开头的标识符通常不是一个好主意。正式地,所有以_X 开头的标识符,其中 X 是大写字母或__ 是为编译器和库实现者保留的,因此它可能与某些编译器内容冲突。 m_ 或类似的更好。

    【讨论】:

    • 感谢您的回答,我尝试添加这些行,但没有绘制任何内容。我在我的问题中添加了更多代码,主要是主渲染功能,我确实使用了 ClearDepthStencilView() 和 OMSetRenderTargets(),这类似于设置 SetDepthStencilState 吗?我的代码基于 msdn 和示例项目,我花了一些时间才让它全部工作,我必须说我并不完全理解所有这些,但我发现这些也没有设置混合状态很奇怪如果这是必需的?
    • 另外,我没有使用 DIrectXTK 渲染导入的网格,而是使用我在问题中发布的 Mesh:Render 函数渲染它。因此,如果这 3 行仅将这些状态重置为默认值,那么我是否不需要调用它们,因为它们从未更改过?
    猜你喜欢
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2013-05-08
    • 2013-07-31
    • 1970-01-01
    • 2016-07-02
    相关资源
    最近更新 更多