这几天加入了shadowmap影子,着实费了点脑子看起来很简单的,可这东西牵扯到很多东西,场景要成像的对象都要统一纳入深度图里面渲染一遍,加了很多渲染方面的组织代码,静态模型,骨骼模型,等等,都要影子,渲染的方法还略有区别,真是很繁琐,眼看就要成功了,可烦心事又来了,灯光没办法穿透alpha纹理,那些树叶都是一大片一大片的,根本不透光,场景中为了节约三角形,要做alphatest的纹理比比皆是,如果光线穿不透alpha纹理,那可太糟糕了,在gameres上问了一把,clayman和六水两位大侠给了我不小的帮助,主要的思路是深度图是需要做alphatest的,这样才能被穿透,直接用R32F我试过了,alphatest根本无效,也不知道是不是显卡太差了,看了一篇文章,
GPU GEM1
http://http.developer.nvidia.com/GPUGems/gpugems_ch12.html有提到这个算法,可以把R32F转换为A8R8G8B8即可节约内存又可以提高兼容性,很多显卡还不支持R32F呢,
这就涉及到一个压缩和解压的算法,那篇NV的文章说的太抽象,很不具体,试了很久也不成功。
网上找了一个晚上加一上午的时间,终于找到了答案
http://www.gamedev.net/community/forums/topic.asp?topic_id=442138这个主题就是讨论这个算法的。
其中:
float4 pack(float fDist)
{
const float4 bitSh = float4( 256*256*256, 256*256, 256, 1);
const float4 bitMsk = float4( 0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
float4 comp;
comp = fDist * bitSh;
comp = frac(comp);
comp -= comp.xxyz * bitMsk;
//我这里稍微该了改,把最后低的精度移到了末尾
return float4(comp.y, comp.z, comp.w, comp.x);
}
float unpack(sampler ShadowMapS, float2 texcood)
{
float4 vec = tex2D(ShadowMapS, texcood);
//我这里稍微该了改,把最后一个精度移到了末尾
const float4 bitShifts = float4(1.0/(256.0*256.0), 1.0/256.0, 1, 1.0/(256.0*256.0*256.0));
//return vec.x*1.0/(256.0*256.0*256.0) + vec.y* 1.0/(256.0*256.0) + vec.z*1.0/256.0 + vec.w;
return dot(vec.xyzw , bitShifts);
}
//以下是shadowmap的拍摄过程
void BuildShadowMapVS(float3 posL : POSITION0,
float3 normalL : NORMAL0,
float2 tex0 : TEXCOORD0,
out float4 posH : POSITION0,
out float2 depth : TEXCOORD0,
out float2 tex1 : TEXCOORD1
)
{
// Render from light's perspective.
posH = mul(float4(posL, 1.0f), gLightWVP);
// Propagate z- and w-coordinates.
depth = posH.zw;
tex1 = tex0;
}
float4 BuildShadowMapPS(float2 depth : TEXCOORD0, float2 tex1 : TEXCOORD1) : COLOR
{
// Each pixel in the shadow map stores the pixel depth from the
// light source in normalized device coordinates.
float a = tex2D(TexS, tex1).a;
float f = clamp(depth.x / depth.y , 0, 1);
float4 val=pack(f);
if(a < 0.5)
val.a = 0.0f;
else
val.a = 1.0f;
return val;
}
就是关键的float与A8R8G8B8之间的压缩和解压的算法,其中
comp -= comp.xxyz * bitMsk;很难理解,但仔细想一想你就能想明白其中的道理
这个是可以转换了,但里面还有更为关键的东西,还要把A8的alpha信息加进去,不然还是不能做影子的alpha测试,根据六水兄的提议,我也忽略了256*256*256末尾的精度,加入了成像纹理的alpha信息,这样最终实现了光线对alpha纹理的穿透,还真是不容易,发图出来鉴赏一下这两天的成果: