首页 > 其他分享 >体探针漏光解决方案

体探针漏光解决方案

时间:2024-04-11 11:16:12浏览次数:38  
标签:Cube Bent 漏光 Normal 解决方案 Probe 探针 偏移

【USparkle专栏】如果你深怀绝技,爱“搞点研究”,乐于分享也博采众长,我们期待你的加入,让智慧的火花碰撞交织,让知识的传递生生不息!


问题描述

在全局照明领域,体探针插值漏光是存在多年的顽疾。比如:GAMES202的LPV(Light Propagation Volumes);Unity的LPPV(Light Probe Proxy Volume);GDC上各种GI分享(某版COD);还有之前我给项目实现的类似UE VLM的功能,都存在这个问题。和很多技术人员一样,一看到行业困难的技术点,就会自己动脑想一套更好的方案来解决它,因为这样可以名正言顺的造轮子。

 


GAMES202里GI部分提及的漏光问题

  


Unity LPPV 漏光问题

 

基础思路

 


被墙隔离的探针关系

 

根本的原因当然是探针的密度不可能无限密,而且分空间的表面可以没有厚度。而一般的探针信息里并没有描述空间划分的逻辑,上图中只有红色探针往左和绿色探针往右2个区域是正确的,中间的插值就出错了。所以,所有的思路都是去描述空间的划分,或表面上一个像素与体素的归属关系修复上,就是让A点只采样红色探针,B点只采样绿色探针,因为他们的空间归属如此。

方案1:Bent Normal偏移

我没有把简单Normal偏移作为一种方案,因为这种太基础了。而我在写初版VLM的时候就顺手写了出来,基本是非常容易想到的,而且效果也不够好。看下图,AB有个简单的区分方式,就是它们法线不同,沿着各自法线方向去取探针,会得到正确的结果,也让它们跳出了中间的错误插值地段。但是,墙面不会总是简单的一个方向,有些横梁等结构会像黄色一样,法线偏移后依然是错误的探针。因为AB两个面的这种结构法线完全一样,无法区分彼此,还有更严重的问题是,当角色从A面靠近墙面的时候,靠墙的这部分角色法线是朝右边的,所以导致A处的角色显示绿色的GI。

 


法线方向偏移采样的问题

 

所以,我想到了用更大尺度的法线来描述总体法线朝向(或可见度方向)。首先想到是屏幕空间Normal的Mipmap,但是屏幕空间有相机外丢失信息的天然弊端,所以后面选择了离线制作场景的Bent Normal,正确做法应该是对应Lightmap,用UV2解析。但为了演示方便我写到了顶点上。

 


计算Bent Normal到顶点上

 

测试下效果,用2个非垂直(垂直问题小很多)交叉隔开的4个空间,分别打3个不同颜色的灯,不打灯的空间为黑色换角色,然后每0.5米一个探针,均匀放置探针,并创建出3DTexture。可以看到Normal偏移在非交叉处是对的,偏移方向就刚好是法线方向。

 


测试的模型

  


Bent Normal与Normal的效果对比

 

Bent Normal算法
Bent Normal的离线计算是比较常见的技术。原理就是对某个点,法线所在的半球方向随机发出很多射线,没有发生碰撞的那些方向全部加起来,然后归一化。很像初中物理里求一堆力的合力,简单相加符合的力就可以,但是这种简单的计算依然会出现小的漏光,加强版里解决。

 


Bent Normal基础版算法

 

 


基础版 发射射线

 

这个图里,黑色的Mesh与绿色Mesh相交,那么露出的顶点显示的红色Bent Normal方向是对的,但是最右边的顶点因为在物体内部,所以它没有计算出Bent Normal,这样渲染的黄色部分的Bent Normal是左右2个顶点插值的结果,就导致黄色的Bent Normal偏移角度不够,依然会插值到绿色框内部或右面的探针而产生漏光。

具体的改善是不要原点发射方向,而是沿着射线方向偏移一点再发射。如下图,再考虑射线的双向碰撞检测,就可以抛弃蓝色碰撞部分,获得绿色部分的合成,这样得到顶点Bent Normal(黄色),会更符合环境描述,使红黄2个插值的结构也更正确。

 


高级版发射射线

 

 


Bent Normal 高级版算法

 

该方法最终效果,关于动态对象,不能取这份数据,需要逐对象分帧每帧发射一条射线,累积附近的偏移方向判断(实时Bent Normal计算)

 

 

方案2:DistanceProbe

同样是空间划分的描述,我们可以记录下碰撞体距离,根据是否大于距离判断是否取对面,总之在这种过渡位置不插值,要么取x处,要么取x+1处探针,取哪个根据ShadingPoint与Probe的距离是否大于提前记录的Probe到障碍物距离来定。

下图所示,绿色圈表示当前ShadingPoint位置;2个红圈表示用来插值的2个Probe颜色。为了直观只演示x方向上的判断。

  1. 左边红圈处没有记录往右存在1米内的碰撞,所以直接取x与x+1,2个红圈位置的Probe颜色来插值。

 


直接用2个红圈插值

 

  1. 右边存在碰撞,但与ShadingPoint距离小于与碰撞体的距离,那么就直接取x处Probe颜色为ShadingPoint颜色。

 


红圈右边存在碰撞,但与ShadingPoint距离小于与碰撞体的距离

 

  1. X处右边存在碰撞,与ShadingPoint距离大于与碰撞体的距离,那么就直接取x+1处Probe颜色为ShadingPoint颜色。

 


x右边存在碰撞,与ShadingPoint距离大于与碰撞体的距离

 

所以只要把偏移数据再创建一个3DTexture来存储,设置为Point Filter,即可实现功能。

看下效果(每米增加到8个Probe的效果)。

 

这种方式有2个问题:

  1. 需要较高的摆放密度。这是因为同一个空间内比如方案1里的(0.5x0.5x0.5)内,只记录一个到x+方向的float距离,(y+、z+同理都是一个float),但是一个空间内不同位置的距离应该是不同的,所以需要尽量让这个单位空间去小的范围。
  1. 这种距离固定是只出现在碰撞面刚好与xyz坐标轴垂直的情况下,如果表面不是轴对齐, 那么一个小空间内也不能用一个float描述距离,这时候需要记录平面方程来判断空间划分,而不是一个float的Distance,存储容量x4,而实际工程中一定是需要支持非轴对齐的情况的,除非无限细分空间。

 


左边是非轴对齐表面,右边是轴对齐表面

 

关于动态对象,这个算这个方案的优势之处,因为存储的是空间信息,所以任何ShadingPoint都能根据WorldPosition直接获取偏移量,得到正确数据。

方案3:Decal Offset

前面2种方案都需要受到体素/空间划分密度影响,这是因为它们都是均匀摆放,导致一些位置受限。所以还有一种更直观的想法,就是我可以把某个不规则空间内应该往哪个方向偏移记录起来,等采样的时候访问。这种记录可以在任意位置(不需要均匀间隔),任意形状大小(为了方便用Cube形状,但支持任何大小)。至于如何区分哪些是框住的部分,只要类似延迟贴花,算对象空间内坐标是否<0.5即可(Cube中心对象空间内xyz任何一方>0.5都不在Cube包含范围内)。

从顶视图看,我们为其中一个空间摆放3个偏移Cube,预计算每个Cube中心的非遮挡范围的中心方向(可见度Cone的轴线方向)为箭头所示,并把这个方向当作颜色为3个Cube渲染到单独RendererTexture。

 


为3个位置摆放Cube,确保Cube中心的可见度/非遮挡方向为所覆盖像素的偏移方向

 


3个Cube 把自己中心可见度Cone轴线方向作为颜色渲染到RT上

 

该方案最终效果:

 

 

 可以看到,漏光基本修复了,但是Cube之间有接缝,这个需要多摆放一份Cube让偏移方向可以过渡,或者对相邻Cube做Fade,类似Reflection Probe的2个Fade。

这种方案,因为Cube数量多而材质统一顶点数少,在正式工程,肯定用GPU Culling来做,HZB等做剔除后,绘制Instance性能很高。对于动态物体因为也是描述空间而非表面,所以可以直接支持。

3种方案Demo的源文件工程:
https://github.com/jackie2009/Probe_Light_Leak


这是侑虎科技第1570篇文章,感谢作者jackie 偶尔不帅供稿。欢迎转发分享,未经作者授权请勿转载。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)

作者主页:https://www.zhihu.com/people/jackie-93-85-85

再次感谢jackie 偶尔不帅的分享,如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。(QQ群:465082844)

标签:Cube,Bent,漏光,Normal,解决方案,Probe,探针,偏移
From: https://www.cnblogs.com/uwatech/p/18128399

相关文章

  • Springcloud学习笔记63---RocketMq超时重试,导致重复消费的问题,解决方案
    1.重复消费的背景当Consumer处理时间过长,在超时时间内没有返回给Broker消费状态,那么Broker也会自动重试。设定一个超时时间,达到超时时间的那个消费当作消费失败处理。Java客户端中的DefaultPushConsumer中的构造方法中的consumeTimeout字段(默认15分钟)。packagewilliam.rmq.......
  • 关于淘宝镜像过期问题解决方案
    问题:将项目拷贝到另一台电脑启动时报错Error:Theprojectseemstorequireyarnbutit'snotinstalled解决方法:1.删除项目中的yarn.lock文件2.终端执行npminstall-gyarn再次启动项目npmrunserve就可以了......
  • Git使用:大体积的历史commit无法推送到远程仓库的解决方案
    0介绍场景:把本地仓库全量推送到远程的空仓库,保留提交历史,所有分支,所有tag;大部分代码托管服务都会有免费推送的限制(如gitlab,Freepushlimit|GitLab,Accountandlimitsettings|GitLab),所以当提交中包含大于指定体积的commit时,会遇到如下的失败:如上的失败,可以通过git命令,......
  • 一网统管/安防监控/视频综合管理EasyCVR视频汇聚平台解决方案
    一、当前现状分析当前视频资源面临以下问题:1)不同单位在视频平台建设中以所属领域为单位,设备品牌众多,存在的标准不一,各系统之间也没有统一标准;2)各单位视频平台建设分散、统筹性差,没有进行统一规划、统一部署,各平台之间的数据共享不足,数据孤岛现象严重;3)各单位视频系统功能应用单......
  • VS2022 解决方案打不开 .NET Framework 4.0 、 4.5 等老项目
    vs2022开发工具最低支持net4.8,以下的如net3.5、4.0、4.5项目,加载不上怎么处理。一、下载.NETFramework框架.NETFramework4.5.2.NETFramework4.5.1.NETFramework4.5.NETFramework4.0,把框架放到vs安装目录下的对应包中。microsoft.netframework.referenceassemblies.......
  • Java高并发解决方案
    电商的秒杀和抢购,对我们来说,都不是一个陌生的东西。然而,从技术的角度来说,这对于Web系统是一个巨大的考验。当一个Web系统,在一秒钟内收到数以万计甚至更多请求时,系统的优化和稳定至关重要。这次我们会关注秒杀和抢购的技术实现和优化,同时,从技术层面揭开,为什么我们总是不容易抢到......
  • 智慧校园平台解决方案-收费管理系统
    收费管理系统简介: 学生收费管理系统与教务系统​​​​​​​,学工系统实现数据互通;实现网站支付功能,实现学生在家,在宿舍,只要能够上网即可通过支付宝,微信,网银对产生的订单进行支付。服务网大厅中的web网上查询使得数据查询更加便利,财务负责人通过平台查看学生收费情况,院系老......
  • Mysql时间差8小时解决方案
    在开发中,有可能会遇到这种情况: 插入数据库中的时间时正常。但是将时间传到前端页面上显示时,会早8个小时。这个问题我们可以从两方面来分析: MySQL本身的问题。JDBC连接的问题。MySQL本身的问题1-1.验证MySQL时间首先,我们执行如下SQL看看MySQL上的时间跟我的......
  • 无主之地2缺失nvtt.dll怎么解决?无主之地2缺失nvtt.dll问题的原因分析及高效解决方案
    很多玩家在玩无主之地2这款游戏的时候遇到了nvtt.dll文件缺失的问题,那么是什么原因造成的呢?应该怎么解决呢?下面一起来看看吧!一、原因1.未正确安装游戏:•游戏在安装过程中可能由于网络问题、安装文件损坏、安装程序故障等原因,导致部分必要文件(如nvtt.dll)未能正确复制到游戏......
  • EG25H4偏微分方程的解决方案
    EG25H4–CA2–偏微分方程的解决方案学生应独立准备解决指定问题的方案问题。提交的稿件,连同抄袭封面,应上传至2024年4月19日(星期五)下午5点(英国夏令时)前抵达MyAberdeen。请注意在截止日期后收到的未经授权的提交文件将受到逾期罚款,因为根据大学关于未经授权逾期提交的处罚政策课程。......