DX11 C ++ Shader无法接收实例缓冲区内容

时间:2014-01-20 18:11:24

标签: c++ shader directx-11

我想绘制一个obj文件的实例。在我实现Instancing而不是通过他自己的draw()函数绘制每个Object(它工作得很好)后,实例定位不正确。可能没有在着色器中正确设置InstanceBuffer中的数据。

D3DMain.cpp - 创建输入布局

struct INSTANCE {
//D3DXMATRIX matTrans;
    D3DXVECTOR3 
};

/***/

// create the input layout object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
    //vertex buffer
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  12, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0,  24, D3D11_INPUT_PER_VERTEX_DATA, 0},

    //instance buffer
    {"INSTTRANS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    //{"INSTTRANS", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    //{"INSTTRANS", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    //{"INSTTRANS", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
};
if (FAILED(d3ddev->CreateInputLayout(ied, 4, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout))) throw(std::string("Input Layout Creation Error"));
d3ddevcon->IASetInputLayout(pLayout);

World.cpp - 设置实例缓冲区

    std::vector<INSTANCE> instanceBuffer;
    INSTANCE insertInstance;

    D3DXMATRIX scaleMat, transMat;
    D3DXMatrixScaling(&scaleMat, 50.0f, 50.0f, 50.0f);

    int i=0;
    for (std::list<SINSTANCES>::iterator it = sInstances.begin(); it != sInstances.end(); it++) {
        if ((*it).TypeID == typeId) {
            //do something
            D3DXMatrixTranslation(&transMat, (*it).pos.x, (*it).pos.y, (*it).pos.z);
            insertInstance.matTrans = (*it).pos;//scaleMat * transMat;
            instanceBuffer.push_back(insertInstance);
            i++;
        }
    }
    instanceCount[typeId] = i;


    //create new IB
    D3D11_BUFFER_DESC instanceBufferDesc;
    ZeroMemory(&instanceBufferDesc, sizeof(instanceBufferDesc));
    instanceBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    instanceBufferDesc.ByteWidth = sizeof(INSTANCE) * i;
    instanceBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    instanceBufferDesc.CPUAccessFlags = 0;
    instanceBufferDesc.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA instanceData;
    ZeroMemory(&instanceData, sizeof(instanceData));
    instanceData.pSysMem = &instanceBuffer[0];

    if (FAILED(d3ddev->CreateBuffer(&instanceBufferDesc, &instanceData, &instanceBufferMap[typeId]))) throw(std::string("Failed to Update Instance Buffer"));

OpenDrawObj.cpp - 绘制.obj文件

UINT stride[2] = {sizeof(VERTEX), sizeof(INSTANCE)};
    UINT offset[2] = {0, 0};

    ID3D11Buffer* combinedBuffer[2] = {meshVertBuff, instanceBuffer};
    d3ddevcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    d3ddevcon->IASetVertexBuffers(0, 2, combinedBuffer, stride, offset);
    d3ddevcon->IASetIndexBuffer(meshIndexBuff, DXGI_FORMAT_R32_UINT, 0);

    std::map<std::wstring, OBJMATERIAL>::iterator fit;
    for (std::vector<DRAWLIST>::iterator it = drawList.begin(); it != drawList.end(); it++) {
        fit = objMaterials.find((*it).material);
        if (fit != objMaterials.end()) {
            if ((*fit).second.texture != NULL) {
                d3ddevcon->PSSetShaderResources(0, 1, &((*fit).second.texture));
            }
            d3ddevcon->DrawIndexedInstanced((*it).indexCount, instanceCount, (*it).startIndex, 0, 0);
        }
    }

这里调用绘图函数(上面):我传递实例缓冲区(map(int,ID3D11Buffer *)和实例编号)

(*it).second->draw(0.0f, 0.0f, 0.0f, 0, instanceBufferMap[typeId], instanceCount[typeId]);

shader.hlsl

struct VIn
{
float4 position : POSITION;
float3 normal : NORMAL;
float2 texcoord : TEXCOORD;
//row_major float4x4 instTrans : INSTTRANS;
float4 instTrans : INSTTRANS;
uint instanceID : SV_InstanceID;
};



VOut VShader(VIn input)
{
VOut output;

//first: transforming instance
//output.position = mul(input.instTrans, input.position);
output.position = input.position;
output.position.xyz *= 50.0; //scale
output.position.z += input.instTrans.z; //apply only z value

float4 transPos = mul(world, output.position); //transform position with world matrix

output.position = mul(view, transPos);  //project to screen

最后一个文件中的“input.instTrans”不正确并包含ramdom数据。 你有什么想法吗?

1 个答案:

答案 0 :(得分:0)

所以我发现了这个错误,它位于一个完全意想不到的位置...... 所以这是代码片段:

ID3D10Blob *VS, *VS2, *PS, *PS2; //<- i only used VS and PS before

//volume shader
if (FAILED(D3DX11CompileFromFile(L"resources/volume.hlsl", 0, 0, "VShader", "vs_5_0", D3D10_SHADER_PREFER_FLOW_CONTROL | D3D10_SHADER_SKIP_OPTIMIZATION, 0, 0, &VS, 0, 0))) throw(std::string("Volume Shader Error 1"));
if (FAILED(D3DX11CompileFromFile(L"resources/volume.hlsl", 0, 0, "PShader", "ps_5_0", D3D10_SHADER_PREFER_FLOW_CONTROL | D3D10_SHADER_SKIP_OPTIMIZATION, 0, 0, &PS, 0, 0))) throw(std::string("Volume Shader Error 2"));
// encapsulate both shaders into shader objects
if (FAILED(d3ddev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pvolumeVS))) throw(std::string("Volume Shader Error 1A"));
if (FAILED(d3ddev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pvolumePS))) throw(std::string("Volume Shader Error 2A"));

//sky shader
if (FAILED(D3DX11CompileFromFile(L"resources/sky.hlsl", 0, 0, "VShader", "vs_5_0", D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, 0, &VS2, 0, 0))) throw(std::string("Sky Shader Error 1"));
if (FAILED(D3DX11CompileFromFile(L"resources/sky.hlsl", 0, 0, "PShader", "ps_5_0", D3D10_SHADER_OPTIMIZATION_LEVEL3, 0, 0, &PS2, 0, 0))) throw(std::string("Sky Shader Error 2"));
// encapsulate both shaders into shader objects
if (FAILED(d3ddev->CreateVertexShader(VS2->GetBufferPointer(), VS2->GetBufferSize(), NULL, &pskyVS))) throw(std::string("Sky Shader Error 1A"));
if (FAILED(d3ddev->CreatePixelShader(PS2->GetBufferPointer(), PS2->GetBufferSize(), NULL, &pskyPS))) throw(std::string("Sky Shader Error 2A"));

使用两个缓冲区来编译着色器解决了这个问题,虽然我不知道为什么。谢谢你的支持,但是;)