지난 정리글 이후에 D3d 초기화 함수를 확인해보자
초반 도입부에서 가장 중요한 것들을 보면 디바이스, 디바이스컨텍스트, 스왑체인, 타겟뷰 등을 생성한다.

디바이스
아래 방식은 일단 지역변수로 Comptr 오브젝트를 생성하고 문제가 없다면 m_device 와 같은 멤버로 넣어주는 안전한 방식을 사용한다.
featureLevels 를 보면 원하는 버전을 몇가지 선택해둔다. 이제 디바이스를 만들 때 높은 버전부터 확인하며 호환 될 경우 안정적으로 객체를 생성한다. 따라서 실제 소프트웨어를 판매 할 때는 아래와 같이 작업하는 것이 안정적이다.

생성된 디바이스의 레벨이 다르다면 그 아랫단계로 다시 생성하거나 아래처럼 종료하는 형식으로 예외한다.

DX3D 에서는 MSAA( Multi-Sampling AA ) 를 제공한다. AA 는 주변 픽셀 값들을 이용해 부드럽게 처리하는 방식을 의미한다.
지원이 되는지 먼저 확인하고

스왑체인
아래와 같이 설정해주면 DX 는 자동으로 AA 를 적용해준다.
스왑 체인은 DXGI 에 준비되어 있다. 스왑 체인의 역할은 더블 버퍼링 형식을 지원한다. 프론트 버퍼와 백 버퍼를 사용해서 부드럽게 화면 전환이 가능하도록 만든다. 요즘은 트리플 버퍼링도 사용한다. 앞과 뒤를 나눌 수 도 있고 page 플립을 통한 버퍼링도 가능하다.

여기서는 컬러 하나를 표현할 때 32비트를 사용한다. 즉, 컬러 별로 사용할 메모리 크기를 설정하는 것이다. 그리고 UNORM 은 0~255 로 0~1 을 표현한다는 것이다.
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
이제 위에 설정한 스왑체인 형식을 실제 오브젝트로 생성한다.
이 함수는 디바이스와 콘텍스트까지 생성해준다. 만약 이미 디바이스를 만들어서 이 함수를 쓰기 싫으면

아래와 같이 팩토리를 이용해서 만들 수 있다. 다만, 타고타고타고타ㅣ고 가긴 한다....

렌더 타깃 뷰 생성
렌더 타깃 뷰는 실제 모니터에 보여질 화면을 설정한다. 기본적으로 스왑체인에서 모니터에 보여질 버퍼를 설정하지만, 개발 하다보면 스왑체인에서 관리하는 버퍼 외에도 렌더 타깃을 사용하는 경우가 더러 있기 때문에 렌더 타깃 뷰를 따로 관리한다.
ID3D11Texture2D 는 대략적으로는 컬러값들의 이차원배열로 저장된 메모리 정도로만 알고 있어도 괜찮다.
이 버퍼를 이용해 윈도우의 특정 영역만 렌더링 영역으로 설정 가능하다.

여기서 보면 뷰보트를 셋팅하는데 콘텍스트를 사용하는 것을 볼 수 있는데 콘텍스트는 생성된 오브젝트를 관리하는 역할을 한다.
그리고 RS 는 레스터라이제이션이다. 그래서 3차원 좌표를 2차원으로 확인하는 과정에 사용되어질 스크린뷰포트 를 설정하는 함수라고 생각 할 수 있겠다.(NDC 에서 화면 좌표)
m_context->RSSetViewports(1, &m_screenViewport);
그리고 실제 RS 도 설정 가능하다.
이렇게 DESC 를 설정하고 생성하면 된다. 여기서 와이어프레임 등의 렌더링 FillMode 를 설정할 수 있다.
그리고 컬링모드를 앞면 혹은 뒷면이 안보이게 등으로 바꿀 수 있고
FrointCounterClockwise 로 실제 그려질 부분이 시계방향일지 반시계일지 설정 가능하다.
// Create a rasterizer state
D3D11_RASTERIZER_DESC rastDesc;
ZeroMemory(&rastDesc, sizeof(D3D11_RASTERIZER_DESC)); // Need this
rastDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
// rastDesc.FillMode = D3D11_FILL_MODE::D3D11_FILL_WIREFRAME;
rastDesc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE;
rastDesc.FrontCounterClockwise = false;
m_device->CreateRasterizerState(&rastDesc, &m_rasterizerSate);
depth 버퍼
다음은 depth 버퍼 생성이다.
이때는 .Format 에서 버퍼의 크기를 설정하고 또 S8 과 같이 depth 스텐실의 크기까지 설정해둔다.
.Usage 는 cpu 와 gpu 가 텍스쳐의 접근 방식을 정할 수 있다. 이것으로 읽기 쓰기를 설정한다.
이제 m_device 를 이용해 2d 메모리를 생성 할 수 있다. gpu 의 메모리 공간을 받아 온 것을 의미한다.
이제 이 2d 메모리에 deptghStencil 버퍼를 depthStencilView 를 통해 사용하게 된다.
// Create depth buffer
D3D11_TEXTURE2D_DESC depthStencilBufferDesc;
depthStencilBufferDesc.Width = m_screenWidth;
depthStencilBufferDesc.Height = m_screenHeight;
depthStencilBufferDesc.MipLevels = 1;
depthStencilBufferDesc.ArraySize = 1;
depthStencilBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
if (numQualityLevels > 0) {
depthStencilBufferDesc.SampleDesc.Count = 4; // how many multisamples
depthStencilBufferDesc.SampleDesc.Quality = numQualityLevels - 1;
} else {
depthStencilBufferDesc.SampleDesc.Count = 1; // how many multisamples
depthStencilBufferDesc.SampleDesc.Quality = 0;
}
depthStencilBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilBufferDesc.CPUAccessFlags = 0;
depthStencilBufferDesc.MiscFlags = 0;
if (FAILED(m_device->CreateTexture2D(&depthStencilBufferDesc, 0,
m_depthStencilBuffer.GetAddressOf()))) {
cout << "CreateTexture2D() failed." << endl;
}
if (FAILED(
m_device->CreateDepthStencilView(m_depthStencilBuffer.Get(), 0, &m_depthStencilView))) {
cout << "CreateDepthStencilView() failed." << endl;
}
그리고 위의 m_depthStencilView 를 어떤 상태로 사용할지도 정해 줄 수 있는데 그것이 바로 state 이다.
이것도 DESC 로 형식만들고 Create 해준다. 여기서 depth 를 쓸지 말지 그리고 더 가까운 위치의 오브젝트를 그릴것인지 아님 안그릴지 등을 설정해준다.

'DX' 카테고리의 다른 글
| 모델 뷰 프로젝션 (MVP) 과 프로젝션 행렬 (0) | 2025.06.15 |
|---|---|
| D3D11 렌더링 파이프라인 (0) | 2025.06.15 |
| COM 과 D3D (0) | 2025.06.15 |
| DirectX Math (0) | 2025.06.06 |
| 조명, 노멀 벡터 변환 (GLM) (0) | 2025.06.06 |