GPU Pro 2 ------ Volume Decals

1649 篇文章 11 订阅
1623 篇文章 22 订阅

花了$60买了正版的GPU Pro2。坚持每天学一点。

边学习边翻译,希望也能对别人有些益处。从Volume Decals 开始,可以从Emil Persson 的官网上下到源代码 http://www.humus.name/index.php?page=3D&ID=83


Volume Decals

                           Emil Persson

5.1 介绍

贴花通常应用于放置在场景几何体面上的贴图。在大部分情况下,这个应用都表现的很好。用贴图四边形来做贴花会造成Z-fighting的问题。在下面的几何体可能不平坦,造成贴花就绘制在了几向体的下面。在边缘处,贴花也有可能出现悬挂的情况。解决这个问题通常的办法是对贴花引入裁剪或者在这种情况下就不做贴花。将贴花合适的贴在任意的模型上需要很复杂的代码,必须要取得模型的顶点。在PC上意味着如果要取得很好的性能,就必须把模型几何体信息拷贝一份到内存中。有一个典型的例子,向一块石头射击,贴花可能没有跟对齐中心。这篇文章用体积贴花投影到场景几何体上的方法解决了所有的问题,这里面用到了深度缓存。


5.2 体积贴花

5.2.1 找到场景坐标

这个技术的想法是在选中的区域把贴花当成一个体积来渲染。任何一种凸的几何体都可以,但一般都用球或者盒子。通过采样深度缓存,fragment shader 计算在下面的几何体的位置。可以通过下面的方法实现:

// texCoord is the pixel's normalized screen position
float depth = DepthTex.Sample(Filter, texCoord);
float4 scrPos = float4(texCoord, depth, 1.0);
float4 wPos = mul(scrPos, ScreenToWorld);

图 5.1 贴花实例

float3 pos = wPos.xyz /wPos.w;
// pos now contains pixel position in world space

ScreenToWorld 矩阵是一个复合矩阵,包含了两个转换:从屏幕坐标系到裁剪坐标系,从裁剪坐标系到世界坐标系。从世界坐标到裁剪坐标是由ViewProjection矩阵完成的,所以这里要用这个矩阵的逆。裁剪空间范围x和y是从-1到1,然而贴图坐标是从0到1,所以我们需要一个对齐的操作。由以下的代码完成:

float4 ScaleToWorld = Scale(2, -2, 1) * Tranlate(-1, 1, 0) * Inverse(ViewProj);

我们感兴趣的是体积贴花和这个局部位置的关系。这个局部位置会被当成贴图坐标去采样一个体积贴花。因为这个贴花是个体积贴图,它会非常好的包裹着非连续性的特殊的图形(图5.2)。为了给每一个贴花唯一表现,可以给这个矩阵加一个随机的旋转。可以通过下面来构造:


float4 ScreenToLocal = Scale(2, -2, 1) * Translate(-1, 1, 0) * Inverse(ViewProj) * DecalTranslation * DecalScale * DecalRotation;

全部的fragment shader如下:

Texture2D<float> DepthTex;
SamplerState DepthFilter;

Texture3D<float4> DecalTex;
SamplerState DecalFilter;

cbuffer Constants
{
    float4x4 ScreenToLocal;
    float2 PixelSize;
};

float4 main(PsIn in) : SV_Target
{
    // Compute normalized screen position
    float2 texCoord = In.Position.xy * PixelSize;

    // Comput local position of scene geometry
    float depth = DepthTex.Sample(DepthFilter, texCoord);
    float4 scrPos = float4(texCoord, depth, 1.0f);
    float4 wPos = mul(scrPos, ScreenToLocal);

    // Sample decal
    float3 coord = wPos.xyz / wPos.w;
    return DecalTex.Sample(DecalFilter, coord);
}

5.2.2 开发和问题

这个系统可以在延迟渲染技术中实现的相当完美。贴花可以在geometry buffer (G-buffer) pass之后渲染,而且还可以将一些diffuse color,specularity color应用上去。这个技术同样适用于预渲染,意味着在贴花中还可以应用光照信息。

在前向渲染系统中,贴花必须在光照计算之后。举例说一些情况,爆炸后的烧焦的样子呀,贴花可以很好的与目标缓存进行试算。更复杂的一些情况是,用alpha 进行混合,常用于子弹打出一个洞,这种情况下,必须考虑到光照。其中一个解决方案是,当渲染时,在shader中的alpha通道中保存所有光照的亮度;在贴花时能将每个颜色通道预乘以alpha,在混合器中与目标透明度相乘以得到较好的效果。这并没有将灯光的颜色考虑在内,但如果灯光是清楚的白色,结果还是很好的。另一个解决办法是利用最近一个灯光的衰减数,不考虑法线。相应的,法线可以从深度缓存中得到,尽管这会很慢。

这种贴花技术有一个问题是,会在体积贴花内的所有的物体上应用上贴花。对于静态物体这没有问题,但如果你有一个巨大的贴花,然后有一些动态的物体在其内移动,这些动态的物体会得到贴花污点在其上面,举个例子,比如之前有一个炸弹在道路上弹了,之后有一个汽车从上面开过。这个问题可以通过在贴花之后渲染动态物体来解决。一个更好的解决办法是按出现的先后顺序去渲染,这样之后移动到贴花上的物体就不会受到贴花的影响。还有一个解决办法,是使用物体的ID号,贴花可以记录会应用贴图的物体。


5.2.3 优化

在一些平台上支持depth-bounds测试,depth-bounds测试会用于提高性能 。在其它一些平台上,动态分支会用于仿真这一功能,通过对比采样的深度缓存和depth-bounds。无论如何,这样Shader会短一些,很大一部分fragment 可以避免做深度测试。在一些情况下,如果不裁剪任何东西会更快一些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值