栅格化渲染源码解析-neural_renderer源码(一)概览

目录

一、栅格化渲染

二、neural_renderer

三、总体流程

3.1加载物体

3.2 渲染总体流程

3.3 光照

3.4 顶点投影

3.5 栅格化


一、栅格化渲染

目前三维渲染中,较多渲染技术采用栅格化的方法。也有光追渲染的技术,光追是另一套渲染pipeline,这里暂不讨论光追,只讨论栅格化。

栅格化的定义:将三维场景中的物体进行着色投影到成像平面,形成二维图形的过程。其详细定义和流程可以参考其他文章,本文暂不重复描述。

基于代码选取,栅格化渲染的代码较多,例如基于openGL的渲染管线,本文选取的是neural_renderer,此代码主要的创新点是如何在渲染中回传梯度,但是其栅格化部分的代码写的具有不错的可读性。我们暂不讨论代码中关于梯度的问题,只是详细解析一下neural_renderer是如何进行栅格化渲染的流程的。

二、neural_renderer

有三个版本,一个是torch+cuda版本,另一个是chianer+cupy版本。还有一个tensorflow版本,几个版本之间可以相互参考。

GitHub - FuxiCV/pt_mesh_renderer: A PyTorch implementation for the "Mesh Renderer"

​​​​​​https://arxiv.org/abs/2008.07154

​​​​​​https://openaccess.thecvf.com/content_cvpr_2018/html/Genova_Unsupervised_Training_for_CVPR_2018_paper.html

本篇论文的重要贡献在于,将栅格化过程作为一个可以向回传递梯度的过程,从而产生优化,详见论文项目到贡献点和论文原文。这里不详细讨论。本文只详细讨论文章的源码中与栅格化渲染相关的部分。

源码解析中,主要以chainer版本源码做为参考,同时参考另两个版本。chainer是一个类似于神经网络库,在栅格化代码中的作用主要是提供张量乘法和进行GPU任务的并行。例如,代码中并行调用GPU的方法是chainer.cuda.elementwise(...),此步骤中的代码也是光栅化渲染的核心代码。

三、总体流程

此流程可能与openGL的渲染pipeline有不同地方。

  1. 加载物体:将物体从.obj文件之中加载出来。
  2. 生成面片张量:用于将面片和顶点结合,张量形式易于处理。(因为.obj文件之中的顶点和面片是独立分开的,而这里转换张量更易于GPU进行并行运算。)
  3. 对于贴图光照:此步骤只对贴图进行了处理。注意,这里的光照只有平行光和常数化光场(可以理解为光照是从各个方向均匀的照射过来)
  4. 顶点投影:用对齐的视角进行投影
  5. 栅格化采样:根据投影结果进行栅格化采样。

3.1加载物体

加载物体,物体被加载为几个张量,vertices, faces, textures. 分别是顶点,面片,贴图。

vertices顶点即物体所有多面体的顶点。维度是 [num_vertices, xyz] 每个顶点的xyz三维坐标 

faces面片是顶点之间的组合关系。[num_faces, v123] 面片数量和每个面片的三个顶点。v1,v2,v3这个是一个索引,即该面片在整个顶点的之中的第几个。每三个顶点组合在一起,形成了一个面片。

texture贴图:xyz贴图与面片一一对应,即根据贴图图像生成的针对每个面片的RGB值。该张量尺寸是

[num_faces, texture_size, texture_size, texture_size, RGB]

这里的texture_size不是整张贴图的尺寸,而是每个三角面片上需要贴图的大小。至于为什么三角面片是二维的,而这里的texture_size在这个张量中有三个维度,这点可能需要从load_obj的源码入手。源码中,每个面片有三个顶点,后面采样时候需要用到每两个顶点的权重关系,贴图生成的时候是一个三维的张量。具体看不懂没关系,后面会详细解释一下这个张量的作用。

3.2 渲染总体流程

根据顶点生成面片张量。相当于将顶点和面片统一到一个张量之中,方便后续并行化处理。

.obj文件之中,顶点和面片是独立分开的,顶点是顶点,面片是面片,

顶点和面片转为张量,此张量是 [num_faces, v012, xyz],这个张量蕴含了物体所有的顶点信息。相当于将物体的空间信息存储在张量之中。每个面片,每个面片的三个顶点,每个顶点的三维坐标。

即所有面片的三个顶点的三维坐标。这个张量相当于将.obj模型之中的顶点给统一了起来。

3.3 光照

目前,此代码只实现了光源和面片之间的相互作用,且只实现了漫反射的光照。光源形式只包括常数化光场(即各个方向都有光照过来),和平行光(光从同一个方向照射过来)。

此光照只作用于面片,根据面片的法向朝向与光照相互作用。

3.4 顶点投影

根据摄像机视角和内外参数,将物体的顶点投影到成像平面。即空间坐标到UV坐标的转换。

3.5 栅格化

原理部分可以参考这篇文章: 猴子也能看懂的渲染管线(Render Pipeline) - 知乎 (zhihu.com)

z-buffer的概念:深度缓存z-buffer - 知乎 (zhihu.com)

栅格化的过程是代码的核心。这里涉及到一个z-buffer的概念,即物体经过投影之后,

torch版本的neural_renderer是将代码写成.cu和.cpp文档,通过编译之后用python调用。

chainer版本的nerual_renderer源码是通过chainer.cuda.elementwise(...)进行处理。归结起来,chainer版本的源码更加易于修改,因为只需要修改函数之中的代码即可重新运行,不需要像torch版本的源码一样,需要编译。

栅格化过程涉及到三个部分,这里涉及到cuda并行:

for_each_face:计算该face在当前视角下的投影,计算该face的depth

for_each_pixel: 计算该pixel下所有涉及面片的深度,找到离投影平面最近的面片的索引(相当于z-buffer的作用)

texture_sampling: 根据贴图和前两步的结果进行采样,形成采样图像。

以上内容只是粗略介绍了一下栅格化的框架,以及代码结构,详细源码会在后面进行解析。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

祥瑞Coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值