Drawing fullscreen triangle without vertex buffers

Started by
6 comments, last by Adam_42 9 years, 8 months ago

So I'm doing deferred shading and I need to draw a fullscreen quad/triangle in my vertex shader. I found this old topic (http://www.gamedev.net/topic/609917-full-screen-quad-without-vertex-buffer/) and used the vertex shader posted. For reference, here it is:


FullscreenTriangleVSOut main(uint VertexID: SV_VertexID)
{
    FullscreenTriangleVSOut output;

    output.mTexcoord = float2((VertexID << 1) & 2, VertexID & 2);
    output.mPosition = float4(output.mTexcoord * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);

    return output;
}

I then added the following simple pixel shader:


float4 main(FullscreenTriangleVSOut input) : SV_Target0
{
    return float4(1.0f, 0.0f, 0.0f, 0.0f);
}

I expected the whole window to be red, but it's just black.

Here's the other calls I'm doing to set this simple op up:


    void DX11RendererImpl::ShadingPass(const RenderQueue& renderQueue)
    {
        mContext->OMSetRenderTargets(1, &mBackbuffer, mDepthStencilView);
        mContext->OMSetDepthStencilState(mDepthStencilState, 1);

        mContext->ClearRenderTargetView(mBackbuffer, gClearColor);
        mContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

        // unbind all the buffers and input layout
        mContext->IASetVertexBuffers(0, 0, NULL, 0, 0);
        mContext->IASetVertexBuffers(1, 0, NULL, 0, 0);
        mContext->IASetIndexBuffer(NULL, DXGI_FORMAT_R32_UINT, 0);
        mContext->IASetInputLayout(NULL);

        // the fxaa vertex shader and above posted pixel shader
        mContext->VSSetShader(mVertexShader, NULL, NULL);
        mContext->PSSetShader(mPixelShader, NULL, NULL);
        
        mContext->Draw(3, 0);

        DXCALL(mSwapchain->Present(0, 0));
    }

Any ideas why this isn't drawing my whole screen in red?

Advertisement
  1. Is black your clear color?
  2. You return alpha of 0.0f, depending on blending settings which we cannot see your pixels might do nothing;
  3. Set correct primitive topology (TRIANGLESTRIP);
  4. You need to draw 4 vertices to make a quad, at the moment you have only 3;
  5. It doesn't seem you need depth buffer at all; don't bind it.

- fullscreen triangle needs only 3 vertices.

Check also:

- viewport

- blending operations

- rasterizer state / culling state

Cheers!

I experimented abit and it turns out I can draw it fine if I set D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST and draw 6 vertices. But surely 3 should suffice?

You only need 3. I use that vertex shader example all the time. However I don't see you setting your viewport in that code. Second, what does your VS output look like? I suggest setting a InputLayout that mimics it even though you only use the vertex ID. 3rd, you don't even need to bind a index buffer.

Finally, try setting the 4th value of your returned color in the pixel shader to 1.0f as that is your alpha channel if you are using one in your render target. Otherwise the quad may be completely transparent if you are doing alpha blending.

Come to think of it, I am using frontface = CCW, that might be the cause of it?


        D3D11_RASTERIZER_DESC rasterizerDesc;
        ZeroMemory(&rasterizerDesc, sizeof(D3D11_RASTERIZER_DESC));
        rasterizerDesc.FillMode = D3D11_FILL_SOLID;
        rasterizerDesc.CullMode = D3D11_CULL_BACK;
        rasterizerDesc.FrontCounterClockwise = true;
        rasterizerDesc.DepthClipEnable = true;
        rasterizerDesc.ScissorEnable = false;
        rasterizerDesc.MultisampleEnable = false;
        rasterizerDesc.AntialiasedLineEnable = false;
        DXCALL(mDevice->CreateRasterizerState(&rasterizerDesc, &mRasterizerState));

EDIT: I altered the vertex shader as follows:


FullscreenTriangleVSOut main(uint VertexID: SV_VertexID)
{
    FullscreenTriangleVSOut output;

    output.mTexcoord = float2((VertexID << 1) & 2, VertexID == 0);
    output.mPosition = float4(output.mTexcoord * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);

    return output;
}

The positions should now be:

[-1, -3]

[3, -1]

[-1, 1]

However, not the whole screen is red... this is how it looks:

image.jpg

As for the viewport, I think it is no problem. Like this:


D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = static_cast<float>(swapChainDesc.BufferDesc.Width);
viewport.Height = static_cast<float>(swapChainDesc.BufferDesc.Height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
mContext->RSSetViewports(1, &viewport);

EDIT: I fixed it, the vertex shader math was slightly wrong. Heres the more condensed version for CCW frontface rendering


float4 main(uint VertexID: SV_VertexID) : SV_POSITION
{
    return float4(float2(((VertexID << 1) & 2) * 2.0f, (VertexID == 0) * -4.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
}


The positions should now be:

[-1, -3]
[3, -1]
[-1, 1]

Those positions look wrong. Take a look at the diagram at http://www.altdev.co/2011/08/08/interesting-vertex-shader-trick/

This topic is closed to new replies.

Advertisement