Interlude 5. Poisson Reconstruction

0x00 To begin with 这篇文章将会包含以下内容: 泊松重建的一些前置数学知识 泊松重建算法原理及推导过程 For reference: 📺 Laplace’s Equation and Poisson’s Equation 📖 如何通俗地理解拉普拉斯方程、泊松方程、亥姆霍兹方程? 📖 泊松表面重建详解 📃 Poisson Surface Reconstruction 0x01 隐函数表达 Implicit Expression 表达一个三维曲面,例如球心位于原点、半径为 $r$ 的球面,可以使用球的标准方程: $$ F(x,y,z):x^{2}+y^{2}+z^{2}-r^{2}=0 $$ 该方程(形如 $F(x,y,z)=0$)就定义了球面的隐函数表达,它将所有变量都放在等式一侧,隐含了因变量关于自变量的函数关系,在描述球面的情况下,$z$ 关于 $x,y$ 的关系可以显化为: $$ z=\sqrt{ r^{2}-x^{2}-y^{2} } $$ 这就是隐函数的一种显式表达,它描述球面在 $xOy$ 平面以上的部分。如果需要描述整个球面,还需要 $xOy$ 平面以下的部分: $$ z=-\sqrt{ r^{2}-x^{2}-y^{2} } $$ 也就是说显化的隐函数可能无法覆盖所有满足隐函数方程的解集,因为显函数是一一映射,而隐函数可能是一对多或者多对多的映射。 在计算机图形学中,SDF 就是一种常用的可以描述表面的隐函数表达: $$ \phi(\mathbf{x})=\pm \text{dist}(\mathbf{x},\partial \Omega) $$ SDF 以物体表面为界,空间中任意一点 $\mathbf{x}$ 的 SDF 函数值为与物体表面的带符号距离(物体内部为负、外部为正)。自然的,物体表面可以用 SDF 值为零的水平集描述: $$ \{\mathbf{x}\,|\,\phi(\mathbf{x})=0\} $$ ![使用 SDF 的零水平集描述表面,Jeong et.al](https://raw.gitmirror.com/congyuxiaoyoudao/Picgo-ImageBed/main/TA-interludes/Interlude%205.PoissonRecon/202508201058142.png#center) 0x02 泊松方程 Poisson Equation 泊松表面重建其实不需要对泊松方程有什么很深刻的数学物理了解,笔者也非相关专业,所以就仅凭自己的想法写一点更为直观的解释 ...

八月 19, 2025 · 3 分钟 · The Only Problem

Interlude 4. 在点云数据中估计法线

3DGS 的原论文中,每个高斯是不存法线信息的,然而后续工作中,也有研究人员将法线和 BRDF 信息进行训练,这样一来,就可以在后续的光栅化过程中输出 GBuffer,完成 relighting 的任务。生成初始法线,可以仅考虑高斯的均值,基于局部平面假设进行估计。 0x00 To begin with 这篇文章将会包含以下内容: 什么是 PLY 利用最小二乘法估计点云法线 使用 PCL 的实现 在 CloudCompare 中实现 For reference👇: 📖 PLY - Polygon File Format 📖 Estimating Surface Normals in a PointCloud 📺 Normal and Curvature Calculation for a Pointcloud 📃 http://mediatum.ub.tum.de/doc/800632/941254.pdf 0x01 PLY 格式 PLY(Polygon File Format, also known as the Stanford Triangle Format),是一种用于存储多边形集合的图形对象的格式。有两种子格式: ASCII:ASCII 编码表示,直观易读 Binary:二进制格式,存储空间小,能够快速保存和加载 PLY 文件的经典结构如下: Header // description field, containing element type, property and count Vertex List // list of data for each vertex Face List // list of data for each face (List of other elements) Header 描述文件格式,评论(comment)以及每个元素的描述,并在其后指定该元素属性。例如一个以 ASCII 子格式保存的 PLY 文件,其 Header 如下: ...

七月 2, 2025 · 4 分钟 · The Only Problem

Interlude 3. WebGPU From Scratch

从导师那里听说了 WebGPU,做了点调查发现这个 API 还挺新的,正好之前只零零碎碎学了一点 OpenGL,相比于不适合人类学的 Vulkan,还是 WebGPU 显得友好一点。 🚩 0x00 To begin with 这篇文章将会包含以下内容: 什么是 WebGPU 配置 WebGPU 开发环境 第一个 WebGPU 项目:HelloTriangle! For reference👇: 🍪 WebGPU Samples 📖 WebGPU API Spec 📖 WebGPU Shading Language 📺 WebGPU小白入门(一):如何零基础创建第一个WebGPU项目! 📖 您的第一个 WebGPU 应用 📖 lil-gui 0.20.0 0x01 认识 WebGPU WebGPU 是一个由 W3C GPU 工作组制定的新的现代图形 API,用于在 Web 应用中访问 GPU 功能。 在 WebGPU 出现之前,Web 端的图形编程应用主要采用 WebGL 和 WebGL 2,虽然它们有着跨平台能力和强大的社区支持,但架构过于古老,最新的 WebGL 2 只是封装了 2009 年 OpenGL 3.2 的实现。Khronos 也指出 WebGL 后续更新中不再引入现代 GPU 的新特性。 ...

六月 30, 2025 · 7 分钟 · The Only Problem

Interlude 2. Manga Speed Lines

偶然用 shader 乱搓出的一个类似漫画风格的放射线效果,实际上还有很多缺陷,权且当思路分享了 🚩 0x00 To begin with 这篇文章将会包含以下内容: 漫画的速度线效果 基于 blender 着色器的乱糊 👀 0x01 What is Radiating Lines 漫画中经常有这种放射线的效果: 通常是用来表达角色情绪、物体速度感或突出画面重点,动漫中还会做出动画以增加表现力。但是如果不靠画(全凭程序化)怎么做呢? 如果不限制工具的话思路很简单,在 PS 里先画一个渐变,再用波浪扭成间隔不等的尖刺状,最后转成极坐标就完事了。 但是如果要用 shader 写的话就有点头疼了,主要是那种不规则的尖刺效果。我一开始想的是让 V 的起点在径向随机偏移,但 UV 毕竟是重复平铺的,极坐标一扭还是会窜到中心去,甚至 V 有没有都没关系。 所以偏移 UV 的想法是不行了,我的做法是糊出一个遮罩(也是很邪门了)。 🕸️ 0x02 Radiating Lines 放射线效果 要做出放射的效果,首先得让 UV 位于模型的中心,以正方形平面为例,在映射中将 UV 同时减去 0.5,让 UV (0,0) 处位于模型中心。 然后就是让 U 绕圆周环游一圈,现在的 UV 可以当成直角坐标系处理,很容易给出一个单位圆的方程: $$ u^2+v^2=1 $$ 然后算以 U 轴正方向为起点的角度: $$ \theta=\arctan \frac{v}{u} $$ 可以用运算节点的反正切 2 计算这个$\theta$,但是结果的范围是$-\pi \sim+\pi$,需要映射回$0 \sim1$: ...

三月 31, 2025 · 1 分钟 · The Only Problem

Interlude 1. ToonIntergratedBxDF

之前的几篇文章中,我们已经完成了Toon模型一些基本的Feature。在深入定制之前,我们必须冷静下来思考一下我们需要什么 🚩 0x00 To begin with 这篇文章将会包含以下内容: 集成卡渲着色模型 For reference👇: 📖 【UE5】通过深度偏移计算刘海投影 👀 0x02 ToonIntergrateBxDF 目前我们的光照模型只是已经具备了基本的明暗处理,仍然有数量众多的Feature需要去实现(Ramp、SDF、Anisotropic hair、Matcap、眼透等等)。虽然有一小部分可以用一些trick附加在基础色或其它材质槽上,但其余的就无可奈何了。而且不同于Unlit,在底层逻辑写死的情况下,能在材质编辑器中做的工作就比较有限了。 一个比较容易想到的方法就是为需要特殊处理的材质单独新建一个着色模型,比如说头发一个、皮肤一个,然后里面各自处理需要的Feature。但着色模型数量是有限的,在不扩展FMaterialShadingModelField至uint32的情况下最多只允许16个着色模型。 而且这么多模型逐一添加也比较繁琐,我认为不太优雅,所以想到另一个方法。既然我们已经有一个ToonBxDF,何不仿照IntegrateBxDF的写法,在里面写个大分支,分发不同Toon材质的情况呢? 思路有了,那下一个问题就是,根据什么分发呢?IntegrateBxDF是根据ShadingModelID,我们应该也需要一个ToonShadingModelID。这个时候我想起了之前开辟但没使用过的ToonCustom引脚。现在它被存储在GBuffer的CustomData的Alpha通道中,我们可以停止放置Play,好好使用它了。 FGBufferData中的CustomData在BasePass中经过编码来到GBufferD,最后输出到MRT[4]或MRT[5]。 类型是float,(没错,half4竟然是个宏)。 但是范围只有0~1,由于GBufferTexture的性质,我们在这个引脚输入的任何数值都会被硬件钳制到这个范围。没办法,写个函数转一下吧。 1uint DecodeFloatToToonShadingModelID(float SrcFloat) 2{ 3 return SrcFloat * 255; 4} UE里面也新写一个材质函数,把正常的ID映射过去, 最后在ToonIntergrateBxDF里随便写点东西测试一下,只有当ToonShadingModelID为0时才有光照计算。 单独把身体的ID设成2看看效果。

三月 11, 2025 · 1 分钟 · The Only Problem