查找簡單的2D DirecX11 / HLSL問題


1

一些可能的問題,可能是有知識的人解釋的

  • 我的索引順序,在我已經閱讀的所有文章中,三角形列表的索引陣列只是順時針方向,請參見下面我如何對其進行排序以進行證明。編輯-我已根據傑森·艾倫的評論更改了索引,沒有變化
  • 請記住,我的代碼運行正常,沒有錯誤,沒有與我的問題相關的警告(我知道)。
  • 這些警告會成為問題嗎?

enter image description here

我在這個問題上的努力已經太久了。我知道答案將非常簡單,但是以某種方式成功地使我逃避了。

我一直在我的引擎中實現延遲渲染,而第二遍,實際上是渲染到交換鏈緩衝區的第二遍,則保持黑色(或渲染前我清除為任何顏色)。

現在我知道該問題與與第一次pass / gBuffer相關的任何事情都不相關,因為我完全繞過了該部分,從字面上註釋掉了遊戲循環中對它的調用。

我的第二遍遞延頂點著色器如下...

float4 main( float4 pos : POSITION ) : SV_POSITION
{
     return pos;
}

我的第二遍像素著色器如下...我已省略了實際的照明代碼,因為在解決問題之前,所有照明代碼都已被註釋掉。

 float4 main(in float4 screenPos : SV_Position) : SV_Target
 {
     return float4(1.0f,1.0f,1.0f, 1.0f);
 }

如您所見,我沒有做任何與照明有關的事情或其他任何事情,我想做的就是將每個像素都設置為白色,我希望它能正常工作。

這是我的renderSecondPass函數。這就是我所說的每一幀。無關的代碼已被省略。

 void DirectX::renderSecondPass()
 {
 nullShaders();

 d3d11DeviceContext->VSSetShader(deferredVertexShader, NULL, 0);
 d3d11DeviceContext->PSSetShader(deferredPixelShader, NULL, 0);

 HRESULT hr;
 float clear[] = { 1.0, 0.5, 0.0, 1.0 };

 d3d11DeviceContext->OMSetRenderTargets(1, &d3d11RenderTargetView, NULL);
 d3d11DeviceContext->ClearRenderTargetView(d3d11RenderTargetView, clear);

 d3d11DeviceContext->IASetInputLayout(InputLayout::Deferred);
 d3d11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);


 for (unsigned int i = 0; i < lightBuffer.size(); i++)
 {
    UINT stride = sizeof(Vertex::Deferred);
    UINT offset = 0;

    d3d11DeviceContext->IASetVertexBuffers(0, 1, &deferredQuadVB, &stride, &offset);
    d3d11DeviceContext->IASetIndexBuffer(deferredQuadIB, DXGI_FORMAT_R32_UINT, 0);

    d3d11DeviceContext->DrawIndexed(deferredQuadIndiceCount, 0, 0);
 }

 hr = swapChain->Present(0, 0);

 if (FAILED(hr))
 {
     MessageBox(0, L"Swap Chain Present Error.", 0, 0);
 }

 }

這是輸入佈局...

 namespace Vertex
 {
     struct Deferred
     {
         VECTOR<float> Position;
         float Position_W;
     };
 }
 // C++ side above 

 // Shaderside below
 namespace InputLayout
 {
     static ID3D11InputLayout* Deferred;
 }

 const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC[] =
 {
     { "POSITION",  0, DXGI_FORMAT_R32G32B32A32_FLOAT,  0, 0,   D3D11_INPUT_PER_VERTEX_DATA, 0 }
 };

創建輸入佈局,並從文件中加載著色器本身。無關的代碼已被省略。

bool DirectX::initShaders()
{
std::vector<char> shaderBuffer;
std::string filename;
HRESULT hr;

// deferredVS
filename = "Shaders\\deferredVS.cso";
if (!shaderFileToMemory(filename, shaderBuffer))
{
    MessageBox(0, L"Load defaultVS Shader Into Memory Error.", 0, 0);
    return false;
}
hr = d3d11Device->CreateVertexShader(&shaderBuffer[0], shaderBuffer.size(), NULL, &deferredVertexShader);
hr = d3d11Device->CreateInputLayout(InputLayoutDesc::DEFERRED_VS_INPUTLAYOUT_DESC, 1, &shaderBuffer[0], shaderBuffer.size(), &InputLayout::Deferred);

// deferredPS
filename = "Shaders\\deferredPS.cso";
if (!shaderFileToMemory(filename, shaderBuffer))
{
    MessageBox(0, L"Load deferredPS Shader Into Memory Error.", 0, 0);
    return false;
}
hr = d3d11Device->CreatePixelShader(&shaderBuffer[0], shaderBuffer.size(), NULL, &deferredPixelShader);

return true;
}

頂點和索引緩衝區是使用以下...創建的。

 bool DirectX::initDeferredQuad()
 {
std::vector<Vertex::Deferred> deferredQuadVertices;
std::vector<unsigned int> deferredQuadIndices;

Vertex::Deferred quadVertices[4];
Vertex::Deferred quadVertice;

quadVertice.Position_W  = 1.0;
quadVertice.Position = VECTOR<float>(-1.0, 1.0, 0.0);
quadVertices[0] = quadVertice;
quadVertice.Position = VECTOR<float>(1.0, 1.0, 0.0);
quadVertices[1] = quadVertice;
quadVertice.Position = VECTOR<float>(-1.0, -1.0, 0.0);
quadVertices[2] = quadVertice;
quadVertice.Position = VECTOR<float>(1.0, -1.0, 0.0);
quadVertices[3] = quadVertice;

D3D11_BUFFER_DESC vbd;
D3D11_SUBRESOURCE_DATA vinitData;
HRESULT hr;

vbd.Usage               = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth           = sizeof(Vertex::Deferred) * 4;
vbd.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags      = 0;
vbd.MiscFlags           = 0;
vbd.StructureByteStride = 0;

vinitData.pSysMem       = &quadVertices;

hr = d3d11Device->CreateBuffer(&vbd, &vinitData, &deferredQuadVB);

if (FAILED(hr))
{
    MessageBox(0, L"Quad Vertex Buffer Creation Error.", 0, 0);
    return false;
}

unsigned int quadIndices[] =
{   0, 1, 2,
    2, 1, 3 };

deferredQuadIndiceCount = 6;

D3D11_BUFFER_DESC ibd;
D3D11_SUBRESOURCE_DATA iinitData;

ibd.Usage               = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth           = sizeof(unsigned int) * 6;
ibd.BindFlags           = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags      = 0;
ibd.MiscFlags           = 0;

iinitData.pSysMem       = &deferredQuadIndices;

hr = d3d11Device->CreateBuffer(&ibd, &iinitData, &deferredQuadIB);

if (FAILED(hr))
{
    MessageBox(0, L"QuadIndex Buffer Creation Error.", 0, 0);
    return false;
}

return true;

}

我認為問題出在這裡。由於我的頂點著色器直接輸入了柵格化器數據,因此頂點著色器必須在Clip Space中輸出SV_Position。我為頂點製作的坐標對於由佔據整個屏幕的2個三角形組成的四邊形是否正確?(我嘗試過更改z值,沒有更改)

這裡是resizeSwapChain,我一直在這裡構建/重建視口。在初始化時以及釋放窗口調整後每當窗口大小改變時,都會調用此函數(WM_EXITSIZEMOVE)。無關的代碼已被省略。

 void DirectX::resizeSwapChain()
 {
const unsigned int clientWidth = uClient->getAppScreenWidth();
const unsigned int clientHeight = uClient->getAppScreenHeight();
HRESULT hr;

if (!(d3d11RenderTargetView == NULL))
{
    d3d11RenderTargetView->Release();
    d3d11RenderTargetView = 0;
}

if (!(d3d11DepthStencilView) == NULL)
{
    d3d11DepthStencilView->Release();
    d3d11DepthStencilView = 0;
}

if (!(d3d11StencilBuffer) == NULL)
{
    d3d11StencilBuffer->Release();
    d3d11StencilBuffer = 0;
}

hr = swapChain->ResizeBuffers(1, clientWidth, clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);

ID3D11Texture2D* backBuffer;

hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer));

hr = d3d11Device->CreateRenderTargetView(backBuffer, 0, &d3d11RenderTargetView);

backBuffer->Release();
backBuffer = 0;

D3D11_TEXTURE2D_DESC depthStencilDesc;

depthStencilDesc.Width = clientWidth;
depthStencilDesc.Height = clientHeight;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;

if (msaaEnabled)
{
    depthStencilDesc.SampleDesc.Count = 4;
    depthStencilDesc.SampleDesc.Quality = msaaQuality - 1;
}
else
{
    depthStencilDesc.SampleDesc.Count = 1;
    depthStencilDesc.SampleDesc.Quality = 0;
}

depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;

hr = d3d11Device->CreateTexture2D(&depthStencilDesc, 0, &d3d11StencilBuffer);

hr = d3d11Device->CreateDepthStencilView(d3d11StencilBuffer, 0, &d3d11DepthStencilView);

d3d11ScreenViewport.TopLeftX = 0;
d3d11ScreenViewport.TopLeftY = 0;
d3d11ScreenViewport.Width = static_cast<float>(clientWidth);
d3d11ScreenViewport.Height = static_cast<float>(clientHeight);
d3d11ScreenViewport.MinDepth = 0.0f;
d3d11ScreenViewport.MaxDepth = 1.0f;

d3d11DeviceContext->RSSetViewports(1, &d3d11ScreenViewport);

mainCamera->setProjectionMatrix(MATRIX4X4<float>::perspectiveFieldOfViewLeftHandMatrix(0.25 * GenericMath::PI, GenericMath::aspectRatio(clientWidth, clientHeight), 0.001, 1000.0));
 }

這是我的D3D11初始化函數,這是我創建柵格化狀態的地方。無關的代碼已被省略。

 bool DirectX::initDirectX()
 {
D3D_FEATURE_LEVEL featureLevel;

HRESULT hr = D3D11CreateDevice(NULL, driverType, NULL, NULL, NULL, 0, D3D11_SDK_VERSION, &d3d11Device, &featureLevel, &d3d11DeviceContext);

hr = d3d11Device->CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, 4, &msaaQuality);

DXGI_SWAP_CHAIN_DESC swapChainDesc;
swapChainDesc.BufferDesc.Width = uClient->getAppScreenWidth();
swapChainDesc.BufferDesc.Height = uClient->getAppScreenHeight();
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

if (msaaEnabled)
{
    swapChainDesc.SampleDesc.Count = 4;
    swapChainDesc.SampleDesc.Quality = msaaQuality - 1;
}
else
{
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
}

swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1;
swapChainDesc.OutputWindow = *windowsHandle;
swapChainDesc.Windowed = true;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = 0;

IDXGIDevice* dxgiDevice = 0;
hr = d3d11Device->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);

IDXGIAdapter* dxgiAdapter = 0;
hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter);

IDXGIFactory* dxgiFactory = 0;
hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory);

hr = dxgiFactory->CreateSwapChain(d3d11Device, &swapChainDesc, &swapChain);

dxgiDevice->Release();
dxgiDevice = 0;

dxgiAdapter->Release();
dxgiAdapter = 0;

dxgiFactory->Release();
dxgiFactory = 0;

resizeGBuffers();
resizeSwapChain();

D3D11_RASTERIZER_DESC rasterizerDesc;
ZeroMemory(&rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.CullMode = D3D11_CULL_BACK;
rasterizerDesc.FrontCounterClockwise = false;
rasterizerDesc.DepthClipEnable = true;

hr = d3d11Device->CreateRasterizerState( &rasterizerDesc, &d3d11SolidRS);\

ZeroMemory(&rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));

rasterizerDesc.FillMode = D3D11_FILL_WIREFRAME;
rasterizerDesc.CullMode = D3D11_CULL_BACK;
rasterizerDesc.FrontCounterClockwise = false;
rasterizerDesc.DepthClipEnable = true;

hr = d3d11Device->CreateRasterizerState( &rasterizerDesc, &d3d11WireframeRS);

d3d11DeviceContext->RSSetState(d3d11SolidRS);

return true;
 }

如果有人需要更多信息,請問。謝謝

1

Your indices are wrong, they should start at 0.

Correct indices:

unsigned int quadIndices[] =
{   0, 1, 2,
    2, 1, 3 };

3

You have not set a viewport with RSSetViewports. You need to set this to the pixel dimensions of your render target. Without this the viewport will be set to 0,0,0,0 meaning no pixels will be touched.

Additionally you have not set a raster state or blend state. It is good practice to set these and can be helpful early on to set the winding order in the raster state to not cull, this can come in handy if you are working out the vertex positions by hand.


2

I can't believe it has taken me this long to find this...

So the array I was giving the Index Buffer Desc that contains the data was the wrong one... It was a blank one that I forgot I didn't need, the vector if you look at the code.

enter image description here

Look at that garbage. Those are supposed to be the indices... Well at least I know how to use the debugger now, thanks guys got it working.