일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- vertex
- RenderTargetView
- 코딩
- 다중표본화
- 다이렉트X 튜토리얼
- 프로그래밍
- engine
- 동기화
- UE4
- CommandList
- 전처리문
- View
- DirectXTK
- 게임수학
- C++
- DESC
- 다이렉트X
- DirectX
- Direct3D
- C언어
- c
- 다이렉트 초기화
- Direct Init
- DirectX12
- Input Assembler
- GPU
- Direct3D Init
- swapchain
- CPU
- 세팅
- Today
- Total
비타Cpp
Direct3D 초기화 예제 본문
지금 까지 만들어진 응용 프로그램 프레임워크를 이용하여 간단한 예제프로그램을 만들어 보자. 이 프로그램의 주된 기능은 부모 클래스인 D3DApp이 대부분 담당하기 때문에 이 예제만의 특별한 코드는 거의 없다.
#include "../../_Common/d3dApp.h"
class InitDirect3DApp : public D3DApp
{
public:
InitDirect3DApp(HINSTANCE hInstance);
~InitDirect3DApp();
virtual bool Initialize()override;
private:
virtual void OnResize()override;
virtual void Update(const GameTimer& gt)override;
virtual void Draw(const GameTimer& gt)override;
};
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE prevInstance,
PSTR cmdLine,
int showCmd)
{
//디버그 빌드에서는 실행시점 메모리 점검 기능을 켠다.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
try
{
InitDirect3DApp theApp(hInstance);
if (!theApp.Initialize())
return 0;
return theApp.Run();
}
catch (DxException& e)
{
MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
return 0;
}
}
InitDirect3DApp::InitDirect3DApp(HINSTANCE hInstance)
:D3DApp(hInstance)
{
}
InitDirect3DApp::~InitDirect3DApp()
{
}
bool InitDirect3DApp::Initialize()
{
if (!D3DApp::Initialize())
return false;
return true;
}
void InitDirect3DApp::OnResize()
{
D3DApp::OnResize();
}
void InitDirect3DApp::Update(const GameTimer& gt)
{
}
void InitDirect3DApp::Draw(const GameTimer& gt)
{
//명령 기록에 관련된 메모리의 재활용을 위해 명령 할당자를 재설정 한다.
//재설정은 GPU가 관련 명령 목록들을 모두 처리한 후에 일어난다.
ThrowIfFailed(mDirectCmdListAlloc->Reset());
//명령 목록을 ExecuteCommandList를 통해서 명령 대기열에 추가 했다면 명령 목록을 재설정 할 수 있다.
//명령 목록을 재설정하면 메모리가 재활용된다.
ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
//리소스 용도에 관련된 상태전이를 Direct3D에 통지한다.
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_RENDER_TARGET));
//뷰포트와 시저렉트를 설정한다.
//명령 목록을 재설정할 때마다 이들도 재설정해야 한다.
mCommandList->RSSetViewports(1, &mScreenViewport);
mCommandList->RSSetScissorRects(1, &mScissorRect);
//후면버퍼와 깊이버퍼를 지운다.
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());
//자원 용도에 관련된 상태 전이를 Direct3D에 알린다.
mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATES::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();
}
위의 코드에서 새로운 메서드들을 살펴보자.
ClearRenderTargetView 메서드는 지정된 렌더 대상을 지정된 색으로 지우고, ClearDepthStencilView는 지정된 깊이·스텐실 버퍼를 지운다. 이 응용프로그램은 업데이트되는 매 프레임마다 Clear명령으로 지운후 Draw명령을 수행한다.
void ClearRenderTargetView(
[in] D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetView,
[in] const FLOAT [4] ColorRGBA,
[in] UINT NumRects,
[in] const D3D12_RECT *pRects
);
1. RenderTargetView : 지울 렌더 대상을 서술하는 RTV.
2. ColorRGBA : 렌더 대상을 지우는데 사용할 색상.
3. NumRects : pRects 배열의 원소 개수, pRects가 널 포인터면 0을 지정하면 된다.
4. pRects : 렌더 대상에서 지울 직사각 영역들을 나타내는 D3D12_RECT들의 배열. 렌더 대상 전체를 지우고 싶으면 nullptr를 지정하면 된다.
void ClearDepthStencilView(
[in] D3D12_CPU_DESCRIPTOR_HANDLE DepthStencilView,
[in] D3D12_CLEAR_FLAGS ClearFlags,
[in] FLOAT Depth,
[in] UINT8 Stencil,
[in] UINT NumRects,
[in] const D3D12_RECT *pRects
);
1. DepthStencilView : 지울 깊이·스텐실 버퍼를 서술하는 DSV.
2. ClearFlags : 깊이·스텐실 버퍼중 지우고자 하는 요소(깊이 값 또는 스텐실 값)들을 나타내는 플래그. D3D12_CLEAR_FLAG_DEPTH나 D3D12_CLEAR_FLAG_STENCIL 또는 그둘을 비트별 OR(논리합)로 결합한 값을 지정하면 된다.
3. Depth : 깊이 버퍼를 지우는데 사용할 깊이값.
4. Stencil : 스텐실 버퍼를 지우는 데 사용할 스텐실 값.
5. NumRects : pRects 배열의 원소 개수. pRects가 널 포인터면 0을 지정하면 된다.
6. pRects : 깊이·스텐실 버퍼에서 지울 직사각 영역들을 나타내는 D3D12_RECT들의 배열. 깊이·스텐실 버퍼 전체를 지우고 싶으면 nullptr를 지정하면 된다.
또 다른 새 메서드는 ID3D12GraphicsCommandList::OMSetRenderTargets이다. 이 메서드는 렌더링에 사용할 렌더 대상과 깊이·스텐실 버퍼를 파이프라인에 묶는다. 일단 지금은 현재 후면 버퍼 하나와 주 깊이·스텐실 버퍼 하나를 각각 렌더 대상과 깊이·스텐실 버퍼로 지정하지만, 이후에는 여러 개의 렌더 대상을 활용 하는 기법들도 나올것이다.
void OMSetRenderTargets(
[in] UINT NumRenderTargetDescriptors,
[in, optional] const D3D12_CPU_DESCRIPTOR_HANDLE *pRenderTargetDescriptors,
[in] BOOL RTsSingleHandleToDescriptorRange,
[in, optional] const D3D12_CPU_DESCRIPTOR_HANDLE *pDepthStencilDescriptor
);
1. NumRenderTargetDescriptors : 파이프라인에 묶을 렌더 대상들을 서술하는 RTV들의 개수, 일부 고급 기법은 동시에 여러 개의 렌더 대상을 사용한다.
2. pRenderTargetDescriptors 파이프라인에 묶을 렌더 대상들을 서술하는 RTV들의 배열을 가리키는 포인터.
3. RTsSingleHandleToDescriptorRange : 앞의 배열의 모든 RTV가 서술자 힙 안에 연속적으로 저장되어 있으면 true, 그렇지 않으면 false를 지정한다.
4. pDepthStencilDescriptor : 파이프라인에 묶을 깊이·스텐실 버퍼를 서술하는 DSV를 가리키는 포인터.
마지막으로, IDXGISwapChain::Present 메서드는 후면 버퍼와 전면 버퍼를 교환한다.
'DirectX12 > 튜토리얼' 카테고리의 다른 글
정점 버퍼(Vertex Buffer) (0) | 2021.12.12 |
---|---|
Direct3D 정점(Vertex) 입력과 배치 (0) | 2021.12.05 |
메시지 처리부(Message Proc) (0) | 2021.12.04 |
FPS : Frames Per Second(초당 프레임 수) (0) | 2021.10.16 |
Direct3D Base 클래스 - D3DApp (0) | 2021.10.16 |