Alpha混合(二)Material Alpha
Alpha值
Alpha混合是为了实现透明效果,透明到什么程度是由alpha值决定的,对于一个32位的ARGB格式的颜色来说,它的组成部分如下:
我们可以看到,最高位的一个byte表示alpha值,它并不代表实际的颜色,它是控制颜色的百分比。范围是0x00 - 0xff,也就是十进制的0-255。它可以控制256个级别的透明程度,0表示完全透明,就是什么也看不见了。255表示完全不透明。随后的三个字节分别表示红绿蓝三原色。那么alpha值是如何工作的呢?如果开启了alpha混合,假设指定了颜色为0x80ff0000,可知alpha值为0x80(十进制128),红色=0xff(十进制255),为满色,绿色和蓝色都为0。于是最终的颜色就是(128 / 255)* 255 = 128,也就是说,透明程度是原来红色的50%。
在D3D中,alpha值的来源有三种:
- 顶点的diffuse color(漫反射光颜色)或specular color(镜面光颜色)
- Material(材质)的diffuse color
- 纹理的alpha channel
使用Material alpha
今天我们看一下如何使用material alpha来实现透明效果,主要的步骤如下:
定义material,并指定diffuse color
在定义Material时,一定要记得使用ZeroMemory将其清空,因为这里用的是局部变量,默认值不确定,如果不清空出现各种奇怪的效果。
HRESULT SetupMaterial(D3DXCOLOR color) { D3DMATERIAL9 material; ZeroMemory(&material, sizeof(material)); material.Ambient = color; material.Diffuse = color; material.Specular = color; material.Emissive = color; g_pd3dDevice->SetMaterial(&material); return D3D_OK; }
设置material为红色,且alpha值为0x80,这样产生的透明效果是原来颜色的50%。
// Setup material DWORD color = 0x80ff0000; SetupMaterial(color);
启用光照
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING , true );
设置material为diffuse material的来源
g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );
diffuse material的另外两种来源分别是顶点的diffuse color和specular color,对应代码如下
// Set vertex diffuse color as diffuse source g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 ); // Set vertex specular color as diffuse source g_pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR2 );
启用混合
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
开始混合
在下面的代码中,前面三行是指定两个color的来源及对应的操作,这里我们选择color的来源是diffuse color,操作是直接选择color1,而忽略color2,所以中间一句实际上可以省略。关于颜色的操作,还有很多其他类型,比如相加,相减等等,详情请看D3DTSS_COLOROP这个枚举类型。中间三句是选择两个alpha值的来源及对应他们的操作,也是从diffuse color中选择alpha值,操作也是直接选择第一个alpha值,而忽略第二个。最后三行开始真正的混合操作,第一行是指定源像素的alpha因子,这里是D3DBLEND_SRCALPHA,也就是直接使用alpha值,第二行指定目标像素的alpha因子,这里是D3DBLEND_INVSRCALPHA,相当于1 - alpha,最后一行是混合类型,这里是D3DBLENDOP_ADD,相加,所以最终的计算公式就是
OutputPixel = sourceColor * alpha + destColor * (1 - alpha)
在这里,源像素是指当前我们正在绘制的像素,而目标像素是指已经绘制到backbuffer中的像素。
// Set the color to come completely from the diffuse
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); //Set the alpha to come completely from the 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); // blend g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
效果图
Happy coding!!!
==
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
2009-08-27 也谈交换两个变量