引言

在前面几篇博文中,已经陆续讲解了光照处理,和纹理映射的内容。现在来讲解一些更有趣的东西。Alpha混合,总是出现在各种各样的游戏中。我们无时无刻都在和它进行打交道,所以很有必要掌握如何进行Alpha混合,以及如何通过Alpha混合来做到透明效果。

混合方程

进行Alpha混合时,我们总是会利用混合方程来进行混合。一般来说,混合方程总是如下所示:

OutputPixel =  SourcePixel * SourceBlendFactor + DestPixel * DestBlendFactor

这个方程很简单,而且其中的"+"操作符,也能够在DirectX中,通过设置渲染状态来改变这个值。我们进行Alpha混合的时候,就是设置这些值来对Alpha混合进行控制。

在默认情况下,Alpha混合方程中的操作符总是“+”,它在DirectX中使用如下的常量来定义:

D3DBLENDOP_ADD

除了这个操作符之外,还有下面的一些操作符:

D3DBLENDOP_SUBTRACT 表示操作符是“-”, 即混合方程为     OutputPixel =  SourcePixel * SourceBlendFactor - DestPixel * DestBlendFactor ;

D3DBLENDOP_REVSUBTRACT, 混合方程为 : OutputPixel =  DestPixel * DestBlendFactor - SourcePixel * SourceBlendFactor ;

D3DBLENDOP_MIN , 混合方程为 : OutputPiexl = min(SourcePixel * SourceBlendFactor, DestPixel * DestBlendFactor)  ;

D3DBLENDOP_MAX, 混合方程为:  OutputPiexl = max(SourcePixel * SourceBlendFactor, DestPixel * DestBlendFactor) ;

我们可以通过调用下面的函数来设置这些混合操作符:

m_pDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT) ;

这些操作符的具体含义很难察觉,它们只是定义了进行混合计算时的不同操作,使用不同的操作符可以达到不同的效果,需要读者自己积累经验来使用。

在默认情况下,DirectX 9.0是不进行Alpha混合操作的,所以我们可以通过如下的代码来开启Alhpa混合:

m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, true) ;

混合因子

在上面的混合公式中,SourceBlendFactor和DestBlendFactor称为混合因子。我们可以通过调用下面的两个函数来设置这两个不同的因子:

m_pDevice->SetRenderState(D3DRS_SRCBLEND, source) ;

m_pDevice->SetRenderState(D3DRS_DESTBLEND, dest) ;

上面的source和dest可以是下面的任何值:

  • D3DBLEND_ZERO : 表示混合因子为(0,0,0,0)
  • D3DBLEND_ONE : 表示混合因子为(1,1,1,1)
  • D3DBLEND_SRCCOLOR: 表示混合因子是(rs, gs, bs, as)
  • D3DBLEND_INVSRCCOLOR : 表示混合因子是(1 - rs, 1 - gs, 1 - bs, 1 - as)
  • D3DBLEND_SRCALPHA : 表示混合因子是( as, as, as, as)
  • D3DBLEND_INVSRCALPHA : 表示混合因子是( 1 - as, 1  - as , 1 - as, 1 - as)

除了上面讲述的,还有很多其他的混合因子,具体的可以查看DirectX附带的文档。

Alpha混合实现透明效果

我们来讲解下,如果通过Alpha混合来实现透明效果。

一个物体想要透明,在计算机图形学上,就是依靠于将需要进行透明处理的物体与背景上的像素值进行Alpha混合,从而达到透明的效果。而为了达到这样的效果,我们必须确保,不透明的物体要先被绘制出来,然后才能够绘制透明物体。因为不透明的物体后绘制出来的话,就没有办法进行Alpha混合,从而达到透明效果。

进行透明效果的Alpha混合公式如下:

OutputPiexl = SourcePiexl * SourceAlphaChannel + DestPiexl * (1 - SourceAlphaChannel)

所以,我们只要对需要进行Alpha混合的物体,调用上面讲述的方法,开启Alpha混合,并且将混合因子设置为D3DBLEND_SRCALPHA, 和 D3DBLEND_INVSRCALPHA,就可以了。

程序实例

下面就是进行Alpha混合的绘制代码:

void CubeDemo::draw()
{//Set the vertex declarationHR(m_pDevice->SetVertexDeclaration(VertexPNT::_vertexDecl));//Set the vertex bufferHR(m_pDevice->SetStreamSource(0,m_pVertexBuffer,0,sizeof(VertexPNT)));//Set the index bufferHR(m_pDevice->SetIndices(m_pIndexBuffer));//Create the world matrixD3DXMATRIX _worldM ;D3DXMatrixIdentity(&_worldM);//Set the techniqueHR(m_pEffect->SetTechnique(m_hTechnique));//Set the gWVP matrixD3DXHANDLE _hWVP = m_pEffect->GetParameterByName(0, "gWVP");HR(m_pEffect->SetMatrix(_hWVP, &(_worldM* m_ViewMatrix* m_ProjMatrix)));//Set the gWorld matrixHR(m_pEffect->SetMatrix(m_gWorld, &_worldM));//Set the gInverseTransposeD3DXMatrixInverse(&_worldM,NULL, &_worldM);D3DXMatrixTranspose(&_worldM, &_worldM);HR(m_pEffect->SetMatrix(m_gInverseTranspose, &_worldM));//Set the gPowerstatic float power = 5.0f;HR(m_pEffect->SetValue(m_gPower,&power,sizeof(float)));//Set the gMaterialHR(m_pEffect->SetVector(m_gMaterial,&D3DXVECTOR4(0.5, 0.7, 0.0, 0.5)));//Set the gLightColorHR(m_pEffect->SetVector(m_gLightColor, &D3DXVECTOR4(0.8, 0.8, 0.8, 1.0)));//Set the gLightVectorD3DXVECTOR4 lightVector ;D3DXVec4Normalize(&lightVector, &D3DXVECTOR4(1,1,1,0));HR(m_pEffect->SetVector(m_gLightVector, &lightVector));//Set the gSpecularLightColorHR(m_pEffect->SetValue(m_gSpecularLightColor, &D3DXCOLOR(1.0,1.0,1.0,1.0),  sizeof(D3DXCOLOR)));//Set the gSpecularMaterialHR(m_pEffect->SetValue(m_gSpecularMaterial, &D3DXCOLOR(0.2,0.2,0.2,1.0), sizeof(D3DXCOLOR)));//Set the gAmbientLightColorHR(m_pEffect->SetValue(m_gAmbientLightColor, &D3DXCOLOR(1.0,1.0,1.0,0.0),sizeof(D3DXCOLOR)));//Set the gAmbientMaterialHR(m_pEffect->SetValue(m_gAmbientMaterial, &D3DXCOLOR(0.5,0.5,0.5,0.0), sizeof(D3DXCOLOR)));//Set the gTexHR(m_pEffect->SetTexture(m_gTex, m_pTexture));//Begin passUINT _pass = 0 ;HR(m_pEffect->Begin(&_pass, 0));HR(m_pEffect->BeginPass(0));//Draw the primitivedrawCube();//Draw the teapotdrawTeapot();//End passHR(m_pEffect->EndPass());HR(m_pEffect->End());
}
void CubeDemo::drawCube()
{m_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,24,0, 12);
}void CubeDemo::drawTeapot()
{//Enable the alpha blendHR(m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true));HR(m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA));HR(m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA));D3DXMATRIX _worldM;D3DXMatrixTranslation(&_worldM,0,0,-5);HR(m_pEffect->SetMatrix(m_gWVP, &(_worldM* m_ViewMatrix* m_ProjMatrix)));//Set the gWorld matrixHR(m_pEffect->SetMatrix(m_gWorld, &_worldM));//Set the gInverseTransposeD3DXMatrixInverse(&_worldM,NULL, &_worldM);D3DXMatrixTranspose(&_worldM, &_worldM);HR(m_pEffect->SetMatrix(m_gInverseTranspose, &_worldM));//Commit the changesHR(m_pEffect->CommitChanges());HR(m_TeaportMesh->DrawSubset(0));HR(m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false));
}

在上面的代码中,我们将gMaterial的Alpha值设置为0.5,在Shader中,会使用这个变量来作为最终像素的Alpha值返回,然后交给光栅化函数自动的进行Alpha混合操作,下面是本次实例的Shader文件:

//---------------------------------------------------------------------------
// declaration  : Copyright (c), by XJ , 2014 . All right reserved .
// brief    : This file will define the Texture_Direction Shader.
// date     : 2014 / 5 / 29
//----------------------------------------------------------------------------
uniform float4x4 gWVP ;             //这个变量将会保存世界变换矩阵*相机变换矩阵*透视投影矩阵的积//用这个矩阵,将点转化到裁剪空间中去uniform float4x4 gInverseTranspose;       //这个变量将会保存世界变换矩阵的逆矩阵*转置矩阵,用来对法向量进行变换uniform float4   gMaterial;         //这个变量用来保存顶点的材质属性,在本Demo中,将对所有的顶点使用相同的//材质uniform float4   gLightColor;           //这个变量将用来保存一个平行光的颜色uniform float3   gLightVector;           //这个变量用来保存平行光的光照向量uniform float4x4 gWorld;          //这个变量保存世界变换,用来对模型坐标进行变换,从而计算视向量uniform float3   gEye;                //这个变量保存视点的位置,也就是相机的位置uniform float    gPower    ;           //这个变量将会控制反射光的衰减速度uniform float4   gSpecularLightColor;     //反射光颜色uniform float4   gSpecularMaterial;      //物体对反射光的材质属性uniform float4   gAmbientLightColor;           //环境光颜色uniform float4   gAmbientMaterial;              //物体对环境光的材质属性uniform extern texture gTex ;           //定义纹理//定义采样器
sampler TexS = sampler_state
{Texture = <gTex> ;MinFilter = LINEAR ;MagFilter = LINEAR ;MipFilter = LINEAR ;
};//定义顶点着色的输入结构体
struct OutputVS
{float4 posH : POSITION0 ;float2 tex0 : TEXCOORD0 ;float3 normalW : TEXCOORD1 ;float3 posW : TEXCOORD2 ;
};OutputVS TextureVS(float3 posL: POSITION0, float3 normalL: NORMAL0, float2 tex:TEXCOORD0)
{//清空OutputVSOutputVS outputVS = (OutputVS) 0 ;//对顶点的法向向量进行变换normalL = normalize(normalL);float3 normalW = mul(float4(normalL, 0.0f),gInverseTranspose).xyz;normalW = normalize(normalW);//保存法相向量outputVS.normalW = normalW ;//保留顶点的世界坐标float3 posW = mul(float4(posL, 1.0), gWorld).xyz ;outputVS.posW = posW ;//使用gWVP将世界坐标转化为裁剪坐标outputVS.posH = mul(float4(posL, 1.0f), gWVP);//保存纹理坐标outputVS.tex0 = tex ;//返回结果return outputVS ;
}// end for Vertex Shaderfloat4 TexturePS(float2 tex0:TEXCOORD0, float3 normalW:TEXCOORD1, float3 posW:TEXCOORD2): COLOR
{//--------------------------------------------------// 光照计算//--------------------------------------------------//进行插值后,法相向量不再是归一化的,重新进行归一化操作normalW = normalize(normalW);//根据漫反射公式:// Color = max(L * Normal, 0)*(LightColor*Material)float s = max(dot(gLightVector,normalW), 0);float3 diffuse = s*(gMaterial*gLightColor).rgb ;//根据环境光公式:// Color = AmbientColor * AmbientMaterialfloat3 ambient = (gAmbientLightColor * gAmbientMaterial).rgb ;//根据反射光公式:// Color = pow((max(dot(r,v),0)),p) * (SpecularLightColor*SpecularMaterial)float3 view = gEye - posW ;view = normalize(view);float3 ref = reflect(-gLightVector, normalW);float t = pow(max(dot(ref,view),0),gPower);float3 specular = t * (gSpecularLightColor * gSpecularMaterial).rgb ;//--------------------------------------------------------------------//  获取纹素//--------------------------------------------------------------------float3 pixel_color = tex2D(TexS, tex0).rgb;diffuse = (diffuse + ambient) * pixel_color ;return float4(diffuse + specular, gMaterial.a) ;
}// end for Pixel Shadertechnique TextureTech
{pass P0{vertexShader = compile vs_2_0 TextureVS();pixelShader =  compile ps_2_0 TexturePS();}
}

最后是程序运行的最终结果图:

好了,今天就到此结束了!!!

DirectX9.0 (10) Alpha混合相关推荐

  1. 深度测试与alpha混合(3)

    alpha源混合系数通常设置为D3DBLEND_SRCALPHA,即当前绘制像素的alpha值.目标混合系数设置为D3DBLEND_INVSRCALPHA,即1减去当前绘制像素的alpha值.那么当前 ...

  2. 深度测试与alpha混合(1)

    深度测试与alpha混合(1) 在绘制复杂的三维场景时,不可避免地会出现物体间的相互遮挡,在这种情况下,为了正确地绘制场景需要使用深度测试.半透明物体的绘制不同于不透明物体,Direct3D通过alp ...

  3. 【STM32F429开发板用户手册】第46章 STM32F429的DMA2D应用之刷色块,位图和Alpha混合

    最新教程下载:http://www.armbbs.cn/forum.php?mod=viewthread&tid=93255 第46章       STM32F429的DMA2D应用之刷色块, ...

  4. alpha混合原理(2)

    alpha混合原理 在前面介绍的示例程序中,绘制图形的颜色总是替换当前颜色缓冲区中存在的颜色,这样后面的物体总是覆盖在原有的物体上.但是当想要绘制类似于玻璃.水等具有透明效果的物体时,这种方法显然满足 ...

  5. 【Visual C++】游戏开发五十五 浅墨DirectX教程二十二 水乳交融的美学:alpha混合技术

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/15026917 作者:毛星 ...

  6. SwiftStack迎来v5.0,向混合IT规则张开怀抱

    SwiftStack v5的Cloud Sync提供双向复制通道,用于加快内部数据中心与Google Cloud Storage.Amazon S3以及Glacier之间的数据传输. SwiftSta ...

  7. 图解Ubuntu 9.10 Alpha 6

    Ubuntu 9.10 Alpha6发布了.Ubuntu 9.10目标于2009年10月29日正式发布,目前的Alpha 6采用了Linux 2.6.31内核和GNOME 2.28 RC1 桌面环境, ...

  8. Windows的位图alpha混合技术

    摘 要:本文介绍了在Windows环境下对位图的图像alpha混合技术,提供了alpha混合函数的实现方法,并对Windows API提供的alpha混合函数的使用进行了介绍. 关键词:Windows ...

  9. OPPO Reno配置曝光 骁龙855+10倍混合光学变焦

    [TechWeb]今日,微博"科技小公举"疑似透露OPPO Reno详细配置信息. 图片显示,OPPO Reno将搭载高通骁龙855移动平台,10倍混合光学变焦技术,搭载4800W ...

最新文章

  1. FusionCharts Free(3)
  2. python | 三种可变参数简述
  3. 为什么 窗口回调函数要使用静态成员函数
  4. STORM之ITridentSpout、FirstN(取Top N)实现、流合并和join
  5. OFD文件结构--OFD.xml
  6. 『NLP学习笔记』AllenNLP的注册机制
  7. Intellij IDEA2017破解
  8. 一个老程序员在情人节对中国软件业的致言!(转)
  9. 苹果六现价多少钱_六克拉的Derier多少钱 六克拉钻戒多少钱
  10. 【团体天梯赛/PTA】7-34 福到了 (15 分)
  11. python如何回退_Pycharm技巧之代码跳转该如何回退
  12. 如何安装Python?
  13. 《以幽默的方式过一生》-琢磨先生读书笔记
  14. java中几种创建对象的方式
  15. python爬虫ip代理没有作用_可能是一份没什么用的爬虫代理IP指南
  16. WeChall CTF Writeup(七)
  17. Centos安装ffmpeg视频处理工具(带安装h264编码格式插件)
  18. java生成文字与图片_java生成word(文字和图片)
  19. 怎样做研究(转载哈工大刘挺教授博客内容)
  20. Lady Gaga 《The cure》——好听的英文歌曲《治愈》【英汉互译】

热门文章

  1. MATLAB 绘制数据图
  2. Ubuntu 安装时出现“failed to load ldlinux.c32” 方法总结
  3. 使用iframe的正确姿势
  4. Extjs 4.0 textarea 滚动条自动到最低
  5. SQL 入门,看这篇就够了 ---- 基础篇
  6. 安卓自动无限试玩,只需一根WiFi玩法
  7. Linux学习笔记二十九——http服务
  8. 模拟美萍加密狗--Rockey2虚拟狗(三)
  9. 如何基于虚拟化和SDN实现虚拟化的蜜网
  10. Revit 中注释族的应用详解及公共族库工具