
위 내용에 맞춰 버텍스를 만들어보자. 인덱스는 생략함.
float stackheight = height / stackCount;
// 한 층 위의 더미로 올라 갈 때의 반지를 변화량
float radiusStep = (topRadius - bottomRadius) / stackCount;
uint32 ringCount = stackCount + 1;
for( uint32 i = 0; i < ringCount; ++i )
{
float y = - 0.5f + i * stackHeight;
float r = bottomRadius + i * radiusStep;
float dTheta = 2.0f * XM_PI/sliceCount;
for(uint32 j = 0; j <=sliceCount; ++j)
{
Vertex vertex;
float c = cosf(j*dTheta);
float s = sinf(j*dTheta);
vertex.Position = XMFLOAT3(r*c, y, r*s);
vertex.TangentU = XMFLOAT3(-s, 0.0f, c);
float dr = bottomRadius - topRadius;
XMFLOAT3 bitangent(dr*c, -height, dr*s);
XMVECTOR T = XMLoadFloat3(&vertex.TangentU);
XMVECTOR B = XMLoadFloat3(&bitangent);
XMVECTOR N = XMVertor3Normalize(XMVector3Cross(T,B));
}
}
위와 같이 정점을 구하고 인덱스를 찍었다면 배열에 담아 그림을 그려달라고 GPU에게 요청해야한다. DirectX12에서 GPU에게 요청하는 과정을 알아보자.
이전의 [Prev]CommandList를 CommandQueue(GPU가 실행하도록)에 제출하고 새롭게 그릴 명령들을 [New]CommandList에 담아 CommnadQueue에 제출하는 과정을 정리하고 이해해보자. 아래는 Draw의 과정을 단순하게 그림으로 나타내보았다.

1.ExecuteCommandList를 통해 커맨드 큐에 제출한 다음에 커맨드 리스트를 리셋할 수 있다.
2. 다시 GPU에 제출할 commandList를 생성하기 전에 리스트리 ID3D12GraphicsCommandList::Reset() 해준다.
3. commandList에 렌더링을 위한 과정 함수를 실행하여 리스트에 넣는다.
[ Command List 대표 함수 /* 순서 중요 */ ]
A : ID3D12GraphicsCommandList::RSSetViewports( 1, &D3D12_VIEWPORT )
B : ID3D12GraphicsCommandList::RSSetScissorRects( 1, & D3D12_RECT )
C : ID3D12GraphicsCommandList::ResourceBarrier (1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET));
리소스의 상태를 렌더링을 할 수 있도록 변경함. (리소스 상태를 장벽을 사용하여 동기화 함.)
* CD3DX12_RESOURCE_BARRIER::Transition
전환 장벽: 서로 다른 사용간에 전환함을 나타냄.
위 예제는 백 버퍼가 렌더링 대상으로 사용됨을 나타냄.
D : ID3D12GraphicsCommandList::ClearRenderTargetView( )
E : ID3D12GraphicsCommandList::ClearDepthStencilView( )
백 버퍼와 뎁스 버퍼를 클리어 함.
F : ID3D12GraphicsCommandList::OMSetRenderTargets( )
어디에 렌더링을 할지 설정함.
G : ID3D12GraphicsCommandList::SetDescriptorHeaps( )
H : ID3D12GraphicsCommandList::SetGraphicsRootSignature( )
I : ID3D12GraphicsCommandList::SetGraphicsRootDescriptorTable( )
********* Draw **********
ID3D12GraphicsCommandList::IASetVertexBuffers ( )
ID3D12GraphicsCommandList::IASetIndexBuffer ( )
ID3D12GraphicsCommandList::IASetPrimitiveTopology ( )
정점 자료를 이용하여 기하학적 기본 도형을 형성하는 방법을 설정해준다.
ID3D12GraphicsCommandList::SetGraphicsRootDescriptorTable ( )
ID3D12GraphicsCommandList::DrawIndexedInstanced ( )
***************************
G:ID3D12GraphicsCommandList::ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT));
리소스의 상태를 출력할 수 있도록 변경함.
4. commandList에 기록을 종료함.
ID3D12GraphicsCommandList::Close()
5. 커맨드 리스트의 실행을 위해 큐에 제출함.
6. 백 버퍼와 프론트 버퍼를 교체함. [스왑체인 swapchain]
7. 이 펜스 지점까지 커맨드들을 표시하기 위해 펜스 값을 증가함.
8. 새 펜스 지점을 설정하는 인스트럭션을 커맨드 큐에 추가함. GPU가 모든 커맨드들의 처리가 완료되기 전까지 Signal()을 처리하지 않음.
auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
ThrowIfFailed(cmdListAlloc->Reset());
if (mIsWireframe)
{
ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque_wireframe"].Get()));
}
else
{
ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].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());
int passCbvIndex = mPassCbvOffset + mCurrFrameResourceIndex;
auto passCbvHandle = CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvHeap->GetGPUDescriptorHandleForHeapStart());
passCbvHandle.Offset(passCbvIndex, mCbvSrvUavDescriptorSize);
mCommandList->SetGraphicsRootDescriptorTable(1, passCbvHandle);
DrawRenderItems(mCommandList.Get(), mOpaqueRitems);
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT));
ThrowIfFailed(mCommandList->Close());
ID3D12CommandList* cmdLists[] = {mCommandList.Get()};
mCommandQueue->ExecuteCommandLists(1, cmdLists);
ThrowIfFailed(mSwapChain->Present(0, 0));
mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
mCurrFrameResource->Fence = ++mCurrentFence;
mCommandQueue->Signal(mFence.Get(), mCurrentFence);

'🎯 game engine > ◽ directX12' 카테고리의 다른 글
[DirectX12] 큐브맵 만들기 / StructuredBuffer (0) | 2024.11.26 |
---|---|
[DirectX12] 스텐실(stencil) 거울 만들기 (0) | 2024.11.07 |
[DirectX12] 조명의 종류 (0) | 2023.12.19 |
[DirectX12] 조명 연산을 위한 법선 벡터, 법선 벡터의 변환 (0) | 2023.12.14 |
[DirectX12] Direct3D 초기화 과정, 그래픽 프로그래밍의 CPU와 GPU의 상호작용 (1) | 2023.12.06 |
안 하는 것 보다 낫겠지
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!