Alpha混合通常是为了实现透明效果,透明效果的程度通过alpha值来控制,对于一个8bit的alpha chanel,可以产生0-255级透明效果,0表示完全透明,255表示完全不透明,在D3D中alpha值的来源主要有三种
今天介绍如何使用顶点的alpha值来实现透明效果,为了简化程序,我们使用顶点的alpha值来控制顶点的颜色,不涉及到纹理。关于如何使用material alpha及Texture alpha将在后续的篇章中介绍。
我们使用Lit顶点格式,也就是无需光照,顶点本身包含颜色值,所以顶点格式如下。
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
{ 0.0f, 0.0f, -1.0f, 0x8000ff00 };
这里只选取一个顶点作为示例。前三个值表示顶点的位置,最后一个值表示顶点的颜色,在D3D中,颜色用一个DWORD表示,其格式如下,最高位的一个byte表示alpha值,随后三个byte分别表示红绿蓝三原色。每个值的范围都是00-ff(十六进制),即十进制0-255。
所以对于0x8000ff00这个值,80表示alpha值,00ff00表示颜色,显然是绿色。
在D3D中,Diffuse color(漫反射颜色)一共有三种来源:
为了使用顶点的alpha值,我们需要将diffuse color的来源设置为D3DMCS_COLOR1。
g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
下面需要设置一些列的纹理状态,虽然我们只使用顶点,而未使用纹理,但是设置颜色和alpha值都需要通过纹理状态函数来完成。这段代码的意义是先选择两个颜色来源,然后指定一个施加在这两个颜色上的操作,从代码可知,第一个颜色是顶点的颜色,第二个是纹理的颜色,颜色操作是D3DTOP_SELECTARG1,也就是直接选择第一个颜色(顶点颜色)。纹理颜色被丢弃,所以第二行可有可无。
//Set the color to come completely from the vertex color g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); //Ignored g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
下面这段代码和上面设置颜色的代码道理相同,选择两个alpha值来源,然后指定一个施加在两个alpha值上的操作,这里同样只选择顶点的alpha值,因为我们就是想使用它!
//Set the alpha to come completely from the vertex diffuse g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); //Ignored g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
混合公式
OutputPixel = SourcePixel ⊗ SourceBlendFactor + DestPixel ⊗ DestBlendFactor
OutputPixel—混合后的颜色
SourcePixel—源像素,即当前正在计算的像素的颜色
SourceBlendFactor—源颜色的百分比
DestPixel—目标像素,即已经绘制的像素颜色(在back buffer中)
DestBlendFactor—目标像素颜色的百分比
⊗表示分量乘积
真正的混合操作由下面的代码完成,第一行指定源像素的混合因子,这里是D3DBLEND_SRCALPHA,也就是使用顶点的alpha值,源像素即当前正在计算的像素,第二行指定目标像素的混合因子,这里是D3DBLEND_INVSRCALPHA,也就是1减去顶点的alpha值。目标像素是指当前已经绘制在backbuffer中的像素,由于我们只绘制了一个物体,所以目标像素为空。第三行是混合操作,相加,这也是D3D的默认值。
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
下面是使用Vertex alpha和Vertex color混合的结果,根据alpha值的不同,可以产生不同级别的透明效果,这四幅图的alpha值依次是20, 80, C0和FF。
Happy coding!!!