Implicit隐式渲染入门 SDF SphereTracing
Implicit
何为隐式?隐式(Implicit)的是显式(explicit)的反义词。
explicit可以简单理解为用网格等信息描述的几何形状,网格信息是离散的,信息量越大描述越精准。Implicit则不需要顶点等显式信息,用方程,或者说有符号距离场 (Signed Distance Field) 即SDF,表示几何形状的数学模型。
SDF
在SDF中,空间中的每一点都有一个值,表示该点到最近表面的距离。这个距离可以是正的(如果点在形状的外部),也可以是负的(如果点在形状的内部)。SDF提供了一种简洁而强大的方式来描述复杂的三维形状,包括难以用传统多边形网格表示的形状。
SDF的优势:
- 高效的几何操作:进行布尔运算以及形状变形和平滑处理变得简单高效。
- 复杂形状的表示:特别适合描述复杂或有机形状,如流体、云雾和生物组织。
- 动态变化的支持:使实时更新和变形成为可能。
对几何primitive的sdf描述
Inigo Quilez :: computer graphics, mathematics, shaders, fractals, demoscene and more (iquilezles.org)
Sphere Tracing
why
传统的光线追踪算法,通过发送光线并检测这些光线与场景中物体的交点,进行着色。但是当场景使用SDF来表示时,传统的交点检测方法不再适用。原因在于SDF和多边形网格表示场景的方式截然不同:
- 顶点表示:在传统的多边形网格表示中,物体由许多小的平面片(通常是三角形)构成的。这些三角形有明确的边界和顶点,因此当光线与这些三角形相交时,可以通过数学计算找到精确的交点。
- SDF表示:相比之下,SDF场景被视为一个连续的体。体中每个点都有一个值,表示该点到最近表面的距离。这种表示方法不涉及明确的边界或顶点,而是提供关于形状表面的连续信息。
由于SDF没有离散的多边形或边界,传统的光线与多边形的交点检测算法(通常涉及线性代数和平面几何计算)不再适用。在SDF表示的场景中,没有明确的多边形表面可以直接与光线进行交点计算。因此需要Sphere Tracing这样的算法来处理SDF场景。
How
原版的SphereTracing十分讨巧,其基本原理非常简洁,也非常聪明:
- 从点 \(p_0\) 开始投射一条 ray,以 SDF 值 \(f(p_0)\) 为步长进行一次 marching。
- 以上次 marching 的终点为起点,以 \(f(p_1)\) 为步长继续下一次 marching。
- 重复 marching 直到 \(f(p_n)\) < \(\epsilon\) , \(\epsilon\) 为预设的阈值。此时我们认为 \(f(p_n)\) 即为交点。

Enhanced Sphere Tracing
上述的传统 Sphere Tracing 算法冗余的步进次数很多,为了进一步提高效率,诞生了很多种优化方案。
binary search 二分查找法,实际效果不理想,并且遇上TPMS这种复杂结构会有更多问题
Inigo Quilez :: computer graphics, mathematics, shaders, fractals, demoscene and more (iquilezles.org)
Segment Tracing 通过假设场景是 \(C^2\) 连续去加长初始 marching 的距离,有效减少 marching 次数的同时,大幅提升了每次 marching 的消耗,效果不理想,并且在有棱角的场景表现更差
https://diglib.eg.org/bitstream/handle/10.1111/cgf13951/v39i2pp545-554.pdf
GitHub - aparis69/Segment-Tracing: Source code for the Computer Graphics Forum paper: Segment Tracing Using Local Lipschitz Bounds. Presented at Eurographics 2020.
【光线追踪】Segment Tracing:一种可能加速距离场求交的实时光线追踪方案 - 知乎 (zhihu.com)
Enhanced Sphere Tracing 采用激进的 marching 步长,即设定一个步长倍数\(\alpha\) ,marching 步长改为 \(f(p_n) * \alpha\) 而不是 Sphere Tracing 保守的 \(f(p_n)\) 。只要两个 sphere 相交,就说明本次 marching 可安全,否则退回到点 \(p_n\) 的位置重新进行保守的 marching。

Accelerating Sphere Tracing 在 enhanced 的基础上更进一步。假设前两次 marching 所形成的 sphere 都相切于同一平面,那么下一次可以尝试 marching 同样与该平面相切并且也与上一次的 marching sphere 相切的距离。同样,如果尝试失败则回退至保守 marching。

上述两个方法都是在2023年以前最优秀的 marching 算法之一,直到 Automatic Step Size Relaxation。
Automatic step size relaxation
Automatic step size relaxation 可以根据历史 marching 的情况,动态调整步长:平面多的地方。可以走相切平面的激进步长,而曲面多的地方则调整为走更保守的步长。

每次 marching 不断更新近似斜率 m,然后用它来指导下一次 marching。
博主拙劣的C++实现
auto trace_auto_relaxation = [&](glm::vec3 p)
{
float t = 0.0f;
float r = sdf(p);
float m = -1.0f;
float z = r;
const float beta = 0.3f;
for (int i = 0; i < max_steps; i++)
{
if (r < eps) {
return true;
}
if (t + r > max_dist) {
break;
}
glm::vec3 next_p = p + ray_dir * z * relaxation_factor;
float R = sdf(next_p);
bool doBackStep = z > abs(R) + r;
if (!doBackStep) {
float M = (R - r) / (z + 1e-5f);
m = (1.0f - beta) * m + beta * M;
t += z * relaxation_factor;
p = next_p;
r = R;
}
else {
m = -1.0f;
}
float omega = glm::max(1.0f, 2.0f / (1.0f - m));
z = glm::max(eps, r * omega);
}
return false;
};
But
讲完了吗?讲完我要开始转了。
上述的所有方法,对 TPMS(Triply Periodic Minimal Surfaces 三周期极小曲面),都起不到多少作用。目前效果最好的办法只能是力大砖飞——marching 步长乘以系数 \(\alpha ,\alpha < 1\) ,以非常保守的步长去小心翼翼的找TPMS表面。也是博主目前最头疼的问题,欢迎讨论。

Implicit隐式渲染入门 SDF SphereTracing的更多相关文章
- Scala中的Implicit(隐式转换,隐式参数,隐式类)
文章来自:http://www.cnblogs.com/hark0623/p/4196452.html 转发请注明 代码如下: /** * 隐式转换 隐式参数 隐式类 */ //隐式转换 class ...
- IdentityServer4之Implicit(隐式许可)
IdentityServer4之Implicit(隐式许可) 参考 官方文档:3_interactive_login .7_javascript_client 概念:隐式许可 认证服务端配置 认证服务 ...
- IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离
IdentityServer4之Implicit(隐式许可) —— oidc-client-js前后端分离 参考 官方文档:oidc-client-js:oidc-client是一个JavaScrip ...
- C# implicit隐式转换
今天看书,上面介绍implicit和explicit相对冷门,用的较少. 这个implicit类型虽然冷门,但真的很有用.我在自己的项目里就用了这个 上Demo, 1 public partial c ...
- asp.net core IdentityServer4 实现 implicit(隐式许可)实现第三方登录
前言 OAuth 2.0默认四种授权模式(GrantType) 授权码模式(authorization_code) 简化模式(implicit) 密码模式(resource owner passwor ...
- Scala 隐式(implicit)详解
文章正文 通过隐式转换,程序员可以在编写Scala程序时故意漏掉一些信息,让编译器去尝试在编译期间自动推导出这些信息来,这种特性可以极大的减少代码量,忽略那些冗长,过于细节的代码. 1.Spark 中 ...
- Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Scala 学习笔记之隐式参数和隐式转换并用
隐式转换条件: 1. 当表达式类型与预期的类型不同时 2.当对象访问一个不存在的成员时 3.当对象调用某个方法,而该方法的参数声明与传入参数不相匹时. 隐式转换搜索范围: 1. 位于源火目标类型伴生对 ...
- 【Scala】什么是隐式转换?它又能用来干嘛?该怎么用
文章目录 定义 隐式参数 隐式转换 隐式值:给方法提供参数 隐式视图 将Int和Double类型转换为String 狗狗学技能(使用别的类中的方法) 使用规则 定义 隐式参数 隐式参数指在函数或者方法 ...
- C#中的类型转换-自定义隐式转换和显式转换
目录 前言 基础知识 示例代码 实际应用 问题 答案 报错 用户定义的转换必须是转换成封闭类型,或者从封闭类型转换 参考 其他 应用和设计 读音 参考 前言 有时我们会遇到这么一种情况:在json数据 ...
随机推荐
- Android历史版本
目录 [隐藏] 1 测试版 2 版本列表 2.1 Android 1.0 2.2 Android 1.1 2.3 Android 1.5 Cupcake 2.4 Android 1.6 Donut ...
- 高可用mongodb集群(分片+副本):规划及部署
目录 ■■ 概述 ■ 下图是一个典型的3节点分片副本集群 ■ Mongos Server ■ config server ■ shard server ■ replica set ■ 仲裁者(Arbi ...
- 几句话了解元数据(Metadata)
元数据就是关于数据的数据(data about data),主要是描述数据属性(property)的信息,用来支持如指示存储位置.历史数据.资源查找.文件记录等功能. 要理解元数据,首先要知道&quo ...
- 炫酷转换:Java实现Excel转换为图片的方法
摘要:本文由葡萄城技术团队原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 在实际开发过程中,经常会有这样的需求:将Excel表格或特定区域 ...
- 2020/4/26 2-sat 学习笔记
2-sat 吧.... 其实我jio得它一点都不难 嗯 2-sat是个啥东西呢?其实就是有很多人,他们每个人有两个要求,一个要求可以说是要求一个数为0或1而对于第i个数,我们可以选择为0或为1最终询问 ...
- 聊聊基于Alink库的特征工程方法
示例代码及相关内容来源于<Alink权威指南(Java版)> 独热编码 OneHotEncoder 是用于将类别型特征转换为独热编码的类.独热编码是一种常用的特征编码方式,特别适用于处理类 ...
- 『STAOI』G - Round 2 半个游记
很刺激. 2023.3.2 23:17 第一次过审. 2023.3.5 00:02 第一次打回. 原因是背锅人的链接又双叒叕挂错了((( 2023.3.6 21:20 第二次过审. 2023.3.8 ...
- 牛客多校第一场 A. Alice and Bob (暴力SG)
题目大概 有两堆石子,有两个人拿,一个人从一堆中拿\(k\)个,那么就必须从另一堆中拿\(s*k\)个,Alice先拿,问是否必赢. 解题: 数据不大,看到前\(20\)名队伍没有推结论做的..除了打 ...
- Reflect API:每个 JavaScript 开发人员都需要的瑞士军刀
前言 您是否曾经希望拥有一个神奇的工具包,可以让您像超级英雄一样控制 JavaScript 对象?向ReflectAPI 打个招呼吧,它是 ES6 中引入的一个新的全局对象 ,它能够处理简单的代码操作 ...
- python之递归(斐波那契数列)与迭代
对于较大的计算来说,迭代不如递归计算速度快,并且可以说非常慢 但是迭代对于较小的运算又比递归巧妙 # 迭代方法 def slowsnail(x): am = [1, 1] if x < 0: p ...