0

I have a c++/cx project where I'm rendering procedural meshes using DirectX-11, it all seems to work fine, but now I wanted to also import and render meshes from files (from fbx to be exact). I was told to use the DirectX Toolkit for this.

I followed the tutorials of the toolkit, and that all worked, but then I tried doing that in my project but it didn't seem to work. The imported mesh was not visible, and the existing procedural meshes were rendered incorrectly (as if without a depth buffer).

I then tried manually rendering the imported mesh (identical to the procedural meshes, without using the Draw function from DirectXTK) This works better, the existing meshes are all correct, but the imported mesh color's are wrong; I use a custom made vertex and fragment shader, that uses only vertex position and color data, but for some reason the imported mesh's normals are send to shader instead of the vertex-colors.

(I don't even want the normals to be stored in the mesh, but I don't seem to have the option to export to fbx without normals, and even if I remove them manually from the fbx, at import the DirectXTK seem to recalculate the normals)

Does anyone know what I'm doing wrong? This is all still relatively new to me, so any help appreciated. If you need more info, just let me know.

Here is my code for rendering meshes:

First the main render function (which is called once every update):

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

The Present-function:

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

Here's the render function which I call on every mesh: (All of the mesh-specific data is gotten from the imported mesh)

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

And this is the vertex shader:

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

And this is the pixel shader:

struct PixelShaderInput
{
    float3 color: COLOR0;
};

float4 main(PixelShaderInput input) : SV_TARGET
{
    return float4(input.color.r, input.color.g, input.color.b, 1);
}
Stef
  • 315
  • 3
  • 14

1 Answers1

1

The most likely issue is that you are not setting enough state for your drawing, and that the DirectX Tool Kit drawing functions are setting states that don't match what your existing code requires.

For performance reasons, DirectX Tool Kit does not 'save & restore' state. Instead each draw function sets the state it needs fully and then leaves it. I document which state is impacted in the wiki under the State management section for each class.

Your code above sets the vertex buffer, index buffer, input layout, vertex shader, pixel shader, primitive topology, and VS constant buffer in slot 0.

You did not set blend state, depth/stencil state, or the rasterizer state. You didn't provide the pixel shader so I don't know if you need any PS constant buffers, samplers, or shader resources.

Try explicitly setting the blend state, depth/stencil state, and rasterizer state before you draw your procedural meshes. If you just want to go back to the defined defaults instead of whatever DirectX Tool Kit did, call:

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

See also the CommonStates class.

It's generally not a good idea to use identifiers that start with _ in C++. Officially all identifiers that start with _X where X is a capital letter or __ are reserved for the compiler and library implementers so it could conflict with some compiler stuff. m_ or something similar is better.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
  • Thanks for your answer, I tried adding those lines, but they result in nothing being drawn. I added more code to my question, mainly the main render function, I do use ClearDepthStencilView() and OMSetRenderTargets(), is that similar to setting the SetDepthStencilState? My code is based on msdn and sample projects, it took me a while to get it all working and I must say that I don't completely understand all of it, but I find it weird that these didn't set the blend state either if that's required? – Stef Jun 26 '17 at 09:48
  • Also, I wasn't rendering the imported mesh using the DIrectXTK, I was rendering it using the Mesh:Render function I posted in my question. So if these 3 lines only reset those states to default, then shouldn't I not need to call these as they are never changed? – Stef Jun 26 '17 at 10:31