[DirectX] Output Merge


쉐이더의 마지막 단계인 Output Merge (이하 OM)단계를 위해서

Depth Stencil State와 Blend State를 지정해주어야 한다.

Depth Stencil State


오브젝트의 픽셀 하나하나 마다 깊이 값이 지정되어있다. 여기서 지정된 깊이값을 비교하면서 어떤 색상을 출력할지 판정을 한다.

깊이 판정을 하는 경우는 아래와 같다.

  • Less : 제일 기본 옵션, 카메라에서 더 가까운 경우 출력
  • Less_equal : Less 옵션에서 같은 깊이 값을 가진 경우까지 출력
  • Greater : 오히려 카메라에서 더 멀리 있는 경우가 출력된다.
  • Greater_equal : Greater 옵션에서 같은 깊이 값을 가진 경우까지 출력


Blend State


입력된 색상을 어떤 효과를 주어서 출력할 지 결정하는 단계이다.

  • DEFAULT : 기본적으로, 블렌딩을 진행하지 않고 그 색상 그대로 출력한다.
  • MASK : 알파 블렌드에서 AlphaCoverage 옵션은 true인 상태
  • ALPHABLEND : 투명도를 부여한다. 기존 색상과 뒤에 있는 색상을 섞어 출력한다.
  • ONE_ONE : 1대1 비율로 혼합해서 출력함. 검은 배경의 이미지에서 주로 사용.


define 헤더의 변화


DS State와 BS State의 종류를 지정해준다.

// 코드 추가

enum class DS_TYPE
{
    LESS,
    LESS_EQUAL,
    GREATER,
    GREATER_EQUAL,
    NO_WRITE, // LESS 판정, DepthWrite는 하지않음.
    NO_TEST_NO_WRITE, // 깊이 테스트도 하지 않음.
    END
}

enum class BS_TYPE
{
    DEFAULT, // No Blending
    MASK, // Alpha Coverage 옵션 킨 것
    ALPHA_BLEND, // Alpha 계수
    ONE_ONE, // 1대 1 혼합
    END
}


CDevice 클래스의 변화


// 헤더파일 코드 추가

private:

	// DepthStencilState
	ComPtr<ID3D11DepthStencilState>	m_DSState[(UINT)DS_TYPE::END];

	// BlendState
	ComPtr<ID3D11BlendState>		m_BSState[(UINT)BS_TYPE::END];

private:
	int CreateBlendState();
	int CreateDepthStencilState();
// cpp파일


int CDevice::CreateDepthStencilState()
{
    // Less
    m_DSState[(UINT)DS_TYPE::LESS] = nullptr;

    // Less Equal
    D3D11_DEPTH_STENCIL_DESC Desc = {};
    Desc.DepthEnable = true;
    Desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
    Desc.StencilEnable = false;
    Desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    DEVICE->CreateDepthStencilState(&Desc, m_DSState[(UINT)DS_TYPE::LESS_EQUAL].GetAddressOf());
    
    // Greater
    Desc.DepthEnable = true;
    Desc.DepthFunc = D3D11_COMPARISON_GREATER;
    Desc.StencilEnable = false;
    Desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    DEVICE->CreateDepthStencilState(&Desc, m_DSState[(UINT)DS_TYPE::GREATER].GetAddressOf());

    // Greater Equal
    Desc.DepthEnable = true;
    Desc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL;
    Desc.StencilEnable = false;
    Desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
    DEVICE->CreateDepthStencilState(&Desc, m_DSState[(UINT)DS_TYPE::GREATER_EQUAL].GetAddressOf());

    // No Write
    Desc.DepthEnable = true;
    Desc.DepthFunc = D3D11_COMPARISON_LESS;
    Desc.StencilEnable = false;
    Desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    DEVICE->CreateDepthStencilState(&Desc, m_DSState[(UINT)DS_TYPE::NO_WRITE].GetAddressOf());

    // NoTest NoWrite
    Desc.DepthEnable = false;    
    Desc.StencilEnable = false;
    Desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
    DEVICE->CreateDepthStencilState(&Desc, m_DSState[(UINT)DS_TYPE::NO_TEST_NO_WRITE].GetAddressOf());


    return S_OK;
}

int CDevice::CreateBlendState()
{
    // No Blend
    m_BSState[(UINT)BS_TYPE::DEFAULT] = nullptr;

    // Mask
    D3D11_BLEND_DESC Desc = {};
    Desc.AlphaToCoverageEnable = true;
    Desc.IndependentBlendEnable = false;
    Desc.RenderTarget[0].BlendEnable = false;
    DEVICE->CreateBlendState(&Desc, m_BSState[(UINT)BS_TYPE::MASK].GetAddressOf());


    // Alpha Blend   
    Desc.AlphaToCoverageEnable = false;
    Desc.IndependentBlendEnable = false;

    Desc.RenderTarget[0].BlendEnable = true;
    Desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    Desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    Desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;

    Desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    Desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    Desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;

    Desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    DEVICE->CreateBlendState(&Desc, m_BSState[(UINT)BS_TYPE::ALPHA_BLEND].GetAddressOf());




    // One One
    Desc.AlphaToCoverageEnable = false;
    Desc.IndependentBlendEnable = false;

    Desc.RenderTarget[0].BlendEnable = true;
    Desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    Desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
    Desc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;

    Desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    Desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
    Desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;

    Desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
    DEVICE->CreateBlendState(&Desc, m_BSState[(UINT)BS_TYPE::ONE_ONE].GetAddressOf());

    return S_OK;
}

각 상황에 맞는 DS State와 BS State를 제작한다.
그리고 DepthStencilState와 BlendState를 Device에서 생성, 호출한다.

Alpha Blend 사용하기


CResMgr.cpp


CResMgr.cpp에서 CreateDefaultGraphicsShader에서 SetBSType를 통해 ALPHABLEND로 세팅해준다.

Ptr<CGraphicsShader> pShader = nullptr;

	// ===========
	// Test Shader
	// ===========
	pShader = new CGraphicsShader;
	pShader->SetKey(L"TestShader");
	pShader->CreateVertexShader(L"shader\\test.fx", "VS_Test");
	pShader->CreatePixelShader(L"shader\\test.fx", "PS_Test");

	pShader->SetRSType(RS_TYPE::CULL_NONE);
	pShader->SetDSType(DS_TYPE::NO_WRITE); // 깊이 테스트 진행, 깊이 기록 X
	pShader->SetBSType(BS_TYPE::ALPHA_BLEND);

	pShader->SetDomain(SHADER_DOMAIN::DOMAIN_TRANSPARENT);
	
	AddRes(L"TestShader", pShader);


CGraphicsShader.cpp


CGraphicsShader.cpp에서 UpdataData함수도 수정해준다.

    CONTEXT->IASetInputLayout(m_Layout.Get());
	CONTEXT->IASetPrimitiveTopology(m_eTopology);
		
	CONTEXT->VSSetShader(m_VS.Get(), nullptr, 0);
	//CONTEXT->HSSetShader(m_HS.Get(), nullptr, 0);
	//CONTEXT->DSSetShader(m_DS.Get(), nullptr, 0);
	//CONTEXT->GSSetShader(m_GS.Get(), nullptr, 0);
	CONTEXT->PSSetShader(m_PS.Get(), nullptr, 0);

	CONTEXT->RSSetState(CDevice::GetInst()->GetRSState(m_RSType).Get());
	CONTEXT->OMSetDepthStencilState(CDevice::GetInst()->GetDSState(m_DSType).Get(), 0);
	CONTEXT->OMSetBlendState(CDevice::GetInst()->GetBSState(m_BSType).Get(), Vec4(0.f, 0.f, 0.f, 0.f), 0xffffffff);



© 2022.07. by Wookey_Kim

Powered by Hydejack v7.5.2