Alpha Mapping

来源:互联网 发布:alphago原理讲解 知乎 编辑:程序博客网 时间:2024/06/06 02:00

阿尔法通道:

(α Channel或Alpha Channel)是指一张图片的透明和半透明度。例如:一个使用每个像素16比特存储的位图,对于图形中的每一个像素而言,可能以5个比特表示红色,5个比特表示绿色,5个比特表示蓝色,最后一个比特是阿尔法。在这种情况下,它要么表示透明要么不是,因为阿尔法比特只有0或1两种不同表示的可能性。又如一个使用32个比特存储的位图,每8个比特表示红绿蓝,和阿尔法通道。在这种情况下,就不光可以表示透明还是不透明,阿尔法通道还可以表示256级的半透明度,因为阿尔法通道有8个比特可以有256种不同的数据表示可能性。(引自维基百科)

先看效果,这里上一篇博客里的纹理,加上Alpha Mapping 之后做成的效果.
                                      
左侧为使用Alpha Mapping的效果,右侧法线贴图的效果.


我们先来看一下代码,这个是怎么实现的,在Vertex Shader里面还是和 Normal Mapping一样.在这就不一一介绍了,在法线贴图里面有关于切空间的解释,

这是主要的代码意思是将光线和视线变换到正切空间,而world矩阵为单位阵所以不用先变换法线.
float4x4 matWorldViewProjection;float4x4 matWorld;float4 vViewPosition;float3 vLight;struct VS_INPUT {      float4 Position : POSITION0;      float2 TexCoord : TEXCOORD0;      float3 Normal   : NORMAL0;      float3 Binormal : BINORMAL0;      float3 Tangent  : TANGENT0;};struct VS_OUTPUT {      float4 Position : POSITION0;      float2 TexCoord : TEXCOORD0;      float3 Eye      : TEXCOORD1;      float3 Light    : TEXCOORD2;};VS_OUTPUT vs_main( VS_INPUT Input ){      VS_OUTPUT Output;            Output.Position = mul( Input.Position, matWorldViewProjection );      Output.TexCoord = Input.TexCoord;         float3 world = mul (Input.Position, matWorld);      float3 eye = vViewPosition - world;   //视线            //将光线和视线变换到正切空间,world矩阵为单位阵所以不用先变换法线      Output.Eye.x = dot(Input.Tangent, eye);      Output.Eye.y = dot(Input.Binormal, eye);      Output.Eye.z = dot(Input.Normal, eye);            Output.Light.x = dot(Input.Tangent, vLight);      Output.Light.y = dot(Input.Binormal, vLight);      Output.Light.z = dot(Input.Normal, vLight);           return( Output );}


有区别的地方是Pixel Shader里面的代码,下面是Pixel Shader 里面的代码:
float4 AmbientColor;float4 DiffuseColor;float4 SpecularColor;float SpecularIntensity;float SpecularPow;sampler2D TextureMap;sampler2D NormalMap;sampler2D AlphaMap;struct PS_INPUT {      float2 TexCoord : TEXCOORD0;      float3 Eye      : TEXCOORD1;      float3 Light    : TEXCOORD2;};float4 ps_main( PS_INPUT Input ) : COLOR0{      //贴图颜色,环境光和漫反射光照亮这个颜色      float4 baseColor = tex2D(TextureMap, Input.TexCoord);         float3 light = normalize(Input.Light);      float3 eye = normalize(Input.Eye);      float3 normal = normalize(tex2D(NormalMap, Input.TexCoord).xyz * 2.0f - 1.0f);            float ndl = saturate(dot(light, normal));      //光线的反射方向r      float3 r = normalize(reflect(-light, normal));      float rdv = pow(saturate(dot(r, eye)), SpecularPow);      //光照方程      float4 color = AmbientColor * baseColor + DiffuseColor * baseColor * ndl + SpecularColor * SpecularIntensity * rdv;            //根据alphamap设置alpha值    color.w = dot(tex2D(AlphaMap, Input.TexCoord).xyz, float3(0.3f, 0.59f, 0.11f));    return color;}        
//根据alphamap设置alpha值 color.w = dot(tex2D(AlphaMap, Input.TexCoord).xyz, float3(0.3f, 0.59f, 0.11f)); return color;}





其中里面  float3 normal = normalize(tex2D(NormalMap, Input.TexCoord).xyz * 2.0f - 1.0f);

Tangent Space(切空间)中,新的normal值就是z轴方向,也就是说值为(0, 0, 1)。但这并不是法线纹理中存储的最终值,因为一个向量每个维度的取值范围在(-1, 1),而纹理每个通道的值范围在(0, 1),因此我们需要做一个映射,即pixel = (normal + 1) / 2。




  color.w = dot(tex2D(AlphaMap, Input.TexCoord).xyz, float3(0.3f, 0.59f, 0.11f));

其中这一行代码是根据alphamap设置alpha值,float3(0.3f, 0.59f, 0.11f)是灰度值,使AlphaMap纹理的颜色转化为灰色,从而形成上图中间的黑色阴影的部分.  






1 0
原创粉丝点击