DirectX12 Line Geometry Shader

Anonymous
2020-08-29T21:37:55.863+00:00

I created a desktop application for win32 based off a skeleton from the book I have Introduction to 3D Game Programming with Directx12 by Frank D Luna. class BoxApp : public D3DApp { public: BoxApp(HINSTANCE hInstance); BoxApp(const BoxApp& rhs) = delete; BoxApp& operator=(const BoxApp& rhs) = delete; ~BoxApp(); virtual bool Initialize()override; private: virtual void OnResize()override; virtual void Update(const GameTimer& gt)override; virtual void Draw(const GameTimer& gt)override; virtual void OnMouseDown(WPARAM btnState, int x, int y)override; virtual void OnMouseUp(WPARAM btnState, int x, int y)override; virtual void OnMouseMove(WPARAM btnState, int x, int y)override; void BuildDescriptorHeaps(); void BuildConstantBuffers(); void BuildRootSignature(); void BuildShadersAndInputLayout(); void BuildBoxGeometry(); void BuildPSO(); private: ComPtr<ID3D12RootSignature> mRootSignature = nullptr; ComPtr<ID3D12DescriptorHeap> mCbvHeap = nullptr; std::unique_ptr<UploadBuffer<ObjectConstants>> mObjectCB = nullptr; std::unique_ptr<MeshGeometry> mBoxGeo = nullptr; ComPtr<ID3DBlob> mvsByteCode = nullptr; ComPtr<ID3DBlob> mpsByteCode = nullptr; ComPtr<ID3DBlob> mgsByteCode = nullptr; std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout; ComPtr<ID3D12PipelineState> mPSO = nullptr; XMFLOAT4X4 mWorld = MathHelper::Identity4x4(); XMFLOAT4X4 mView = MathHelper::Identity4x4(); XMFLOAT4X4 mProj = MathHelper::Identity4x4(); float mTheta = 1.5f * XM_PI; float mPhi = XM_PIDIV4; float mRadius = 5.0f; POINT mLastMousePos; }; I found that to get started with lines that all I needed to do was change the topology to a line list topology in the draw function: void BoxApp::Draw(const GameTimer& gt) { ThrowIfFailed(mDirectCmdListAlloc->Reset()); ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), mPSO.Get())); mCommandList->RSSetViewports(1, &mScreenViewport); mCommandList->RSSetScissorRects(1, &mScissorRect); mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET)); mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr); mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr); mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView()); ID3D12DescriptorHeap* descriptorHeaps[] = { mCbvHeap.Get() }; mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps); mCommandList->SetGraphicsRootSignature(mRootSignature.Get()); mCommandList->IASetVertexBuffers(0, 1, &mBoxGeo->VertexBufferView()); mCommandList->IASetIndexBuffer(&mBoxGeo->IndexBufferView()); mCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINESTRIP); mCommandList->SetGraphicsRootDescriptorTable(0, mCbvHeap->GetGPUDescriptorHandleForHeapStart()); mCommandList->DrawIndexedInstanced( mBoxGeo->DrawArgs["box"].IndexCount, 1, 0, 0, 0); mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT)); ThrowIfFailed(mCommandList->Close()); ID3D12CommandList* cmdsLists[] = { mCommandList.Get() }; mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists); ThrowIfFailed(mSwapChain->Present(0, 0)); mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount; FlushCommandQueue(); } It works! Lines are drawn: ![21364-capture002.png][1] I know that I would like to set up a geometry shader for enumerating line vertices: void BoxApp::BuildShadersAndInputLayout() { HRESULT hr = S_OK; mvsByteCode = d3dUtil::CompileShader(L"VertexShader.hlsl", nullptr, "main", "vs_5_0"); mpsByteCode = d3dUtil::CompileShader(L"PixelShader.hlsl", nullptr, "main", "ps_5_0"); mgsByteCode = d3dUtil::CompileShader(L"GeometryShader.hlsl", nullptr, "main", "gs_5_0"); mInputLayout = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } }; } It seems to compile still at this point and start up.... When it comes time to load the pipline state the win32 application has some trouble: void BoxApp::BuildPSO() { D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc; ZeroMemory(&psoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC)); psoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() }; psoDesc.pRootSignature = mRootSignature.Get(); psoDesc.VS ={reinterpret_cast<BYTE*>(mvsByteCode->GetBufferPointer()),mvsByteCode->GetBufferSize()}; psoDesc.PS ={reinterpret_cast<BYTE*>(mpsByteCode->GetBufferPointer()),mpsByteCode->GetBufferSize()}; psoDesc.GS ={reinterpret_cast<BYTE*>(mgsByteCode->GetBufferPointer()),mgsByteCode->GetBufferSize()}; psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); psoDesc.SampleMask = UINT_MAX; psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; psoDesc.NumRenderTargets = 1; psoDesc.RTVFormats[0] = mBackBufferFormat; psoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1; psoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0; psoDesc.DSVFormat = mDepthStencilFormat; ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&mPSO))); } struct GSOutput { float4 pos : SV_POSITION; }; [maxvertexcount(3)] void main(line float4 input[2] : SV_POSITION, inout TriangleStream<GSOutput> output) { int i = 0; } ![21277-capture001.png][2] [1]: /api/attachments/21364-capture002.png?platform=QnA [2]: /api/attachments/21277-capture001.png?platform=QnA I don't yet know why the geometry shader isn't accepted by the pipline or why the app doesn't seem to start up after attaching the geometry shader to the pipeline. What I would like to have happen is to use the geometry shader to look at three vertices at a time from a line list topology and project some new points to output quads or triangles to that will represent thick lines drawn on the viewing plane (An orthographiclh just large enough to look at the cube) so that I can adjust the line thickness as needed. Is it known why the geometry shader isn't being accepted and how to go about drawing some lines on the viewing plane of the orthographiclh I have set up? Thank You!

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,690 questions
0 comments No comments
{count} votes

Accepted answer
  1. Anonymous
    2020-08-30T12:39:38.3+00:00
    [maxvertexcount(3)]
    void main(line float4 gin[2] : SV_POSITION, inout TriangleStream<GeoOut> output)
    {
        GeoOut a = (GeoOut)0;
        a.PosH = gin[0];
        output.Append(a);
        a.PosH = a.PosH - .1;
        output.Append(a);
        GeoOut b = (GeoOut)0;
        b.PosH = gin[1];
        output.Append(b);
        b.PosH = b.PosH - .1;
        output.Append(b);
    }
    

    I got some rudimentary triangles to come out sufficiently enough to answer the question. In order for it to work the vertex shader has to be modified to output float4 for an ortho view about 10 units wide +-r(aspectratio).

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.