[DirectX]Programming.Role.Playing.Games:02_03_AlphaBlend

    Alpha混合用的就是Programming.Role.Playing.Games.with.DirectX书上的例子,因为一时想不到什么好的,还是跟以前一样,加了个Shader实现的。还是老规则,左边的是用固定管线实现的,右边是用Shader实现的。右边的变化还是比较明显的。

    代码是在之前Draw2D上修改的,这样快速,不需要在关心这个初始化,那个初始化来着,之前有忘记说,如果顶点格式设置为D3DFVF_XYZRHW格式话,顶点坐标就是2D坐标,不是3D坐标,这点要搞清楚,而且坐标原点是左上角。

    开启和关闭Alpha混合,很简单调用SetRenderState(D3DRS_ALPHABLENDENABLE, bIsEnable),bIsEnable是bool值,是否开启。

    来看下渲染的代码:

    固定管线:

void ModelClass::Render(IDirect3DDevice9* device, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix)
{
	device->SetStreamSource(0, m_vertexBuffer, 0, sizeof(VertexType));
	device->SetFVF(VERTEX_FVF);

	// Disable the alpha blending of rendering the back
	device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);

	device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

	// Enable the alpha bleding of the rendering the front
	device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
	device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

	device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);

	// Dont't forget to disable the alpha blending
	device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
}

    首先我们先关闭Alpha混合,渲染不透明的Square,再开启Alpha混合,渲染透明的Rectangle,记住关闭Alpha混合,不然你是感受不到Shader中是否开启AlphaBlend功能。注意SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA)和SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA),很多书上都会说源颜色和源混合因子相乘,加上目标颜色和目标混合因子相乘,就为输出结果。其实一开始会很不明白的,理解好的人会很快,我是花了很多时间才搞懂的,先看Shader,我再来简单说下。

    Shader渲染:

void ShaderModelClass::Render(IDirect3DDevice9* device, float time, D3DXMATRIX worldMatrix, D3DXMATRIX viewMatrix, D3DXMATRIX projectionMatrix)
{
	bool result;
	UINT passMaxNum;

	device->SetStreamSource(0, m_vertexBuffer, 0, sizeof(VertexType));
	device->SetFVF(VERTEX_FVF);

	result = m_colorShader->Render(device, time, worldMatrix, viewMatrix, projectionMatrix);
	if (!result)
		return;

	m_colorShader->GetEffect()->Begin(&passMaxNum, 0);
	for (UINT pass = 0; pass < passMaxNum; ++pass)
	{
		m_colorShader->GetEffect()->BeginPass(pass);
		device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
		m_colorShader->GetEffect()->EndPass();
	}
	m_colorShader->GetEffect()->End();

	result = m_alphaBlendShader->Render(device, time, worldMatrix, viewMatrix, projectionMatrix);
	if (!result)
		return;

	m_alphaBlendShader->GetEffect()->Begin(&passMaxNum, 0);
	for (UINT pass = 0; pass < passMaxNum; ++pass)
	{
		m_alphaBlendShader->GetEffect()->BeginPass(pass);
		device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);
		m_alphaBlendShader->GetEffect()->EndPass();
	}
	m_alphaBlendShader->GetEffect()->End();
}

    这里我用了2个shader,一个用于渲染不透明的,另一个则用于渲染透明的,代码很简单,就不多说了。不透明渲染的shader就是之前Draw2D的shader,所以不在重复。

    透明Shader:

float time;
float4x4 worldMatrix;
float4x4 viewMatrix;
float4x4 projectionMatrix;

struct VertexInputType
{
	float4 vertex : POSITION;
	float4 color : COLOR0;
};

struct PixelInputType
{
	float4 pos : POSITION;
	float4 color : COLOR0;
};

PixelInputType AlphaBlendVertexShader(VertexInputType input)
{
	PixelInputType output;

	output.pos = input.vertex;
	output.color = input.color;

	return output;
}

float4 AlphaBlendPixelShader(VertexInputType input) : COLOR
{
	float4 color = input.color; 

	return color;
}

technique ShaderTechnique
{
	pass pass0 
	{
		AlphaBlendEnable = true;
		BlendOp = ADD;
		//BlendOp = Subtract;
		//BlendOp = RevSubtract;
		//BlendOp = Min;
		//BlendOp = Max;
		SrcBlend = SrcAlpha;
		DestBlend = InvSrcAlpha;
		VertexShader = compile vs_2_0 AlphaBlendVertexShader();
		PixelShader = compile ps_2_0 AlphaBlendPixelShader();
	}
}

    与不透明不同的地方就在于标红的地方,记得上面用固定管线渲染的时候说过要关闭Alpha混合吗?这边就是用Effect来开启Alpha混合,简不简单。

    上面不是说源颜色和源混合因子相乘,加上目标颜色和目标混合因子相乘,就为输出结果。这里就来详细的介绍下。看到BlendOp = Add了吗?这里设置就是表示源颜色和源混合因子相乘,加上目标颜色和目标混合因子相乘,如果改成Subtract,就是表示源颜色和源混合因子相乘,减去目标颜色和目标混合因子相乘,可以取消注释试试。

    接着说下源颜色和目标颜色,这里你可以理解为源颜色就是当前像素的颜色也就是像素着色器(PixelShader)生成的颜色,也是我们创建模型时赋予的颜色值,未做任何修改。目标颜色也就是颜色缓存中的颜色,源混合因子SrcAlpha就是像素着色器(PixelShader)生成的颜色中的Alpha值,也就是我们在创建模型时,赋予的值也就是0.5f,目标混合因子InvSrcAlpha就跟简单了,值就是1.0-源混合因子,这里源混合因子是0.5f,所以目标混合因子就是0.5f,整个公示就是模型颜色*0.5f + 颜色缓存中的颜色*0.5f,就是显示的颜色了。可以试着将混合因子改成One或者Zero试试。

源码下载:下载地址

猜你喜欢

转载自blog.csdn.net/zp288105109a/article/details/80869334