본문 바로가기

DX

D3D11 초기화

지난 정리글 이후에 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