1)ALPHA测试,裁剪像素
可以通过ALPHA测试,判定当ALPHA位于某个区间的像素输出或者不输出。这项技术运用于绘制铁丝网之类的“有洞”的纹理图像,比使用混合技术要来的节省资源。比如下面这幅纹理图片
左边是它的RGB颜色通道,右边是它的ALPHA灰度图,只有在网上才有ALPHA值。使用HLSL语言的内置函数clip(x),裁剪x<0的像素。从本质上讲,我们剔除了铁丝网上的非铁丝像素。
注意:由于该操作并不涉及混合,只是简单的测试ALPHA值。所以可以不必启用混合。(我在这里写这项技术貌似也不太对啊····别在意这些细节)
具体操作:在像素着色器中添加相关代码(下面是HLSL代码)
float4 PS(VS_OUT pIn) : SV_Target { float alpha = gDiffuseMap.Sample( gTriLinearSam, pIn.texC0 ).a; clip(alpha - 0.25f) float4 diffuse = gDiffuseMap.Sample( gTriLinearSam, pIn,texC1); float4 spec = gSpecMap.Sample (gTriLinearSam, pIn.texC1); spec.a *= 256.0f; float3 normalW = normalize(pIn.normalW); SurfaceInfo v = {pIn.posW,normalW,diffuse,spec}; float3 litColor = ParalleLight(v,gLight,geyePosW); return float4(litColor,alpha); }
注意:之所以要alpha - 0.25f 是为了增加容错性,当纹理图片经过过滤器时,会进行插值计算。
2)使用混合技术达到雾化效果
雾化效果是通过计算三角形上的像素点与摄像机的位置之间的距离,确定一个fogLerp。通过插值计算算出被雾化后的三角形颜色。
我们要使用的常量缓冲有:摄像机位置,雾的颜色,雾化范围,雾化起始点。
cbuffer cbFixed { float gFogStart = 5.0f; float gFogRange = 140.0f; float3 gFogColor = {0.7f, 0.7f, 0.7f}; };
cbuffer cbPerFrame { Light gLight; float3 gEyePosW; };
在顶点着色器中计算要雾化的三角形与摄像机位置的距离,从而计算fogLerp
float d = distance(vOut.posW, gEyePosW); //距离 vOut.fogLerp = saturate( (d - gFogStart) / gFogRange ); //雾化插值
一个距离对应一个雾化插值
在像素着色器中进行插值计算
//注意:该计算应该在完成光照计算与其他混合计算,ALHPA融合之后再进行
float3 foggedColor = lerp(litColor, gFogColor, pIn.fogLerp);
最后输出的就是混合了光照,物体材质,雾颜色的像素颜色。