1)ALPHA测试,裁剪像素

可以通过ALPHA测试,判定当ALPHA位于某个区间的像素输出或者不输出。这项技术运用于绘制铁丝网之类的“有洞”的纹理图像,比使用混合技术要来的节省资源。比如下面这幅纹理图片

image

左边是它的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);

最后输出的就是混合了光照,物体材质,雾颜色的像素颜色。

posted on 2013-03-08 17:11  曾健  阅读(597)  评论(0编辑  收藏  举报