2014-01-20 90 views
0

我想畫一個obj文件的實例。在我實現Instancing而不是通過自己的draw()函數繪製每個對象(工作得很好)之後,Instances定位不正確。可能來自InstanceBuffer的數據未正確設置在着色器中。DX11 C++着色器無法接收實例緩衝區內容

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數據。 你有什麼想法嗎?

+0

沒有什麼突出顯然是錯誤的。我想到的一個問題是,D3D11_APPEND_ALIGNED_ELEMENT可能不適用於多個頂點流,也許它不會像您所期望的那樣將INSTTRANS元素的偏移量設置爲0,16,32,48。 另一件嘗試將通過一個單一的float4(不是一個矩陣),只是嘗試和翻譯工作,然後移動到整個矩陣與規模英寸 –

+0

我試圖通過只是翻譯向量,只適用於x分量到頂點位置。我也將'D3D11_APPEND_ALIGNED_ELEMENT'更改爲手動偏移。這就是調整之後的樣子:有趣的是,當相機移動時,這個「條」的長度會發生變化。 是否有可能通過多個函數傳遞實例緩衝區作爲參數造成任何損害? – cbacon

+0

您是否使用PIX For Windows,VS2012/2013的Pro +版本,AMD GPU PerfStudio,Nvidia nSight或Intel GPA內置的圖形調試器?他們都應該能夠向您展示頂點緩衝區,並告訴您錯誤的位置。 或者,如果您可以提供可執行文件或可編譯/可運行的項目,那麼我們可能有更好的機會進入它的底部。 –

回答

0

所以我發現的bug,它是在完全出乎意料的位置... 因此,這裏的代碼片段:

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

使用兩個緩衝區用於編譯着色器解決了這個問題,但我沒有想法爲什麼。謝謝你的支持,雖然;)

相關問題