2

如果我绘制一个平面,则纹理坐标会正确映射。(4 个顶点,4 个 TC,6 个索引(2 个多边形))

即使它被细分,(9 Verts, 9 TC, 27 Indices(8 polys)) 纹理也会显示: 在此处输入图像描述

(玛雅复平面) 在此处输入图像描述

我可以使用我的 [书面] Obj 转换器并将纹理坐标加载到缓冲区中。但是,如果我在 Maya 中挤出一个面,甚至应用平面 UV 贴图来“修复”损坏的 uv,(上图)纹理坐标在引擎中会变得非常狂野。(以下) 在此处输入图像描述

Obj 纹理坐标格式有问题吗?

更新:我用 D3D11_PRIMITIVE_TOPOLOGY_LINELIST 绘制,并注意到索引也发生了变化。在此处输入图像描述这会是问题吗?或者我应该在http://www.gamedev.net/topic/600234-texcoord-count-is-different-than-vertex-count/上重建纹理坐标

4

3 回答 3

3

此问题是由纹理坐标索引不等于顶点索引引起的。为了解决这个问题,必须对纹理坐标索引进行排序,以便与顶点索引对齐。

对于这个问题,我能够使用符合我理解的蛮力方法来解决,这种方法很慢,将整个顶点/纹理坐标编目为一个键,并从它们的索引中重建顶点和纹理坐标的完整显式数组,填充适合我的应用程序需求的自定义结构。

在此处输入图像描述

还有其他更快的解决方案涉及使用哈希 http://programminglinuxgames.blogspot.com/2010/03/wavefront-obj-file-format-opengl-vertex.html

与法线相关的问题: OpenGL - 索引缓冲区困难

3 个索引缓冲区

还有一个很好的解释: 为什么我的 OBJ 解析器渲染网格是这样的?

以及有关 obj 格式的更多资源: http ://en.wikipedia.org/wiki/Wavefront_.obj_file

OBJ 资源: http: //www.martinreddy.net/gfx/3d/OBJ.spec http://www.fileformat.info/format/wavefrontobj/egff.htm

此外,DirectX 库中的 MeshFromObj10 教程可以帮助一些人,以有效的方式完成它。除了找到第三方来源之外,没有简单的方法对其进行编码。

于 2014-11-18T08:20:36.983 回答
2

看看这些东西,它可能对你有帮助:

DirectX 使用左坐标系。我认为当您导出到 .obj 文件时,您将从 Maya/3ds Max 获得右手坐标系://msdn.microsoft.com/en-us/library/windows/desktop/bb204853(v=vs.85)。 aspx

在 Maya 中比较您的顶点数,然后在您的程序中比较。

找出你在 TU/TV 坐标中得到 1.000671 的原因,这看起来有点高。

确保导出为三角形而不是矩形。

在 Maya 中显示您的法线,看起来该对象所站立的地面/矩形的某些部分丢失了。或者您可以尝试在 D3D11_RASTERIZER_DESC 中禁用剔除。

我现在没有在我的计算机上安装 Maya,但我认为您可以在其中获得一个图形视图,向您显示纹理上的精确 TU/TV 坐标。

http://www.youtube.com/watch?v=T-fFpmBYP_Q 该视图显示在此视频中 4,21。

编辑:

提供一些代码示例:

struct D3D11TextureVertexType
{
    XMFLOAT3 Position;
    XMFLOAT2 TX;
};

这是您可以将顶点放在管道上的方法:

hr = m_pd3dImmediateContext->Map(MyID3D11Buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(hr)) return hr;

    pData = (D3D11TextureVertexType*)mappedResource.pData;
    memcpy(pData, MYOBJECTVERTICES/*this is D3D11TextureVertexType*/, sizeof(D3D11TextureVertexType) * VertexCount);

    m_pd3dImmediateContext->Unmap(MyID3D11Buffer, 0);

    stride = sizeof(D3D11TextureVertexType);
    offset = 0;

    m_pd3dImmediateContext->IASetVertexBuffers(0, 1, &MyID3D11Buffer, &stride, &offset);
    m_pd3dImmediateContext->IASetIndexBuffer(m_AdjRectangleIBuffer, DXGI_FORMAT_R32_UINT, 0);
    m_pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    result = m_TextureShader->Render(m_pd3dImmediateContext, 6, worldMatrix, viewMatrix, orthoMatrix, m_Textures[Q.textureID]->pSRV);           if (!result)
    {
        return S_FALSE;
    }

这是 TextureShaderClass 中的一些有趣的功能

bool Render(ID3D11DeviceContext* deviceContext, int indexCount, DirectX::CXMMATRIX worldMatrix, DirectX::CXMMATRIX viewMatrix, DirectX::CXMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture)
{
    bool result;

    result = SetShaderParameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture);
    if (!result)
    {
        return false;
    }

    RenderShader(deviceContext, indexCount);

    return true;
}

bool InitializeShader(ID3D11Device* device, const WCHAR* filename)
{
    HRESULT result;
    ID3D10Blob* errorMessage;
    ID3D10Blob* vertexShaderBuffer;
    ID3D10Blob* pixelShaderBuffer;
    D3D11_INPUT_ELEMENT_DESC polygonLayout[2];
    unsigned int numElements;
    D3D11_BUFFER_DESC matrixBufferDesc;
    D3D11_SAMPLER_DESC samplerDesc;

    errorMessage = 0;
    vertexShaderBuffer = 0;
    pixelShaderBuffer = 0;



    result = D3DCompileFromFile(filename, NULL, NULL, "TextureVertexShader", "vs_5_0", 0, 0, &vertexShaderBuffer, &errorMessage);
    if (FAILED(result))
    {
        if (errorMessage)
        {
            //OutputShaderErrorMessage(errorMessage, hwnd, filename);
        }
        else
        {
            MessageBox(0, filename, L"Missing Shader File", MB_OK);
        }

        return false;
    }

    result = D3DCompileFromFile(filename, NULL, NULL, "TexturePixelShader", "ps_5_0", 0, 0, &pixelShaderBuffer, &errorMessage);
    if (FAILED(result))
    {
        if (errorMessage)
        {
            //OutputShaderErrorMessage(errorMessage, hwnd, psFilename);
        }
        else
        {
            MessageBox(0, filename, L"Missing Shader File", MB_OK);
        }

        return false;
    }

    result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &m_vertexShader);
    if (FAILED(result))
    {
        return false;
    }

    result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &m_pixelShader);
    if (FAILED(result))
    {
        return false;
    }

    polygonLayout[0].SemanticName = "POSITION";
    polygonLayout[0].SemanticIndex = 0;
    polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
    polygonLayout[0].InputSlot = 0;
    polygonLayout[0].AlignedByteOffset = 0;
    polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    polygonLayout[0].InstanceDataStepRate = 0;

    polygonLayout[1].SemanticName = "TEXCOORD";
    polygonLayout[1].SemanticIndex = 0;
    polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
    polygonLayout[1].InputSlot = 0;
    polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
    polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
    polygonLayout[1].InstanceDataStepRate = 0;

    numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

    result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &m_layout);
    if (FAILED(result))
    {
        return false;
    }

    vertexShaderBuffer->Release();
    vertexShaderBuffer = 0;

    pixelShaderBuffer->Release();
    pixelShaderBuffer = 0;

    matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
    matrixBufferDesc.ByteWidth = sizeof(MatrixBufferType);
    matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    matrixBufferDesc.MiscFlags = 0;
    matrixBufferDesc.StructureByteStride = 0;

    result = device->CreateBuffer(&matrixBufferDesc, NULL, &m_matrixBuffer);
    if (FAILED(result))
    {
        return false;
    }

    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.MipLODBias = 0.0f;
    samplerDesc.MaxAnisotropy = 1;
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
    samplerDesc.BorderColor[0] = 0;
    samplerDesc.BorderColor[1] = 0;
    samplerDesc.BorderColor[2] = 0;
    samplerDesc.BorderColor[3] = 0;
    samplerDesc.MinLOD = 0;
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

    result = device->CreateSamplerState(&samplerDesc, &m_sampleState);
    if (FAILED(result))
    {
        return false;
    }

    return true;
}
bool SetShaderParameters(ID3D11DeviceContext* deviceContext, DirectX::CXMMATRIX worldMatrix, DirectX::CXMMATRIX  viewMatrix, DirectX::CXMMATRIX  projectionMatrix, ID3D11ShaderResourceView* texture)
{
    HRESULT result;
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    MatrixBufferType* dataPtr;
    unsigned int bufferNumber;

    result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(result))
    {
        return false;
    }

    dataPtr = (MatrixBufferType*)mappedResource.pData;

    DirectX::XMMATRIX world = worldMatrix;
    world = XMMatrixTranspose(world);
    DirectX::XMMATRIX view = viewMatrix;
    view = XMMatrixTranspose(view);
    DirectX::XMMATRIX projection = projectionMatrix;
    projection = XMMatrixTranspose(projection);

    dataPtr->world = world;
    dataPtr->view = view;
    dataPtr->projection = projection;

    deviceContext->Unmap(m_matrixBuffer, 0);

    bufferNumber = 0;

    deviceContext->VSSetConstantBuffers(bufferNumber, 1, &m_matrixBuffer);

    deviceContext->PSSetShaderResources(0, 1, &texture);

    return true;
}

void RenderShader(ID3D11DeviceContext* deviceContext, int indexCount)
{
    deviceContext->IASetInputLayout(m_layout);

    deviceContext->VSSetShader(m_vertexShader, NULL, 0);
    deviceContext->PSSetShader(m_pixelShader, NULL, 0);

    deviceContext->PSSetSamplers(0, 1, &m_sampleState);

    deviceContext->DrawIndexed(indexCount, 0, 0);

    return;
}
于 2014-11-14T18:30:26.733 回答
1

从 Maya 尝试在执行挤出后重新导出纹理以获得正确的 uv 映射。

挤压会创建新的面,而现有的 uv 映射不适用于这些面。尝试使用几何清洁工具。

据我所知,您正在制作 UV 贴图后编辑模型,而不是将 UV 贴图更新为挤出对象(这仍然是规划器)。

您还可以尝试包含纹理的所有专家选项,而不仅仅是 .obj 中的模型

好久没用Maya了:(

于 2014-11-14T17:33:45.517 回答