当前位置: 首页 > news >正文

有符号距离场(Signed Distance Field,SDF)

https://zhuanlan.zhihu.com/p/89701518

SDF的用途很多,可以用来做large scale AO, 软阴影等。UE4就用SDF来做AO和软阴影,SDF Ray-traced shaow 比PCSS软,而且和CSM相比,因为没有那么大的几何填充负担,所以反而要便宜很多,和静态的Shadow map相比,又可以支持物体级别的移动(虽然不支持顶点动画),所以是一个相当不错的阴影解决方案。堡垒之夜就用了这项技术,堡垒之夜的近处是级联阴影,远处是SDF Ray-traced shadow.

SDF 可以用一个标量场函数或者一张体贴图来表示,简单地来说就是一种空间的表达,里面存的是空间中一个点到最近的三角面的距离,如果在物体内部则是负值。如图所示:
在这里插入图片描述
在这里插入图片描述

因为是“距离”的标量场,所以用“距离”保留了空间信息,结合硬件插值可以更好地保留表面信息,不像体素一旦被体素化,所有几何信息就全部丢失了,原来的边界在哪里就不知道了,所以SDF的有效分辨率其实比体素要高的多。

SDF追踪的时候能加速,可以跳过空闲的空间。

既然标题写的是建场,那么这次主要分享的就是建场的内容。实际上虚幻用的是最简单的暴力建场,在每个位置发一堆光线求离附近所有三角面的距离,找出最近的那个作为距离场的值。

实际上这个过程相当慢,为了降低烘焙的开销,像在虚幻里一般我们用32x32x32分辨率就相当够了,如果要非常高的精度最大可以用128128128大小。然后一般可以考虑用8位的定点数来存储,最大范围scale到距离场的大小。

加速结构
kd树:建树
因为涉及到大量求交,所以我们这时候就需要用到空间划分了,UE用的是KDop树,这里我直接抄了pbrt上的kd树来用,下面简单描述下KD树。

kd树就是用xyz三个轴,每次取一个轴,用某个策略找一个最佳的划分点,在这个划分点分割,如此往复,直到把所有三角形都划分到叶子节点里。

划分过程如下图:
在这里插入图片描述
kd树遍历
树构建好了之后,遍历就比较简单了,简单来说就是判断一下光线是否会与父亲节点相交,如果相交,再去判断子节点,与父节点相交的光线不一定会和每个子节点相交,遍历的时候不相交的部分,就可以全部跳过。

建场
暴力建场的方法,就是直接迭代323232个点,然后在每个点上向周围发射一大堆光线,然后保存交到的最小距离,作为距离场在这个点上的值。

值得一提的几个细节是,一般距离场的范围是比物体的AABB大一圈,我这里取的是扩大40%大小。

然后,在物体内部的点,距离存的是负值,然而不是所有曲面都是闭合的,有的时候我们没法区分内和外,虚幻用的是一个heuristic,如果50%以上的光线和三角形的正面相交,那么我们认为这个点在物体外面,如果50%以上的光线与三角形的背面相交,我们认为这个点在曲面内部,再借用一张虚幻的图:

Ray March
Sphere Tracing
https://www.cnblogs.com/murongxiaopifu/p/9175936.html
http://jamie-wong.com/2016/07/15/ray-marching-signed-distance-functions/
http://advances.realtimerendering.com/s2015/DynamicOcclusionWithSignedDistanceFields.pdf

相关文章:

  • 面向对象串讲
  • C#结构体里面包含类
  • SpringBoot的自动配置原理
  • postman通过引入外部文件实现参数化
  • unity中画摄像机的视锥体和判断一个点是否在视锥体内
  • 82. 删除排序链表中的重复元素 II
  • unity Graphics.DrawMesh的绘制顺序测试
  • 树莓派Ubuntu Mate 16.04 修改为国内更新源
  • 通过iis访问电脑文件
  • 屏幕后处理——全局雾效
  • Spring的事物原理
  • 软阴影硬阴影
  • Spark RDD
  • Raytracing Algorithm in a Nutshell——读完
  • springboot项目从硬盘指定位置读取文件(获取静态资源)
  • [LeetCode] Wiggle Sort
  • 2017年终总结、随想
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • mysql_config not found
  • python3 使用 asyncio 代替线程
  • TypeScript迭代器
  • Vue 重置组件到初始状态
  • 订阅Forge Viewer所有的事件
  • 通过git安装npm私有模块
  • 项目管理碎碎念系列之一:干系人管理
  • 延迟脚本的方式
  • 一份游戏开发学习路线
  • 一文看透浏览器架构
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • $.ajax()参数及用法
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (1)(1.19) TeraRanger One/EVO测距仪
  • (4)(4.6) Triducer
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)JPA - JQPL 实现增删改查
  • (一) springboot详细介绍
  • (转)人的集合论——移山之道
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .htaccess配置重写url引擎
  • .net mvc actionresult 返回字符串_.NET架构师知识普及
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .vue文件怎么使用_我在项目中是这样配置Vue的
  • @Autowired 与@Resource的区别
  • []我的函数库
  • [AIGC] Redis基础命令集详细介绍
  • [Angular 基础] - 指令(directives)
  • [AutoSar]BSW_Com07 CAN报文接收流程的函数调用
  • [BZOJ 3680]吊打XXX(模拟退火)
  • [GXYCTF2019]禁止套娃
  • [HNOI2018]排列
  • [Java、Android面试]_10_Java中==与equal()方法的区别?重写equal()方法?