简体   繁体   English

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

[英]DX11 C++ Shader can't receive Instance Buffer content

i would like to draw Instances of an obj File. 我想画一个obj文件的实例。 After i implemented the Instancing instead of drawing each Object by his own draw() function (which worked just fine), the Instances are not positioned correctly. 在我实现实例化而不是通过自己的draw()函数绘制每个Object(效果很好)之后,实例的位置就不正确。 Probably the data from the InstanceBuffer is not set in the shader correctly. 可能来自InstanceBuffer的数据未在着色器中正确设置。

D3DMain.cpp - creating input layout 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 - setting up instance buffer 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 - drawing .obj file 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);
        }
    }

the drawing function (above) is called here: I pass the instance buffer (map(int, ID3D11Buffer*) and the instance numbers) 在这里调用绘图函数(上面):我传递实例缓冲区(map(int,ID3D11Buffer *)和实例编号)

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

shader.hlsl 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

the "input.instTrans" in the last file is incorrect and contains ramdom data. 最后一个文件中的“ input.instTrans”不正确,并且包含随机数据。 Do you have any ideas? 你有什么想法?

So i found the bug, it was at an totally unexpected location... So here is the code snippet: 所以我发现了这个错误,它位于一个完全意外的位置...所以这是代码片段:

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

Using two buffers for compiling the shaders solved the problem, though i have no idea why. 尽管我不知道为什么,但是使用两个缓冲区来编译着色器解决了这个问题。 Thank you for the support, though ;) 不过谢谢您的支持;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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