跳到主要内容

组织场景树

3D渲染引擎的最核心目标之一是组织一个层次分明、渲染高效的场景树。场景树是渲染引擎中用于组织和管理场景中所有对象的层次结构,一般是一个树状数据结构,由一系列渲染节点组成,每个节点可以包含子节点,从而形成3D模型普遍的父子关系结构。

在这里,我们将了解到:

  • 场景树的组织结构
  • 渲染通道
  • 渲染节点
  • 绘制单元
  • 上下文管理
  • 渲染管线

场景树组织结构

下面给出了Illustrator中典型的场景树,一个场景树有很多层组织结构,最根部是渲染场景scene,一个渲染场景中可以有多个渲染通道renderPass,也可以理解成多个渲染层,每层管理各自的渲染对象。


渲染通道

渲染通道,本质上是一种逻辑组织概念,帮助渲染引擎实现分层管理场景。想象一下,一副油画其实是用一层一层的场景构成,比如第一层是远处的白云,第二层是稍微近一些的山峦,最后才是近在眼前的河流树木。同样地,我们采用渲染通道,将场景中的对象按照某种规则(比如用途、类型或渲染顺序)划分成不同的层,分离渲染逻辑,可以使得引擎对场景变化的响应更加快速。

每个渲染通道可以独立渲染,常用于处理不同类型的对象,例如背景、常态渲染几何、被拾取高亮的几何等。

一个渲染通道中,具备独立的渲染背景background、相机camera和渲染节点node,其中渲染节点是需要渲染的模型对象,而相机则决定模型的观察方位。

渲染节点

渲染节点是引擎中实际渲染的对象,包含了3D网格数据mesh、材质material、几何geometry、变换信息transform。由于工业模型一般具有多层的父子结构,所以渲染节点一般也有一系列子渲染节点children:[]

mesh是由一系列绘制单元primitive组成的,我们接下来看看绘制单元是什么。

绘制单元

在工业设计中,我们可以用很多不同的造型设计软件,制作出各种各样的3D模型,组成这些模型的基本元素,比如顶点、控制点、 线或面等,都有着精确的数学表达。不管是什么样的曲线或面,当被离散化后,可以形成统一的绘制单元primivite,这将成为渲染引擎的原材料,通常包括以下内容:

  • 顶点数据:定义模型的形状,包括位置、法线、纹理坐标等。
  • 索引数据:定义顶点的连接方式,表示模型的三角形面。
  • 外观属性:定义模型的颜色、纹理、光泽度等。
  • 纹理:贴图数据,用于增强模型的细节。

绘制单元本质上是对底层图形API(如OpenGL、DirectX、Vulkan等)的抽象封装。它包含了几何geometry和材质material,其实在场景树的末端就是大量的几何数据、材质属性。几何数据描述了渲染对象是什么,一般用顶点缓冲(VBO)和索引缓冲(IBO)数据类型来表达,而材质属性描述了怎么渲染这些对象,是用可编程的顶点/面片渲染器(GLSL)、Uniform参数、状态(State)来表达。这些内容将在教程章节中详细介绍。

如果绘制单元中没有定义材质,那么可以继承它的父渲染节点中定义的材质material,几何geometry也同理。这种情况意味着所有绘制单元采用了同样的材质或几何。


渲染上下文管理

渲染管线

渲染管线是光栅式渲染引擎调用OpenGL去实现的核心工作,其功能是利用一个渲染上下文中所包含的渲染要素,在屏幕中渲染出2D图像。这里会简单介绍渲染管线的内部运作,探索将原始数据转换为屏幕上的引人注目的视觉效果的关键阶段。

准备数据:3D模型

我们在进入渲染管线之前,已经通过场景树,组织好了一系列的3D渲染单元,而渲染管线是以渲染单元的几何数据(顶点信息VBO和索引信息IBO),材质属性作为输入。

顶点处理:塑造场景

在这个阶段,来自模型的原始顶点数据被转换为适合GPU的格式。顶点处理器,也就是vertex shader,会通过相机变换,对这些顶点进行一些位置变换(缩放、旋转、平移),来定位模型在相机视野内的位置。此外,还会进行裁剪计算,其目的是将那些不在摄像机视野内的顶点裁剪掉。

光栅化:从多边形到像素

在光栅化之前,会有一个隐藏步骤,就是图形组装,它可以将邻近的三个顶点连接成一个三角形,这时候仍然是3D数据,然后就要进行光栅化。光栅化是将几何三角形投影到屏幕上,并形成了二维屏幕坐标系中的某个区域内的节点像素,那么经过光栅化以后,每个像素点都会生成一个片元。片元是包含了很多状态的集合,比如屏幕坐标、深度信息、法线和纹理坐标等,这些状态用于计算每个像素的最终颜色。

片元处理:绘制像素

在这个阶段,屏幕上的每个片元(单个像素)都会经过处理,让纹理和材质的魔力发挥作用。片元着色器(fragment shader)会根据与对应顶点关联的纹理信息和材质属性来确定每个像素的最终颜色。在确定每个片元的颜色信息后,还需要进行逐片元处理,比如深度测试(确定哪些片元更加靠近相机),混合(使物体看起来透明)等。

帧缓冲区:呈现最终图像

最终渲染的图像由单个像素组成,存储在图形卡上的内存缓冲区中,称为帧缓冲区。然后,浏览器会检索这些数据并将其显示在屏幕上,让您的 3D 模型在网页中栩栩如生。

通过理解 3D 渲染管线,我们可以更深入地理解渲染引擎是如何从原始数据开始,实现高级的着色和照明,从而形成引人注目的视觉效果。