Search
Duplicate

레스터라이저 Rasterizer, 뎁스 스텐실 DepthStencil, 블렌드 Blend (State)

버텍스 - 지오메트리 셰이더로부터 출력된 정점정보는 레스터라이저 스테이지에 보내진후 렌더링 될 픽셀로 변환된다.
Direct3D에서는 이러한 과정을 통틀어서 레스터라이제이션 이라고 부르고 고정 파이프라인 단계로 프로그래밍이 불가능하며 자체 알고리즘을 통해 동작한다.
레스터라이제이션은 다음과 같은 역할을 수행한다.
클리핑
원근 나눗셈(perspective division)
뒷면 제거(backface culling)
스캔변환(ndc Scan transform)
뷰포트 변환
래스터 라이저 스테이트 오브젝트를 만드려면 늘 하던 식의 D3D11_RASTERIZER_DESC 구조체를 만들고
ID3D11Device::CreateRasterizerState함수를 호출하여 생성한다.
// 래스터라이저 스테이트 오브젝트 생성 D3D11_RASTERIZER_DESC RSDesc; RSDesc.FillMode = D3D11_FILL_SOLID; // 평범하게 렌더링 RSDesc.CullMode = D3D11_CULL_NONE; // 컬모드 하지 않음 RSDesc.FrontCounterClockwise = FALSE; // 시계방향이 뒷면임 CCW RSDesc.DepthBias = 0; //깊이 바이어스 값 0 RSDesc.DepthBiasClamp = 0; RSDesc.SlopeScaledDepthBias = 0; RSDesc.DepthClipEnable = FALSE; // 깊이 클리핑 없음 RSDesc.ScissorEnable = FALSE; // 시저 테스트 하지 않음 RSDesc.MultisampleEnable = FALSE; // 멀티 샘플링 하지 않음 RSDesc.AntialiasedLineEnable = FALSE; // 라인 안티앨리어싱 없음 hr = g_pD3DDevice->CreateRasterizerState(&RSDesc, &g_pRasterizerState);
JavaScript
복사
그리고 생선된 오브젝트로 레스터라이저 스테이트에 묶어준다.
void GraphicDevice_DX11::BindRasterizerState(ID3D11RasterizerState* pRasterizerState) { mContext->RSSetState(pRasterizerState); }
JavaScript
복사

Output merger

OuputMerger 에서 중요한것은 렌더타겟에서 계산된 픽셀 값을 사용하는 것이다.
OuputMerger는 동시에 8개의 렌더타겟과 1개의 깊이/스텐실 버퍼를 설정한다.

Blend State(블렌드 스테이트)

블렌드 스테이트는 픽셀 셰이더에서 출력된 값(Src)와 렌더타겟의 값(Dest)에 각각의 계수를 곱하고
그값에 대해 지정한 계산을 수행하고 레더타겟에 쓰여지는 값을 결정한다.
outputColor = 연산방법(SRC값 * SRC계수, DEST값 * DEST 계수)
D3D11_BLEND_DESC bsDesc = {}; bsDesc.AlphaToCoverageEnable = false; //멀티 샘플링에서 알파값 사용 유무 bsDesc.IndependentBlendEnable = false; // False -> 렌더타겟의 0번쨰만 사용 (1~7 번째는 무시) // 0번 렌더타겟에 대한 블렌드 상태 설정 (0~7 번까지 설정 가능하다) bsDesc.RenderTarget[0].BlendEnable = true; bsDesc.RenderTarget[0].SrcBlend = D3D11_BLEND::D3D11_BLEND_SRC_ALPHA; bsDesc.RenderTarget[0].DestBlend = D3D11_BLEND::D3D11_BLEND_INV_SRC_ALPHA; bsDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD; bsDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND::D3D11_BLEND_ONE; bsDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND::D3D11_BLEND_ZERO; bsDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP::D3D11_BLEND_OP_ADD; bsDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE::D3D11_COLOR_WRITE_ENABLE_ALL; GetDevice()->CreateBlendState(&bsDesc, blendStates[(UINT)eBlendState::AlphaBlend].GetAddressOf());
JavaScript
복사
각 옵션별 상용 방법은 MSDN Document를 참고 해보자.
만약 따로 설정하지 안는다면 디폴트 값으로 설정되는 상태는 다음과 같다.
그리고 Blend State를 렌더링 파이프라인에 묶어준다.
FLOAT blendFactor[4] = {0.f, 0.f, 0.f, 0.f}; g_pImmediateContext->OMSetBlendState(g_pBlendState, //설정할 오브젝트 blendFactor, //상수값(RGBA) 0xffffffff); //샘플용 마스크
JavaScript
복사
두번째필드 BlendFactor는  D3D11_BLEND_BLEND_FACTOR 에서 사용할 상수값을 RGBA별로 설정한 배열이며 세번째 필드 SampleMask는 멀티샘플 렌더타겟에서 어떤 샘플을 Enable로 할까(Masking할까)를 설정하는 값으로 멀티 샘플링의 설정과는 독립되어있으며 멀티샘플 렌더타겟을 사용하는가에 따라 다르다.

Depth/Stencil State( 깊이/스텐실 상태 )

뎁스 / 스텐실 스테이트의 흐름은 대략 다음과 같다.
DepthStencil오브젝트를 생성해보자.
ID3D11DepthStencilState* g_pDepthStencilState = NULL; D3D11_DEPTH_STENCIL_DESC DepthStencilDesc; DepthStencilDesc.DepthEnable = TRUE; //깊이 테스트 활성화 DepthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; //쓰기 DepthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; // 앞쪽물체를 렌더링 DepthStencilDesc.StencilEnable = FALSE; //스텐실 테스트 비활성화 DepthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; //스텐실 읽기 마스크 DepthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; //스텐실 쓰기 마스크 // 면이 앞을 보고 있을 경우 스텐실 테스트 설정 DepthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; //유지 DepthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; //유지 DepthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; //유지 DepthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; //항상 성공 //면이 뒤를 보고 있을경우 스텐실 테스트 설정 DepthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; //유지 DepthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; //유지 DepthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; //유지 DepthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; //항상 성공 g_pd3dDevice->CreateDepthStencilState(&DepthStencilDesc,&g_pDepthStencilState);
JavaScript
복사
DepthStencil오브젝트도 따로 설정해주지 않으면 기본값은 아래와 같다.
DepthStencil 오브젝트를 설정 했으면  함수를 호출하여 OM 스테이지에 설정한다
g_pImmediateContext->OMSetDepthStencilState(g_pDepthStencilState, 0);
JavaScript
복사