神器oDepth

    关于Depth Buffer是做什么的,搞过渲染的人都会有100%的自信来回答是用来做什么的,Depth Buffer里保存的是什么东西大家应该也比较清楚,而且怎么从投影空间转换到世界坐标系稍微花点功夫就可以保证正确。

    如果需要为某一个像素写入指定的深度值该怎么办?Depth Buffer的值是GPU完成光栅化之后写进去的,似乎不好人工干预。嗯,的确。但是DX还是留了接口的,只是这个接口平时真的很少用到,以至于大家可能都忽略了这个东西,这个东西就是神器oDepth寄存器,它可以让开发者在PS里为某一个像素输出任何自己想要的值,并且用这个值来覆盖掉光栅化输出的深度值。它的使用方法很简单,如下:

float4 pixelShader(PsInput input,out float outDepth : DEPTH):COLOR0
{
    float4 depth = ?;//你想输出的深度值
	
    outDepth = depth.x;
    return 0;
}

   按照上面的方法就可以输出指定的深度值到Depth Buffer了。但是这个东西有什么用呢,下面我将会记录一下实际开发中具体的应用:

1.Restore Quarter Depth Buffer

    用Quarter Buffer画特效或者AO是一个经常使用的优化,在很多商业游戏里都得到了广泛应用。这个优化采用的是Quarter Buffer来进行的,像素的遮挡关系也需要在Quarter Buffer上来进行,也就是说需要一个Quarter Depth Buffer,这个Depth Buffer当然你也可以把所有的不透明物体再画一遍来生成Quarter Depth,但是这样太费了,所有不透明物体再画一下消耗很大。这时候oDepth的优势就很明显了,只需要一个全屏Quad,采一下全分辨率的深度输出到oDepth即可。可以参考GPU Gems3第23章
 float4 particlePS(VS_OUT vIn): COLOR  
{  
  float myDepth = vIn.depth;  
  float sceneDepth = tex2D(depthSampler, vIn.screenUV).x;  
  if (myDepth > sceneDepth)  
    discard;  
  // Compute color, etc.  
  . . .  
} 

2.Billboard Leaf Self Shadow

很多游戏里树叶采用的是Leaf Card俗称Billboard,因为这样做树叶显得很茂密,而且美术很容易编辑,并且性能也不错。但是这个世界没有万能的东西(上本科时有一次院长来听电子材料老师的课,讲到一个电子材料的时候老是说这个材料非常好,既可以做温度传感器也可以做压力传感器,还可以做光敏器件,大家当时都觉得这个材料真好,下了课之后院长说了几句话我记忆非常深刻,院长说如果这个材料对温度,压力,光都敏感那说明它不适合做传感器,如果你用它做压力传感器来测试压力,周围的温度变化了不就测不准了...果然是院长)言归正传,Leaf Card因为是面片的原因,画影子深度的时候也是一个面片的深度,这样就导致最后算影子的时候Leaf Card的自阴影有一个很明显的切痕,这个在很多游戏里都是一个普遍问题,SpeedTree在这个问题上给出了解决方案,简单来说就是根据uv采了一个offset纹理对Billboard的Mesh的做了个扭曲或者说是扰动,这样的确可以解决self shadow的问题(之前担心手工干预depth的写入的时候还会用的深度测试也就是读取depth,这样可能会有潜在问题到时候查死人,跟NV的大神确认了一下,不会有问题。)
float PSShadowMapFetch(Input In)
{
  // Let In.VP and In.VV be float3;
  // In.VP - interpolated Vertex Position output by VS
  // In.VV - View Vector output by VS
  // OCT - Offset Coefficient Texture
  // SMPP - Shadow Map Pixel Position
  // SMMatrix - transform to Shadow Map space
  float3 SMPP = In.VP + In.VV * tex2D(OCT, In.TexCoord).x;
  float3 SMCoord = mul(SMMatrix, float4(SMPP, 1));
  float SM = tex2D(SMTexture, SMCoord);
  return SM;
}
    这个方法是在画树叶的时候才计算的阴影,所有这时候是可以得到uv的,如果是Deferred Shadow这样做就不行了,因为Deferred Shadow只能得到shdow depth和场景的depth,无法得到树叶的uv,也就无法采offset贴图了。难道Deferred Shadow就无法解决这个问题么,一开始我们也是这么认为的,后来想了大半天才恍然大悟,对于Deferred Shadow只需要在画Shadow Depth的时候将被offset的深度输出就可以了,的确,oDepth又可以大干一场了,果断试了一下,在画Shadow Depth的PS里采了一下offset texture然后输出到oDepth里完美的解决了自阴影问题。
    其实还有第三种应用,只是现在还不能透漏,等时机成熟再补进来吧。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值