Software Development Kit
Windows Vista이후부터 사용
과거 CPU로 처리했던 Win API 대신 GPU를 통해 모든 Windows의 화면 출력
T&L(Transform and Light)를 하드웨어에서 강제로 처리
쉐이더 사용 가능
T&L 없음
개발자가 점 하나를 찍기위해서라도 쉐이더를 사용해야 함
쉐이더 5.0
MultiThread Rendering 강화
다만 개발 난이도가 높아서 많이 사용하지 않음
그래픽 카드가 DirectX의 다양한 기능 중, 무엇을 지원하는지 알려줌
DirectX의 기반
COM is a platform-independent, distributed, object-oriented system for creating binary software components that can interact.
COM objects can be created with a variety of programming languages.
IUnkown을 상속, 구현 필수
#pragma comment(lib, "d3d11.lib")
#include "Sample.h"
bool Sample::Init()
{
// 1)디바이스 생성
HRESULT hr;
D3D_FEATURE_LEVEL pFeatureLevel;
UINT Flags=0;
D3D_FEATURE_LEVEL pFeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
};
UINT FeatureLevels =1;
hr = D3D11CreateDevice(
nullptr, D3D_DRIVER_TYPE_HARDWARE,NULL,0, pFeatureLevels, 1, D3D11_SDK_VERSION,
&m_pd3dDevice,// 디바이스 객체
&pFeatureLevel,
&m_pImmediateContext
);
if (FAILED(hr))
{
return false;
}
// 2)팩토리 생성
hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&m_pGIFactory);
if (FAILED(hr)) return false;
if (m_pd3dDevice == NULL) return E_FAIL;
// 3)스왑체인 생성
// 후면(백)버퍼 생성 -> 전면버퍼
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory(&sd, sizeof(sd));
sd.BufferCount = 1;
sd.BufferDesc.Width = m_rtClient.right;
sd.BufferDesc.Height = m_rtClient.bottom;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = m_hWnd;
sd.Windowed = true;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
hr = m_pGIFactory->CreateSwapChain(m_pd3dDevice,&sd,&m_pSwapChain);
if (FAILED(hr))
{
return false;
}
// 4)랜더타켓뷰 생성
ID3D11Texture2D* pBackBuffer = nullptr;
m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer );
m_pd3dDevice->CreateRenderTargetView(pBackBuffer , NULL, &m_pRTV);
pBackBuffer->Release();
// 5)뷰포트 설정
D3D11_VIEWPORT vp;
vp.Width = m_rtClient.right;
vp.Height = m_rtClient.bottom;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
// 굳이 설정하지 않아도 출력에는 문제 없음
m_pImmediateContext->RSSetViewports(1, &vp);
return true;
}
bool Sample::Frame()
{
return true;
}
bool Sample::Render()
{
static float fTimer = 0.0f;
fTimer += 0.0001f;
m_pImmediateContext->OMSetRenderTargets(1, &m_pRTV, NULL);
float color[4] = { cosf(fTimer)*0.5f+0.5f,
sinf(fTimer) * 0.5f + 0.5f,
cosf(fTimer*2) * 0.5f + 0.5f,
1.0f };
m_pImmediateContext->ClearRenderTargetView(m_pRTV, color);
m_pSwapChain->Present(0, 0);
return true;
}
bool Sample::Release()
{
if (m_pd3dDevice) m_pd3dDevice->Release();// 디바이스 객체
if (m_pImmediateContext)m_pImmediateContext->Release();
if (m_pGIFactory)m_pGIFactory->Release();
if (m_pSwapChain)m_pSwapChain->Release();
if (m_pRTV) m_pRTV->Release();
return true;
}
GAME_RUN(P2_CreateWidnow2, 1024, 768)
HRESULT WINAPI D3D11CreateDevice(
_In_opt_ IDXGIAdapter* pAdapter, // 생성할 장치를 나타내는 display adapter - GPU, NULL시 기본 어댑터 - 현재 사용중인 GPU
D3D_DRIVER_TYPE DriverType, // 드라이버 타입. 하드웨어 가속 시 HARDWARE. 그 외 여러 옵션 존재.
HMODULE Software, // 소프트웨어 구동기. 하드웨어 구동 시 NULL 지정
UINT Flags, // 디버그 모드 등 플래그
_In_reads_opt_( FeatureLevels ) CONST D3D_FEATURE_LEVEL* pFeatureLevels, // 프로그램에서 지원하고자 하는 DX 수준. NULL시 최고 기능 수준. 지정 시 지정된 값 중 최고 수준
UINT FeatureLevels, // pFeatureLevels의 원소 개수. NULL시 0
UINT SDKVersion, // 사용하는 SDK 버전
_COM_Outptr_opt_ ID3D11Device** ppDevice, // 생성된 장치 반환
_Out_opt_ D3D_FEATURE_LEVEL* pFeatureLevel, // pFeatureLevels 배열 중 처음으로 지원가능 기능 또는 NULL시 최고 수준 반환
_COM_Outptr_opt_ ID3D11DeviceContext** ppImmediateContext // 생성된 DeviceContext반환
);
HRESULT WINAPI CreateDXGIFactory(
REFIID riid,
_COM_Outptr_ void **ppFactory
);
typedef struct DXGI_SWAP_CHAIN_DESC
{
DXGI_MODE_DESC BufferDesc; // 후면 버퍼 속성
DXGI_SAMPLE_DESC SampleDesc; // 다중표본화를 위해 추출할 표본의 개수. 픽셀 당 다수의 표본 추출을 통해 품질 증가
DXGI_USAGE BufferUsage; // 버퍼의 용도
UINT BufferCount; // 후면 버퍼의 개수
HWND OutputWindow;
BOOL Windowed; // 창모드
DXGI_SWAP_EFFECT SwapEffect; // 교환 시 효과. DISCARD 설정 시 알아서 지정
UINT Flags;
} DXGI_SWAP_CHAIN_DESC;
virtual HRESULT STDMETHODCALLTYPE CreateSwapChain(
/* [annotation][in] */
_In_ IUnknown *pDevice, // ID3D11Device를 가리키는 포인터
/* [annotation][in] */
_In_ DXGI_SWAP_CHAIN_DESC *pDesc,
/* [annotation][out] */
_COM_Outptr_ IDXGISwapChain **ppSwapChain // 생성된 교환 사슬 인터페이스 반환
) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
/* [annotation] */
_In_ ID3D11Resource *pResource, // 후면 버퍼
/* [annotation] */
_In_opt_ const D3D11_RENDER_TARGET_VIEW_DESC *pDesc,
/* [annotation] */
_COM_Outptr_opt_ ID3D11RenderTargetView **ppRTView // 생성된 렌더 대상 뷰 반환
) = 0;
virtual void STDMETHODCALLTYPE RSSetViewports(
/* [annotation] */
_In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT NumViewports, // 뷰포트의 개수
/* [annotation] */
_In_reads_opt_(NumViewports) const D3D11_VIEWPORT *pViewports // 뷰포트 배열
) = 0;
Resource의 종류를 의미
예를 들어 Multi Render Target기법의 경우 다양한 Render Target에 원하는 작업만을 수행하여 저장할 수 있음
다만 일반적으로 Device가 그릴 영역을 의미
BackBuffer는 특별한 Render Target의 종류를 의미
그렇기 때문에 RenderTargetView 생성이라 하면 Display에 Draw할 BackBuffer를 설정하는 것을 의미
Draw하고자 하는 렌더타겟의 출력하고자하는 영역 설정
ex) 1p-2p 화면 나눠쓰기
이미지의 출력이 이루어질 Buffer를 1개만 사용할 시 Buffer에 작성과 출력이 동시에 진행되면서 깔끔하지 못한 이미지가 출력될 수 있음
작성이 진행중인 Buffer의 이미지가 출력되어 잔상이 남거나 깜박이는 현상
Buffer의 작성이 완료되었더라도 화면출력과 작성간의 순서가 맞지 않으면 이전 이미지의 일부가 남을 수 있음
이를 막기 위해 출력을 담당하는 Primary Buffer와 작성을 담당하는 Back Buffer를 사용하여 이미지의 작성이 완벽히 완료된 후 출력 수행
RenderTarget에 그려진 이미지를 Display에 출력하는 방식
Flipping 방식이 불필요한 복사가 적어서 일반적으로 더 빠름
작성된 이미지를 바로 DWM에 전송
작성된 이미지를 DWM의 Buffer에 복사
DWM은 복사된 이미지를 출력
다른 인터페이스(하드웨어를 제어하는 Object)를 생성 시 사용
생성된 인터페이스를 제어 시 사용
m_pImmediateContext->RSSetViewports(1, &vp);
m_pImmediateContext->OMSetRenderTargets(1, &m_pRTV, NULL);
m_pImmediateContext->ClearRenderTargetView(m_pRTV, color);
하드웨어 조회, 앨리어싱 수준 설정 등 가장 최하단에 위치한 인터페이스
D3D와 분리되어 있기 때문에 D2D에서도 사용 가능