1

I have a c++/cx project where I want to render meshes (loaded from FBX-files) using DirectX-11. The FBX-files contain texture coordinates, but when rendering them, these UV-coordinates send to the vertexshader are completely wrong.

Here's how it looks:

2 cyclists

These are supposed to be 2 human cyclists, but the texture is mapped completely wrong.

The vertexDescription is as follows:

D3D11_INPUT_ELEMENT_DESC _vertexDescriptions[3] =
{
    { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};

Note that the Position and Nomal data are correct when rendering, it's only the texture coordinates that are wrong/missing.

VertexShader-input and -output:

struct VertexShaderInput
{
    float3 position : POSITION;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 color : COLOR0;
    float2 uv : TEXCOORD0;
    float4 position : SV_POSITION;
};

PixelShader-input:

struct PixelShaderInput
{
    float4 color: COLOR0;
    float2 uv : TEXCOORD0;
};

Here's a snippet of the fbx-file:

LayerElementUV: 0 {
    Version: 101
    Name: "UVTex"
    MappingInformationType: "ByPolygonVertex"
    ReferenceInformationType: "IndexToDirect"
    UV: 0.118273,0.459037,0.598600,0.180400,0.647187,0.129884,
    //...
    UVIndex: 2136,255,879,734,2136,734,3602,1034,1034,3602,6071,1176,
    //...

The fbx file is build into a cmo-file by visual studio, and it's loaded like this using directxtk:

_effectFactory = std::make_unique<EffectFactory>(_d3dDevice.Get());
_playerModel = Model::CreateFromCMO(_d3dDevice.Get(), L"Ambiorix.Track3DComponent\\PlayerModel.cmo", *_effectFactory);

The PlayerMesh is then initialized like this (_playerModel is passed to this function):

task<void> PlayerMesh::InitializeAsync(Model *const model)
{
    _logger->Trace(L"PlayerMesh.InitializeAsync()");
    _isInitialized = false;

    _primitiveTopology = model->meshes[0]->meshParts[0]->primitiveType;
    _vertexBufferStride = model->meshes[0]->meshParts[0]->vertexStride;
    _vertexBufferOffset = model->meshes[0]->meshParts[0]->vertexOffset;
    _vertexBuffer = model->meshes[0]->meshParts[0]->vertexBuffer;
    _inputLayout = model->meshes[0]->meshParts[0]->inputLayout;
    _indexFormat = model->meshes[0]->meshParts[0]->indexFormat;
    _indexCount = model->meshes[0]->meshParts[0]->indexCount;
    _indexBuffer = model->meshes[0]->meshParts[0]->indexBuffer;

    std::vector<task<void>> tasks;
    tasks.push_back(CreateVertexShaderAsync(_vertexShaderRelativeFilePath, _vertexDescriptions, ARRAYSIZE(_vertexDescriptions)));
    tasks.push_back(CreatePixelShaderAsync(_pixelShaderRelativeFilePath));

    return when_all(tasks.begin(), tasks.end())
        .then([this]
        {
            CreateSamplerState();

            auto createTextureResult = CreateDDSTextureFromFile(_d3dDevice.Get(), _textureRelativeFilePath->Data(), nullptr, _texture.ReleaseAndGetAddressOf());
            if (FAILED(createTextureResult))
            {
                _logger->Error(L"Failed to create texture.");
                return;
            }

            PlayerMeshConstantBuffer solidColorConstantBuffer;

            D3D11_SUBRESOURCE_DATA InitData;
            InitData.pSysMem = &solidColorConstantBuffer;
            InitData.SysMemPitch = 0u;
            InitData.SysMemSlicePitch = 0u;

            CD3D11_BUFFER_DESC bufferDescription(sizeof(PlayerMeshConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);

            auto createConstantBuffer = _d3dDevice->CreateBuffer(&bufferDescription, &InitData, _constantBuffer.GetAddressOf());
            if (FAILED(createConstantBuffer))
            {
                _logger->Error(L"PlayerMesh.InitializeAsync() | Failed to create constant buffer.");
                return;
            }

            _isInitialized = true;
            _logger->Trace("PlayerMesh.InitializeAsync() | Done.");
        });
}

I can share more code, and the entire fbx file if it helps, just ask, I don't really know what else could be usefull to know.

If anyone can shed some light on how to get the uv coordinates correctly in the shaders, it would be most appreciated.

any help?

Edit: I initially stated the the UV's where 0, but I noticed that having

struct VertexShaderOutput
{
    float4 color : COLOR0;
    float2 uv : TEXCOORD;
    float4 position : SV_POSITION;
};

instead of

struct VertexShaderOutput
{
    float4 color : COLOR0;
    float4 position : SV_POSITION;
    float2 uv : TEXCOORD;
};

fixed that, no idea why though.

Stef
  • 315
  • 3
  • 14
  • not really much to show, but sure, I'll add screenshots – Stef Apr 05 '19 at 13:01
  • Ah, I misread, sorry. If all UVs are zeroed out, then indeed there's nothing to show. – Kromster Apr 05 '19 at 13:02
  • yeah it just shows the upper-left-most pixel of the texture, mapped over the entire model. – Stef Apr 05 '19 at 13:04
  • Well.. nothing in your code shows the loading process, and by your description it looks like the UVs are zeroed when loading/importing the model .. – Kromster Apr 05 '19 at 13:07
  • yes, true, I'll add the code to my post. – Stef Apr 05 '19 at 13:09
  • I added some code, but to be honest, most of this was written years ago, and not by me, so I'm not entirely familiar with all of this code. – Stef Apr 05 '19 at 13:18
  • I noticed that changing the order of the properties of the VertexShaderOutput caused the uvs to become 0 in the pixelshader, no idea why though. – Stef Apr 09 '19 at 12:53

0 Answers0