gpu gem, nvidia纹理阴影实现对比

代码下下来,用2012编译,
http://developer.download.nvidia.com/SDK/10.5/direct3d/samples.html


找到soft shadowmap的那个例子,缩略图是一个武士拿着剑站在草地上


我的笔记本显卡的glsl版本是 4.3的,
编译完一跑就报错,
修改SoftShadows.cpp 288行
    NvScopedShaderPrefix switched(
    (getGLContext()->getConfiguration().apiVer.api == NvGfxAPI::GL)
    ? "#version 430\n" :         ------------ 原来是440,笔者改成430
    "#version 310 es\n#extension GL_ANDROID_extension_pack_es31a : enable\nprecision mediump float;");
    
最终的结果是跑几帧,显卡就死了, 笔者的显卡是intel r hd graphics family,上网一查,据说挺低端的,
再一看shader代码,pcf最低要两次25x25泊松采样(一次用于判断是否在阴影之中,一次用于加权计算阴影)
更高的还有100x100,渲染一个像素就要2万次阴影纹理采样。


笔者的配置跑代码看来是没希望了.


看了shader代码,其实也简单.


有两个版本的渲染,在比较深度是,用的是texture,软阴影的主要贡献应该是这段代码,
return ((uvz.x <= 1.0) && (uvz.y <= 1.0) &&
(uvz.x >= 0.0) && (uvz.y >= 0.0)) ? texture(tex, uvz) : 
((uvz.z <= 1.0) ? 1.0 : 0.0);




第一次随机采样用于判断点是否处于阴影之间,
根据距离来判断,查表(泊松分布),将全部的采样点贡献值综合判断是否处于阴影之中,
采样半径随点与光源的距离而扩大,起到lod的效果


第二次随机采样,开始正式计算该点的阴影权值




最终结果是,在笔者的烂本上,帧率为个位数,并且跑几帧就死


========================= 分割线 =================================


再来gpu gems的例子,
lod采用ddx ddy(opengl对应的函数是dFdy dFdx)


采样块的大小根据ddx ddy计算出来,即观察者(就是投影近平面)离点越近,采样块数越小(此时ddx ddy的值也小),
而当观察远离点是,ddx ddy的值越大,采样块数越大,同时设定一个上限与下限.
实现了lod效果
软阴真正起到贡献作用的是采样过滤函数 SampleCmpLevelZero


最终的软影效果也不错,在笔者的烂本上,中等效果的软影跑出了近150的帧率(最高pcf采样帧率也会到个位数,但不会死机),
效果已经能接受, 观察了一些例子,pcf时会有影子与物体分离的现象,应该是z_proj非线性造成的.




综合比较,gem的例子比较现实.


====================== 分割线 =========================
笔者的实践:


步骤一: 渲染深度至纹理 
步骤二: 绘制整个场景
步骤三: 绘制阴影


2,3可以合并成一个步骤,分开只是为了利于代码组织。


在绘制阴影时,阴影纹理绑定成sampler2DShadow类型,利用shadow2D来进行权值过滤。别傻乎乎地自个儿写代码过滤权值,
吃力不讨好。利用泊松随机过滤效果一般,只会产生一些噪声点,拉近看,还是会觉得怪异。


1 采用透视投影的深度值Zproj,偏压不容易计算,而且离灯光越远,越容易产生阴影与物体分离的现象,
所以深度值可以尝试做一个变通。改成 (Zview - Znear)/(Zfar-Znear),这样绕开在Zproj的非线性问题
2 偏压采用三角面与光源夹角来计算,夹角越小,偏压可以越小
3 采样过多会降低帧率,所以最好做边缘检测,只需要对边缘附近的点进行pcf,可以提高pcf采样块数


第3点能省掉不少的采样,因阴影纹理特点是一大片是影子,一大片是没有影子,对于一些"内部采样"不需要做多余的纹理采样操作.
边缘检测可以简单是根据采样块大小,只扫描外围8采样点,以及当前采样点,如果都处于阴影之中,或者都不处于阴影之中,就认为是

内部点,不做pcf


笔者的软影效果


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值