DirectX неверная текстура - PullRequest
1 голос
/ 06 апреля 2020

Приложение DirectX неправильно отображает текстуру. Результат:

Cat

Ожидается от редактора VS:

enter image description here

As Вы можете видеть, что текстура кота прорисована не полностью.

Я использую WaveFrontReader для загрузки файлов .OBJ и .MTL и WicTextureLoader для загрузки PNG /JPG.

Мой HLSL:

cbuffer constants : register(b0)
{
    row_major float4x4 transform;
    row_major float4x4 projection;
    float3 lightvector;
}

struct vs_in
{
    float3 position : POS;
    float3 normal   : NOR;
    float2 texcoord : TEX;
    float4 color    : COL;
};

struct vs_out
{
    float4 position : SV_POSITION;
    float2 texcoord : TEX;
    float4 color    : COL;
};

Texture2D    mytexture : register(t0);
SamplerState mysampler : register(s0);

vs_out vs_main(vs_in input)
{
    float light = clamp(dot(normalize(mul(float4(input.normal, 0.0f), transform).xyz), normalize(-lightvector)), 0.0f, 1.0f) * 0.8f + 0.2f;

    vs_out output;

    output.position = mul(float4(input.position, 1.0f), mul(transform, projection));
    output.texcoord = input.texcoord;
    output.color    = float4(input.color.rgb * light, input.color.a);

    return output;
}

float4 ps_main(vs_out input) : SV_TARGET
{
    return mytexture.Sample(mysampler, input.texcoord) * input.color;
}

Моя подготовка:

void Config3DWindow()
{
const wchar_t* tf = L"1.hlsl";

d2d.m_swapChain1->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&frameBuffer));
d2d.device->CreateRenderTargetView(frameBuffer, nullptr, &frameBufferView);

frameBuffer->GetDesc(&depthBufferDesc); // base on framebuffer properties
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;

CComPtr<ID3DBlob> vsBlob;
D3DCompileFromFile(tf, nullptr, nullptr, "vs_main", "vs_5_0", 0, 0, &vsBlob, nullptr);
d2d.device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &vertexShader);
D3D11_INPUT_ELEMENT_DESC inputElementDesc[] =
{
    { "POS", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0,                            0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "NOR", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "TEX", 0, DXGI_FORMAT_R32G32_FLOAT,       0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    { "COL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
d2d.device->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc), vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &inputLayout);

///////////////////////////////////////////////////////////////////////////////////////////////
CComPtr<ID3DBlob> psBlob;
D3DCompileFromFile(tf, nullptr, nullptr, "ps_main", "ps_5_0", 0, 0, &psBlob, nullptr);
d2d.device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &pixelShader);


D3D11_BUFFER_DESC constantBufferDesc = {};
constantBufferDesc.ByteWidth = sizeof(Constants) + 0xf & 0xfffffff0;
constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;


d2d.device->CreateBuffer(&constantBufferDesc, nullptr, &constantBuffer);
}

Загрузка функции obj:

WaveFrontReader<UINT> wfr;
wfr.Load(L"12221_Cat_v1_l3.oobj");
wfr.LoadMTL(L"12221_Cat_v1_l3.mtl");
obj.CreateDirect3D2(wfr);

CreateDirect3D2 () :

std::vector<float> Vertices;
 //    float VertexDataX[] = // float3 position, float3 normal, float2 texcoord, float4 color

auto numV = wf.vertices.size();
Vertices.resize(numV * 12);
for (size_t i = 0; i < numV; i++)
{
    auto& v = wf.vertices[i];
    float* i2 = Vertices.data() + (i * 12);

    // position
    i2[0] = v.position.x;
    i2[1] = v.position.y;
    i2[2] = v.position.z;

    // normal
    i2[3] = v.normal.x;
    i2[4] = v.normal.y;
    i2[5] = v.normal.z;

    // tx
    i2[6] = v.textureCoordinate.x;
    i2[7] = v.textureCoordinate.y;

    // Colors
    i2[8] = 1.0f;
    i2[9] = 1.0f;
    i2[10] = 1.0f;
    i2[11] = 1.0f;

}

D3D11_BUFFER_DESC vertexBufferDesc = {};
vertexBufferDesc.ByteWidth = Vertices.size() * sizeof(float);
vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
D3D11_SUBRESOURCE_DATA vertexData = { Vertices.data() }; // in data.h
vertexBuffer = 0;
d2d.device->CreateBuffer(&vertexBufferDesc, &vertexData, &vertexBuffer);


// Indices
std::vector<UINT>& Indices = wf.indices;

D3D11_BUFFER_DESC indexBufferDesc = {};
IndicesSize = Indices.size() * sizeof(UINT);

indexBufferDesc.ByteWidth = IndicesSize;
indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
D3D11_SUBRESOURCE_DATA indexData = { Indices.data() }; // in data.h
indexBuffer = 0;
d2d.device->CreateBuffer(&indexBufferDesc, &indexData, &indexBuffer);

for (auto& ma : wf.materials)
{
    CComPtr<ID3D11Resource> tex;
    CComPtr<ID3D11ShaderResourceView> texv;

    CreateWICTextureFromFile(d2d.device, d2d.context, ma.strTexture, &tex, &texv,0);

    if (tex && texv)
    {
        OBJFT ot;
        ot.texture = tex;
        ot.textureView = texv;
        textures.push_back(ot);
    }
    tex = 0;
    texv = 0;

}

Функция рисования:

void Present(OBJF& o, int Count, _3DP& _3, D2D1_COLOR_F bcol)
{
    float w = static_cast<float>(depthBufferDesc.Width);  // width
    float h = static_cast<float>(depthBufferDesc.Height); // height
    float n = 1000.0f;                                    // near
    float f = 1000000.0f;                                 // far

    matrix rotateX = { 1, 0, 0, 0, 0, static_cast<float>(cos(_3.rotation[0])), -static_cast<float>(sin(_3.rotation[0])), 0, 0, static_cast<float>(sin(_3.rotation[0])), static_cast<float>(cos(_3.rotation[0])), 0, 0, 0, 0, 1 };
    matrix rotateY = { static_cast<float>(cos(_3.rotation[1])), 0, static_cast<float>(sin(_3.rotation[1])), 0, 0, 1, 0, 0, -static_cast<float>(sin(_3.rotation[1])), 0, static_cast<float>(cos(_3.rotation[1])), 0, 0, 0, 0, 1 };
    matrix rotateZ = { static_cast<float>(cos(_3.rotation[2])), -static_cast<float>(sin(_3.rotation[2])), 0, 0, static_cast<float>(sin(_3.rotation[2])), static_cast<float>(cos(_3.rotation[2])), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
    matrix scale = { _3.scale[0], 0, 0, 0, 0, _3.scale[1], 0, 0, 0, 0, _3.scale[2], 0, 0, 0, 0, 1 };
    matrix translate = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, _3.translation[0], _3.translation[1], _3.translation[2], 1 };

    ///////////////////////////////////////////////////////////////////////////////////////////
    D3D11_MAPPED_SUBRESOURCE mappedSubresource = {};
    d2d.context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubresource);
    Constants* constants = reinterpret_cast<Constants*>(mappedSubresource.pData);
    constants->Transform = rotateX * rotateY * rotateZ * scale * translate;
    constants->Projection = { 2 * n / w, 0, 0, 0, 0, 2 * n / h, 0, 0, 0, 0, f / (f - n), 1, 0, 0, n * f / (n - f), 0 };
    constants->LightVector = { 1.0f, 1.0f, 1.0f };
    d2d.context->Unmap(constantBuffer, 0);

    ///////////////////////////////////////////////////////////////////////////////////////////

    FLOAT backgroundColor[4] = { 0.00f, 0.00f, 0.00f, 1.0f };
    if (bcol.a > 0)
    {
        backgroundColor[0] = bcol.r;
        backgroundColor[1] = bcol.g;
        backgroundColor[2] = bcol.b;
        backgroundColor[3] = bcol.a;
    }

    UINT stride = 12 * 4; // vertex size (12 floats: float3 position, float3 normal, float2 texcoord, float4 color)
    UINT offset = 0;

    D3D11_VIEWPORT viewport = { 0.0f, 0.0f, w, h, 0.0f, 1.0f };

///////////////////////////////////////////////////////////////////////////////////////////

    auto deviceContext = d2d.context;
    deviceContext->ClearRenderTargetView(frameBufferView, backgroundColor);
    deviceContext->ClearDepthStencilView(depthBufferView, D3D11_CLEAR_DEPTH, 1.0f, 0);

    deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    deviceContext->IASetInputLayout(inputLayout);
    deviceContext->IASetVertexBuffers(0, 1, &o.vertexBuffer.p, &stride, &offset);
    deviceContext->IASetIndexBuffer(o.indexBuffer, DXGI_FORMAT_R32_UINT, 0);

    deviceContext->VSSetShader(vertexShader, nullptr, 0);
    deviceContext->VSSetConstantBuffers(0, 1, &constantBuffer.p);
    deviceContext->RSSetViewports(1, &viewport);
    deviceContext->PSSetShader(pixelShader, nullptr, 0);

    std::vector<ID3D11ShaderResourceView*> rsx;
    for (auto& t : o.textures)
        rsx.push_back(t.textureView);
    ID3D11ShaderResourceView** rr = rsx.data();
    deviceContext->PSSetShaderResources(0, rsx.size(), rr);

    deviceContext->PSSetSamplers(0, 1, &samplerState.p);

    deviceContext->OMSetRenderTargets(1, &frameBufferView.p, depthBufferView);
    deviceContext->OMSetDepthStencilState(depthStencilState, 0);

    ///////////////////////////////////////////////////////////////////////////////////////////

    DXGI_RGBA ra = { 1,1,1,1 };
    deviceContext->DrawIndexed(o.IndicesSize, 0, 0);
    d2d.m_swapChain1->Present(1, 0);
}

Весь проект здесь: https://drive.google.com/open?id=1BbW3DUd20bAwei4KjnkUPwgm5Ia1aRxl

1 Ответ

2 голосов
/ 06 апреля 2020

Это то, что я получил после того, как смог воспроизвести проблему ОП на моей стороне:

Snapshot of OPs sample code

Единственное изменение, которое я исключил освещение в шейдерном коде:

vs_out vs_main(vs_in input)
{
    float light = 1.0f;
    //float light = clamp(dot(normalize(mul(float4(input.normal, 0.0f), transform).xyz), normalize(-lightvector)), 0.0f, 1.0f) * 0.8f + 0.2f;

    vs_out output;

    output.position = mul(float4(input.position, 1.0f), mul(transform, projection));
    output.texcoord = input.texcoord;
    output.color    = float4(input.color.rgb * light, input.color.a);

    return output;
}

Затем я узнал о кошачьем глазе на хвосте кошки.

Это напомнило мне, что многие форматы изображений хранят изображение сверху вниз .

Текстуры OpenGL (и, возможно, Direct3D) обычно имеют начало в нижнем левом углу. Следовательно, нередки случаи, когда изображения текстуры зеркально отображаются вертикально (во время или после загрузки изображения из файла и перед отправкой его в графический процессор).

Чтобы доказать свое подозрение, я отразил изображение вручную (в GIMP) и затем (без перекомпиляции) получил это:

Snapshot of OPs sample code after I fixed image

Похоже, мое подозрение было правильным.

Что-то не так с загрузка изображения или текстуры в загрузчик OP.

...