1
$\begingroup$

Some possible things that might be the issue and could be explained by someone who is knowledgeable

  • Order of my indices, In all I've read, your array of indices for a triangle list is just clockwise order, see below how I ordered it for proof. EDIT - I have changed my indices according to Jason Allen's comment, no change
  • Keep in mind that my code runs fine, no errors, no warnings(that I know of) related to my issue.
  • Can these warnings be an issue?

enter image description here

I have been banging my head over this issue for far too long. I know the answer is going to be ridiculously simple but somehow it has successfully evaded me.

I've been implementing deferred rendering into my engine and my second pass, the one that actually renders to the swap chain buffer, is staying black (or whatever color I clear it to before rendering).

Now I know the issue has nothing to do with anything associated with the first pass/gBuffer because I am completely bypassing that part, literally commented out the call to it in the game loop.

My 2nd Pass Deferred Vertex Shader is as follows...

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

My 2nd Pass Pixel Shader is as follows... I have omitted the actual lighting code because it is all commented out until I fix the issue.

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

As you can see I am not doing anything related to lighting or anything, all I'm trying to do is set every pixel to white, I want to see it work.

Here is my renderSecondPass function. this is what I call every frame. Irrelevant code has been omitted.

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

 }

Here is the Input Layout...

 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 }
 };

Creation of the Input Layouts and Loading of the shaders themselves from file. Irrelevant code has been omitted.

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;
}

The Vertex and Index Buffer were created using the following...

 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;

}

I thought the issue was here. Since my Vertex Shader is feeding the Rasterizer data directly, the Vertex Shader has to output SV_Position in Clip Space. Wouldn't the coordinates I've made for my vertices be correct for a quad composed of 2 triangles that would take up the entire screen? (I've tried changing the z values, no change)

Here is resizeSwapChain, I've been bulding/rebuild the viewport in here. This function is called at initialization and whenever the window size changes after the window adjustment has been released (WM_EXITSIZEMOVE). Irrelevant code has been omitted.

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

Here is my D3D11 Initialization function, this is where I create my Rasterization states. Irrelevant code has been omitted.

 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;
 }

If anyone needs more info, just ask. Thanks

$\endgroup$
  • $\begingroup$ Everything looks ok. Bugs like these are the worst. :( Your quad coordinates are ok. DX Clip space is from (-1.0, 1.0). 2 suggestions: First, enable a debug Device using D3D11_CREATE_DEVICE_DEBUG. And see if anything interesting pops up in the output. Second, try capturing a frame in RenderDoc: github.com/baldurk/renderdoc Look at the call graph and see if anything is fishy. $\endgroup$ – RichieSams Feb 25 '16 at 23:28
  • $\begingroup$ Have you tried temporarily turning off back-face culling (D3D11_CULL_NONE instead of D3D11_CULL_BACK) to see if there's a winding order problem? $\endgroup$ – Nathan Reed Feb 26 '16 at 4:00
  • $\begingroup$ just did, didn't work $\endgroup$ – phatgreen Feb 26 '16 at 4:04
  • $\begingroup$ I posted a picture, could those warnings be causing an issue? $\endgroup$ – phatgreen Feb 26 '16 at 12:18
3
$\begingroup$

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.

$\endgroup$
  • $\begingroup$ Jason Allen is also correct. You will need to do both to get your program rendering. $\endgroup$ – icStatic Feb 26 '16 at 0:25
  • $\begingroup$ I added more code that is in my project. My D3D11 Initialization and my swap chain resize. Initialization creates rasterization states and also sets one of them. Swap chain makes/remakes the viewport according to screen current size. $\endgroup$ – phatgreen Feb 26 '16 at 1:42
  • $\begingroup$ I posted a picture, could those warnings be causing an issue? $\endgroup$ – phatgreen Feb 26 '16 at 12:18
2
$\begingroup$

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.

$\endgroup$
1
$\begingroup$

Your indices are wrong, they should start at 0.

Correct indices:

unsigned int quadIndices[] =
{   0, 1, 2,
    2, 1, 3 };
$\endgroup$
  • $\begingroup$ Fixed it, no change. See my comment on icStatic's answer $\endgroup$ – phatgreen Feb 26 '16 at 1:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.