Direct3D 11 总结 —— 7 实现透明效果

24 篇文章 2 订阅
13 篇文章 3 订阅

介绍

当两张图片重叠的时候,可以一张完全盖住另外一张,也可以实现两张图片融合的结果。本文将对图片融合展开介绍。
融合的公式如下
  C = C s r c ⊕ F s r c 1 Θ C d s t ⊕ F d s t 1 \ C = C_{src}\oplus F_{src1} \Theta C_{dst} \oplus F_{dst1}  C=CsrcFsrc1ΘCdstFdst1
  A = A s r c ⊕ F s r c 2 Θ A d s t ⊕ F d s t 2 \ A = A_{src}\oplus F_{src2} \Theta A_{dst} \oplus F_{dst2}  A=AsrcFsrc2ΘAdstFdst2
其中 C 代表颜色(color);A 代表透明度(transparent)。   C s r c \ C_{src}  Csrc 代表从像素着色器输出的像素,对应本文的狗像素;   F s r c 1 \ F_{src1}  Fsrc1 代表各 rgb 的比重,可通过程序设置;   C s r c ⊕ F s r c 1 \ C_{src}\oplus F_{src1}  CsrcFsrc1,表示{   R s r c ∗ F r s r c 1 , G s r c ∗ F g s r c 1 , B s r c ∗ F b s r c 1 \ R_{src}*F_{r_{src1}},G_{src}*F_{g_{src1}},B_{src}*F_{b_{src1}}  RsrcFrsrc1,GsrcFgsrc1,BsrcFbsrc1}。   C d s t \ C_{dst}  Cdst 代表已经存在后备缓冲区的数据,对应本文的背景颜色。   Θ \ \Theta  Θ 表示   C s r c ⊕ F s r c 1 \ C_{src}\oplus F_{src1}  CsrcFsrc1   C d s t ⊕ F d s t 1 \ C_{dst} \oplus F_{dst1}  CdstFdst1 的结果之间怎么融合,常用的有 add,就是将 rgb 分别相加。

最终效果

没开融合时的现象

在这里插入图片描述

开了融合后的现象

在这里插入图片描述

代码

OMSetBlendState

设置输出的融合方式

主要增加的代码

ID3D11BlendState* blendState;
D3D11_BLEND_DESC blendDesc = {};
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = FALSE;
blendDesc.RenderTarget->BlendEnable = TRUE; // 是否开启混合
blendDesc.RenderTarget->SrcBlend = D3D11_BLEND_SRC_ALPHA; // 将源图的 alpha 作为 src rgb 的混合因子
blendDesc.RenderTarget->DestBlend = D3D11_BLEND_INV_SRC_ALPHA; // 将源图的 1-alpha 作为 dst rgb 的混合因子
blendDesc.RenderTarget->BlendOp = D3D11_BLEND_OP_ADD; // 进行相加操作
blendDesc.RenderTarget->SrcBlendAlpha = D3D11_BLEND_ONE; // 
blendDesc.RenderTarget->DestBlendAlpha = D3D11_BLEND_ONE;
blendDesc.RenderTarget->BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendDesc.RenderTarget->RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; // 可以写入的位置
m_pDevice->CreateBlendState(&blendDesc, &blendState);

const FLOAT BlendFactor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
m_pContext->OMSetBlendState(blendState, BlendFactor, 0xffffffff);

BlendEnable 表示是否开启融合;SrcBlend 对应公式里面的   F s r c 1 \ F_{src1}  Fsrc1 ,DestBlend 对应公式里面的   F d s t 1 \ F_{dst1}  Fdst1 , BlendOp 对应第一个公式的   Θ \ \Theta  Θ。SrcBlendAlpha 对应公式里面的   F s r c 2 \ F_{src2}  Fsrc2 ,DestBlendAlpha 对应公式里面的   F d s t 2 \ F_{dst2}  Fdst2,BlendOpAlpha 对应第二个公式的   Θ \ \Theta  Θ。RenderTargetWriteMask 表示哪些颜色通道可以写入。

具体代码

rt slot
		1,				// buffer 数量  (start slot ~ start slot + buffer number
		&verticesBuffer,// 顶点缓存
		&strider,		// 每组数据的字节数
		&offset);		// 偏移量


	DirectX::XMUINT3 index[] = {
		{0, 1, 2},
		{0, 2, 3}};

	D3D11_BUFFER_DESC indexDesc = {};
	indexDesc.ByteWidth = sizeof(index) * 2; // 字节数
	// 将 usage 设为 D3D11_USAGE_IMMUTABLE  D3D11_USAGE_DEFAULT 可行
	indexDesc.Usage = D3D11_USAGE_IMMUTABLE; // 资源的使用,gpu和cpu 的读写权限 
	indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; // 标识如何将资源绑定到 pipeline 
	indexDesc.CPUAccessFlags = 0; // CPU 的读写权限
	indexDesc.MiscFlags = 0;
	indexDesc.StructureByteStride = 0;

	resourceData.pSysMem = index;
	resourceData.SysMemPitch = 0;
	resourceData.SysMemSlicePitch = 0;

	ID3D11Buffer* indexBuffer = NULL;
	m_pDevice->CreateBuffer(&indexDesc, &resourceData, &indexBuffer);

	// 设置所引缓存
	m_pContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
	
	// 输入布局
	m_pContext->IASetInputLayout(m_inputLayout);

	// 图元拓扑结构
	m_pContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	/************************************* 顶点着色器阶段 **************************************/
	m_pContext->VSSetShader(m_pVertexShader, nullptr, 0);

	/************************************* 像素着色器阶段 **************************************/
	m_pContext->PSSetShader(m_pPixelShader, nullptr, 0);

	ID3D11Resource* inputResource = NULL;
	ID3D11ShaderResourceView* shaderResourceView = NULL;
	std::wstring path = L"res\\image\\dog2.png";
	CreateWICTextureFromFile(m_pDevice,
		path.c_str(),
		&inputResource,
		&shaderResourceView);

	m_pContext->PSSetShaderResources(0, 1, &shaderResourceView);

	ID3D11SamplerState* sampler;
	D3D11_SAMPLER_DESC sampleDesc = {};
	sampleDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
	sampleDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; // 平铺整数个
	sampleDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
	sampleDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
	sampleDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
	sampleDesc.MinLOD = 0;
	sampleDesc.MaxLOD = D3D11_FLOAT32_MAX;
	m_pDevice->CreateSamplerState(&sampleDesc, &sampler);

	m_pContext->PSSetSamplers(0, 1, &sampler);

	
	/************************************* 输出阶段 **************************************/
	// 设置渲染目标
	m_pContext->OMSetRenderTargets(1, &m_pRenderTargetView, NULL);

	ID3D11BlendState* blendState;
	D3D11_BLEND_DESC blendDesc = {};
	blendDesc.AlphaToCoverageEnable = FALSE;
	blendDesc.IndependentBlendEnable = FALSE;
	blendDesc.RenderTarget->BlendEnable = TRUE; // 是否开启混合
	blendDesc.RenderTarget->SrcBlend = D3D11_BLEND_SRC_ALPHA; // 将源图的 alpha 作为 src rgb 的混合因子
	blendDesc.RenderTarget->DestBlend = D3D11_BLEND_INV_SRC_ALPHA; // 将源图的 1-alpha 作为 dst rgb 的混合因子
	blendDesc.RenderTarget->BlendOp = D3D11_BLEND_OP_ADD; // 进行相加操作
	blendDesc.RenderTarget->SrcBlendAlpha = D3D11_BLEND_ONE; // 
	blendDesc.RenderTarget->DestBlendAlpha = D3D11_BLEND_ONE;
	blendDesc.RenderTarget->BlendOpAlpha = D3D11_BLEND_OP_ADD;
	blendDesc.RenderTarget->RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; // 可以写入的位置
	m_pDevice->CreateBlendState(&blendDesc, &blendState);

	const FLOAT BlendFactor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
	m_pContext->OMSetBlendState(blendState, BlendFactor, 0xffffffff);
	
	// 设置视口
	D3D11_VIEWPORT viewPort = {};
	viewPort.TopLeftX = 0;
	viewPort.TopLeftY = 0;
	viewPort.Width = 800;
	viewPort.Height = 600;
	viewPort.MinDepth = 0.0f;
	viewPort.MaxDepth = 1.0f;
	m_pContext->RSSetViewports(1, &viewPort);
				
	// 开始绘制
	m_pContext->DrawIndexed(6, 0, 0);
}

参考文献

https://www.cnblogs.com/X-Jun/p/9346640.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值