[목차]
- Blend란
- BlendState
- Blending 공식들
[Blend란]
Direct3D에서 Blend는 Pixel Shader가 출력한 색과, 이미 RenderTarget에 있는 기존 색을 혼합(Blend)하여 최종 결과 색을 만드는 후처리 단계로, OutputMerget 단계에서 실시됩니다. 이를 활용하면 반투명 효과(유리, 물), UI 요소 합성(글자, HUD), Multy Target Rendering(Deferred Rendering), 색상 누적(Light Addition, Glow) 등의 효과를 만들어낼 수 있습니다.
Blending 연산 공식은 다음과 같습니다.
FinalColor = (SrcColor * SrcBlend) + (DestColor * DestBlend)
1. SrcColor : 픽셀 셰이더에서 출력한 값
2. DestColor : 앞서 출력된 결과물 값(저장되어 있는 값)
3. SrcBlend, DestBlend : 설정된 블렌드 계수
[BlendState]
Blend도 State를 통해 사용자 임의로 값을 지정해줄 수 있습니다. 물론 아무것도 지정하지 않으면 디폴트 BlendState가 적용됩니다. 기본값은 다음과 같습니다.
D3D11_BLEND_DESC DefaultBlendDesc = {};
DefaultBlendDesc.AlphaToCoverageEnable = FALSE;
DefaultBlendDesc.IndependentBlendEnable = FALSE;
D3D11_RENDER_TARGET_BLEND_DESC& rtDesc = DefaultBlendDesc.RenderTarget[0];
rtDesc.BlendEnable = FALSE;
rtDesc.SrcBlend = D3D11_BLEND_ONE;
rtDesc.DestBlend = D3D11_BLEND_ZERO;
rtDesc.BlendOp = D3D11_BLEND_OP_ADD;
rtDesc.SrcBlendAlpha = D3D11_BLEND_ONE;
rtDesc.DestBlendAlpha = D3D11_BLEND_ZERO;
rtDesc.BlendOpAlpha = D3D11_BLEND_OP_ADD;
rtDesc.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
| BlendEnable | FALSE | - 블렌딩 안함(픽셀 그대로 출력) |
| SrcBlend, DestBlend | ONE, ZERO | - FinalColor = (Source * 1) + (Dest * 0) - 이 공식에 따라 FinalColor는 원본 색만 사용 |
| BlendOp | ADD | - 알파 블렌딩에 사용되는 연산 방식 |
| WriteMask | ALL | - RGBA 모두 출력하기 |
이제 테스트를 위해 BlendState를 정의하지 않고(디폴트 사용) 아래의 Texture를 출력해봅시다.

+) 원래 제대로 만들어진 Texture의 알파값은 검은색이나 흰색 둘 중 하나인데, 이 텍스쳐는 옛날에 제가 모작 프로젝트를 진행할 때 포토샵으로 조금 수정한 텍스쳐라서 알파값 색상이 섞여있는 상태입니다.
출력 결과를 살펴보니 Alpha도 그대로 출력되고 있습니다.이제 Blending을 실시하는 것으로 변경해서 Alpha값을 출력하지 않도록 해보겠습니다.
BlendState는 다음과 같이 정의해주었습니다.
D3D11_BLEND_DESC BlendInfo = { 0, };
// Desc.AlphaToCoverageEnable = false; == 자동으로 알파부분을 제거하여 출력해준다. 너무 느려서 사용 안함.
BlendInfo.AlphaToCoverageEnable = false;
BlendInfo.IndependentBlendEnable = false;
BlendInfo.RenderTarget[0].BlendEnable = true;
BlendInfo.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
BlendInfo.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
BlendInfo.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
BlendInfo.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
BlendInfo.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
BlendInfo.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
BlendInfo.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
// <<설명>>
/*1. BlendEnable : 블렌드 활성화 여부, true는 활성화*/
/*2. SrcBlend : 소스 색상에 곱할 계수, D3D11_BLEND_SRC_ALPHA면 RGBA에서 A*/
/*3. DestBlend : 대상 색상에 곱할 계수*/
/*4. BlendOp : 두 색상의 혼합 방식, ADD, SUBTRACT 등 있음*/
/*5. SrcBlendAlpha : 알파 채널에 대한 Scr 계수*/
/*6. DestBlendAlpha : 알파 채널에 대한 Scr 계수*/
/*7. BlendOpAlpha : 알파 채널의 혼합 연산*/
/*8. RenderTargetWriteMask : RGBA 쓰기 허용 여부 결정*/
Ext_DirectXBlend::CreateBlend("BaseBlend", BlendInfo);
// 반투명 오브텍트는 일반적으로 ZWrite를 꺼야 제대로 섞인다. ZBuffer 충돌~, 또한 렌더 순서도 중요한데, 투명한 오브젝트는 뒤에서 앞으로 렌더링 해줘야한다.
// 멀티 렌더 타겟의 경우는 알파용 렌더타겟을 따로 사용하는 방식도 있음
//...
해당 블렌드는 가장 흔하게 사용되는 Alpha Blend State입니다. CreateBlend() 함수를 호출하면 아래의 연관 함수들이 호출됩니다.
// 위를 통해 블렌드 생성
void Ext_DirectXBlend::CreateBlend(const D3D11_BLEND_DESC& _Value)
{
BlendInfo = _Value;
if (S_OK != Ext_DirectXDevice::GetDevice()->CreateBlendState(&BlendInfo, BlendState.GetAddressOf()))
{
MsgAssert("블랜드 스테이트 생성에 실패했습니다.");
}
}
// 아웃풋머저 단계에서 호출
void Ext_DirectXBlend::Setting()
{
if (nullptr == BlendState)
{
MsgAssert("생성되지 않은 레스터라이저 스테이트 입니다.");
}
if (BlendInfo.RenderTarget[0].SrcBlend == D3D11_BLEND_BLEND_FACTOR)
{
MsgAssert("아직 처리 하지 않는 블랜드 방식입니다 블랜드 필터 입력기능을 만들어 주세요.");
}
Ext_DirectXDevice::GetContext()->OMSetBlendState(BlendState.Get(), nullptr, Mask);
// <<설명>>
// 1. 만든 블렌더 넣기
// 2. 블렌드 팩터 사용 안함
// 3. Mask 0xFFFFFFFF 전달
}
BlendState는 Material에 바인딩해줍니다.
// 일반(단일 메시)
{
std::shared_ptr<Ext_DirectXMaterial> NewRenderingPipeline = Ext_DirectXMaterial::CreateMaterial("Basic");
NewRenderingPipeline->SetVertexShader("Basic_VS");
NewRenderingPipeline->SetPixelShader("Basic_PS");
NewRenderingPipeline->SetBlendState("BaseBlend");
NewRenderingPipeline->SetDepthState("EngineDepth");
NewRenderingPipeline->SetRasterizer("EngineRasterizer");
}
이 상태로 출력해보겠습니다.
이전과 다르게 Alpha 출력이 제거된 것을 확인할 수 있습니다.
[Blending 공식들]
굳이 Blending 공식을 외울 필요는 없을 것 같다고 생각됩니다. 그냥 기본 연산 공식만 알고 계시면 됩니다.
FinalColor = (SrcColor * SrcBlend) + (DestColor * DestBlend)
해당 프로젝트에서도 필요한 Blending 공식은 그때그때 찾아서 활용할 예정입니다. 아래에 자주 사용되는 공식 몇 가지를 간단하게 소개하고 포스팅 마치겠습니다.
1. 알파블렌딩
: 일반적인 반투명 처리에 활용됩니다. 위에서 설정한 값이 이 알파블렌딩 설정값입니다.
// 설정값
SrcBlend = D3D11_BLEND_SRC_ALPHA
DestBlend = D3D11_BLEND_INV_SRC_ALPHA
BlendOp = D3D11_BLEND_OP_ADD
// 공식
Final = SrcColor * SrcAlpha + DestColor * (1 - SrcAlpha)
2. 가산 합성
: 광원, 폭발, 글로우 등에 사용됩니다.
// 설정값
SrcBlend = D3D11_BLEND_ONE
DestBlend = D3D11_BLEND_ONE
BlendOp = D3D11_BLEND_OP_ADD
// 공식
Final = SrcColor + DestColor
3. Subtractive
: 어둡게 만들거나 특정 색을 빼는 연출에 사용됩니다.
// 설정값
SrcBlend = D3D11_BLEND_ONE
DestBlend = D3D11_BLEND_ONE
BlendOp = D3D11_BLEND_OP_SUBTRACT
// 공식
Final = SrcColor - DestColor
'DirectX11 > 프레임워크 제작' 카테고리의 다른 글
| [DirectX11] DirectX11 프레임워크를 위한 기능 추가 - 3 + 간단한 Lighting 해보기 (0) | 2025.06.04 |
|---|---|
| [DirectX11] assimp 라이브러리를 통한 3DMesh 로드와 애니메이션 (0) | 2025.05.29 |
| [DirectX11] Texcoord(UV)와 Sampler (0) | 2025.05.28 |
| [DirectX11] DirectXTex를 통한 Texture 활용 (0) | 2025.05.28 |
| [DirectX11] RasterizerState 생성 (0) | 2025.05.28 |