nvdiffrast的MeshRenderer

  1. 获取输入:
    • vertex: 顶点坐标,大小为(B, N, 3)
    • tri: 面片索引,大小为(B, M, 3) 或 (M, 3)
    • feat(可选): 顶点features,大小为(B, C)
  2. 计算NDC(标准设备坐标)投影矩阵,用于投影到图像平面。
  3. 将顶点坐标转换到同质坐标(加1维,方便后续运算)。
  4. 用NDC投影矩阵将顶点坐标转换到NDC空间。
  5. 创建渲染上下文ctx,根据usage_opengl标志选择CPU或GPU实现。
  6. 如果面片索引是list格式,先转换为连续tensor。
  7. 调用dr.rasterize,根据顶点和面片信息生成raster化的图像。
  8. 调用dr.interpolate,从raster化结果和原顶点信息中插值,计算深度图。
  9. 如果有顶点features,也调用dr.interpolate生成渲染图。
  10. 将结果转换为适合网络输入的格式(NCHW)。
  11. 返回:
    • mask: 根据有效像素生成的掩码图
    • depth: 渲染的深度图
    • image(可选): 渲染的特征图

这样通过神经网络可微分的运算,实现了不同iable的3D mesh渲染,可以将其接入网络进行端到端的训练。

  • 首先,将顶点从三维坐标转换为齐次坐标,即在顶点的最后一维添加一个1,然后将顶点的y坐标取反,这是因为顶点的y方向和图像的v方向是相反的。
  • 然后,将顶点乘以一个归一化设备坐标(NDC)的投影矩阵self.ndc_proj,这个矩阵可以将顶点从相机坐标系转换到NDC坐标系,这是一个[-1, 1]的立方体空间,用于后续的光栅化过程。
  • 接着,创建一个光栅化的上下文self.ctx,这是一个用于执行光栅化和插值的类,它可以选择使用OpenGL或CUDA的实现,根据self.use_opengl的值来决定。
  • 然后,根据三角形的形状,判断是使用范围模式还是实例模式,范围模式是指每个批次的顶点和三角形的数量都不同,实例模式是指每个批次的顶点的数量相同,但三角形的数量不同。如果是范围模式,就需要计算每个批次的三角形的起始索引和数量,并将它们存储在ranges中,然后将每个批次的顶点和三角形拼接起来,得到一个大的顶点和三角形的张量。
  • 然后,将三角形的类型转换为整数类型,并保证它们是连续的,这是为了方便后续的光栅化运算。
  • 接着,调用dr.rasterize函数,传入顶点、三角形、分辨率和范围(如果有的话),得到一个光栅化的输出rast_out,这是一个(B, H, W, 4)的张量,其中B是批次的数量,H和W是分辨率的高度和宽度,4是每个像素的属性,包括三角形的索引、重心坐标和覆盖度(是否被遮挡)。
  • 然后,调用dr.interpolate函数,传入顶点的z坐标、光栅化的输出和三角形,得到一个插值的输出depth,这是一个(B, H, W, 1)的张量,表示每个像素的深度值,然后将它的维度交换,得到一个(B, 1, H, W)的张量。
  • 接着,根据光栅化的输出的覆盖度,计算出一个遮罩mask,这是一个(B, 1, H, W)的张量,表示每个像素是否被三角形覆盖,然后将深度值乘以遮罩,得到一个只有覆盖区域有深度值的张量。
  • 然后,判断是否有特征输入(如顶点颜色),如果有的话,就再次调用dr.interpolate函数,传入特征、光栅化的输出和三角形,得到一个插值的输出image,这是一个(B, H, W, C)的张量,表示每个像素的特征值,其中C是特征的维度,然后将它的维度交换,得到一个(B, C, H, W)的张量,然后将特征值乘以遮罩,得到一个只有覆盖区域有特征值的张量。
  • 最后,返回遮罩、深度和特征(如果有的话),这些都是用于生成人脸图像的重要信息。
相关推荐
子燕若水1 年前
HRNet关键点检测
w如果eras·18 23-0
子燕若水1 年前
“/etc/apt/sources.list.d“和文件/etc/apt/sources.list的不同
w如果eras