简体   繁体   中英

DirectX incorrect texture

My DirectX application does not render the texture correctly. Result:

猫

Expected from VS editor:

在此处输入图像描述

As you can see the cat texture is not completely drawn.

I 'm using WaveFrontReader to load the.OBJ and the.MTL files and WicTextureLoader to load the PNG/JPG.

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

My preparation:

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

Loading the obj:

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

CreateDirect3D2() function:

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;

}

The drawing function:

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

Entire project here: https://drive.google.com/open?id=1BbW3DUd20bAwei4KjnkUPwgm5Ia1aRxl

This is what I got after I was able to reproduce the issue of OP on my side:

OP 示例代码的快照

My only change was that I exluded lighting in the shader 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;
}

Then I became aware of the cat's eye on the cat's tail.

That reminded me that a lot of image formats store the image from top to down.

OpenGL textures (and probably Direct3D as well) has usually the origin in the lower left corner. Hence, it's not un-usual that texture images are mirrored vertically (during or after loading the image from file and before sending it to GPU).

To prove my suspicion, I mirrored the image manually (in GIMP) and then (without re-compiling) got this:

修复图像后 OP 示例代码的快照

It looks like my suspicion was right.

Something is wrong with the image or texture loading in the loader of OP.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM