這幾天加入了shadowmap影子,著實(shí)費(fèi)了點(diǎn)腦子看起來很簡單的,可這東西牽扯到很多東西,場(chǎng)景要成像的對(duì)象都要統(tǒng)一納入深度圖里面渲染一遍,加了很多渲染方面的組織代碼,靜態(tài)模型,骨骼模型,等等,都要影子,渲染的方法還略有區(qū)別,真是很繁瑣,眼看就要成功了,可煩心事又來了,燈光沒辦法穿透alpha紋理,那些樹葉都是一大片一大片的,根本不透光,場(chǎng)景中為了節(jié)約三角形,要做alphatest的紋理比比皆是,如果光線穿不透alpha紋理,那可太糟糕了,在gameres上問了一把,clayman和六水兩位大俠給了我不小的幫助,主要的思路是深度圖是需要做alphatest的,這樣才能被穿透,直接用R32F我試過了,alphatest根本無效,也不知道是不是顯卡太差了,看了一篇文章,
GPU GEM1
http://http.developer.nvidia.com/GPUGems/gpugems_ch12.html有提到這個(gè)算法,可以把R32F轉(zhuǎn)換為A8R8G8B8即可節(jié)約內(nèi)存又可以提高兼容性,很多顯卡還不支持R32F呢,
這就涉及到一個(gè)壓縮和解壓的算法,那篇NV的文章說的太抽象,很不具體,試了很久也不成功。
網(wǎng)上找了一個(gè)晚上加一上午的時(shí)間,終于找到了答案
http://www.gamedev.net/community/forums/topic.asp?topic_id=442138這個(gè)主題就是討論這個(gè)算法的。
其中:
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);
//我這里稍微該了改,把最后一個(gè)精度移到了末尾
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;
}
就是關(guān)鍵的float與A8R8G8B8之間的壓縮和解壓的算法,其中
comp -= comp.xxyz * bitMsk;很難理解,但仔細(xì)想一想你就能想明白其中的道理
這個(gè)是可以轉(zhuǎn)換了,但里面還有更為關(guān)鍵的東西,還要把A8的alpha信息加進(jìn)去,不然還是不能做影子的alpha測(cè)試,根據(jù)六水兄的提議,我也忽略了256*256*256末尾的精度,加入了成像紋理的alpha信息,這樣最終實(shí)現(xiàn)了光線對(duì)alpha紋理的穿透,還真是不容易,發(fā)圖出來鑒賞一下這兩天的成果:
