# 图形学基础
# svg、canvas、webgl的区别以及各自的适用领域
名称 | 定义 | 应用领域 |
---|---|---|
svg | 是基于 XML 的矢量图形格式,不依赖分辨率,可以放大缩小而不失真。它使用 XML 标签来描述二维图形 | 需要高度缩放和交互的场景,如图标、信息图形、UI 组件等 |
canvas | 是逐像素渲染的位图格式, 依赖分辨率, 放大缩小会失真。它使用 JavaScript 来绘制二维图形 | 需要高性能绘制和动画的场景,如游戏、数据可视化等 |
webgl | 是一种实现在浏览器端的3D绘图标准,WebGL基于OpenGL的标准封装的一套Javascript 的图形API | 需要展示 3D 内容和场景的场景,如 3D 模型查看器、3D 游戏等 |
总的来说,
- SVG 强调于图形, Canvas 和 WebGL 强调于绘制
- SVG 强调于低复杂度、低动态化的场景, Canvas 和 WebGL 适用于高复杂度、高动态化的场景
- Canvas 和 WebGL 依赖于 JavaScript,能够提供更高的可定制性和动态特性
- WebGL 专注于 3D 图形,提供了 GPU 加速的 3D 图形绘制能力
# webgl的运行流程、顶点着色器与片断着色器
运行流程分为以下阶段:
图片取自 https://juejin.cn/post/7226301946838417467
- 顶点着色器 - 通过顶点 着色器语言(GLSL)计算每个顶点的最终位置、颜色、纹理坐标等数据
图片取自 https://juejin.cn/post/7226301946838417467
图元装配 - 将计算出来的顶点数据组装成图形要绘制的形状, 如三角形、矩形等
光栅化 - 将组装出来的图形分解成像素, 计算每个像素的最终颜色
片元着色器 - 通过片元 着色器语言(GLSL)计算每个像素(片元)的最终颜色
图片取自 https://juejin.cn/post/7226301946838417467
深度测试 - 判断像素的深度值, 只绘制最接近视点的像素
模板测试 - 通过模板遮罩剔除不需要的像素
融合 - 将最终的像素颜色值输出到帧缓冲
这里重点提到 顶点着色器 和 片元着色器
顶点着色器主要功能
计算顶点的最终位置 - 通过矩阵变换(平移、旋转、缩放)等操作。
计算顶点的颜色 - 通过光照模型计算出顶点的漫反射颜色。
计算顶点的纹理坐标 - 对应到2D或3D贴图上。
将计算出来的数据通过varying变量传递给片元着色器。
片元着色器主要功能
根据varying变量的值, 通过线性插值计算出每个像素的最终值。
计算出每个像素(片元)的最终颜色。
通过纹理采样得到每个片元的值。
通过片元着色器语言, 计算出复杂的着色效果。
输出gl_FragColor变量, 包含最终的片元颜色值。
- 模型格式的了解、材质、贴图、法向贴图
参考资料
通过组合不同的贴图和设置合适的材质属性, 可以创建出各种复杂的材质效果.
贴图(Map)是将图像(Texture)映射到3D几何体表面上的过程
贴图
- Diffuse Map(漫反射贴图): 表示物体的颜色
- Normal Map(法线贴图): 存储表面法线方向信息
- Specular Map(高光贴图): 控制高光的颜色和强度
- Gloss Map(光泽度贴图): 定义物体的粗糙度
- Displacement Map(置换贴图): 改变物体几何形状
- Ambient Occlusion Map(环境光遮蔽贴图): 模拟物体表面受环境光遮蔽的情况
- Emissive Map(自发光贴图): 控制物体发出的自发光颜色
纹理(Texture)是贴图的基础, 是重复性的图像数据
纹理
常见的格式有:
- RGB(A)格式: 包含R、G、B三个(或四个)颜色通道
- Normal Map格式: 用于法线贴图
- Height Map格式: 用于置换贴图
- Gradient Map格式: 用于渐变效果
- Color LUT格式: 颜色查找表
材质(Material)包含了物体表面与光线交互的所有信息
材质
- 贴图(Maps): Diffuse Map、Specular Map等
- 光照模型(Shader): Lambert、Phong、Cook-Torrance等
- 材质属性: 颜色、透明度、光泽等
# 坐标系变换过程、渲染管线的流程
坐标系变换过程指将一个坐标系下的点、向量或坐标变换到另一个坐标系下的过程。总结分为两步:
- 确定变换矩阵
- 通过变换矩阵变换坐标
渲染管线的流程主要分为几何阶段和光栅化阶段两个大部分
整个过程可以概括为:
通过着色器和各种转换, 将3D空间中的物体渲染到2D屏幕上
3D顶点坐标 -> D屏幕坐标 -> 片元 -> 像素颜色
几何阶段
主要负责将3D空间中的顶点数据转换到2D屏幕空间
- 顶点着色器: 对顶点数据进行变换、光照计算等
- 曲面细分着色器: 对顶点进行细分, 增加细节
- 裁剪: 剔除不可见的顶点
- 投影变换: 将3D坐标转换为2D屏幕坐标
光栅化阶段
主要将顶点数据转换为片元(像素),最终得到像素颜色
- 三角形设置: 将顶点连接成三角形网格
- 三角形遍历: 得到三角形覆盖的像素位置, 生成片元
- 片元着色器: 根据输入数据计算片元颜色
- 片元操作: 对片元进行测试(深度、模板等)和颜色混合, 得到最终像素颜色
# 前向渲染/延迟渲染、分块渲染
前向渲染(Forward Rendering)
- 着色、几何体、材质在同一环节计算
- 适合简单场景和半透明表面
- 可以使用多重采样抗锯齿(MSAA)
- 擅长材质和灯光效果
- 动态光照对性能有影响
- 公式复杂度: O(num_geometry_fragments * num_lights)
延迟渲染(Deferred Rendering)
- 使用GBuffer缓存, 分两步进行着色
- 适合复杂场景和动态光照
- 不能使用多重采样抗锯齿(MSAA)
- 禁用一些功能时更灵活
- 动态光照对性能影响小
- 公式复杂度: O(screen_resolution * num_lights)
分块渲染(Forward+ Rendering)
- 将场景分块,对不同块使用不同渲染方式
- 简单块使用前向渲染
- 复杂块使用延迟渲染
- 融合前向和延迟渲染的优点
- 适合大型复杂场景
- 需要更多开销切换不同渲染方式
总的来说:
- 前向渲染适用于简单场景, 延迟渲染适用于动态光照场景
- 分块渲染可以将场景分块, 针对不同块使用不同渲染方式, 融合前向渲染和延迟渲染的优点
- 选择渲染方式需要综合考虑场景复杂度、硬件配置、目标效果等多方面因素
# 帧缓冲、离屏渲染
名称 | 定义 | 目的 | 过程 | 性能 | 应用场景 |
---|---|---|---|---|---|
帧缓冲(Frame Buffer) | 屏幕显示图像的直接映射, 它存储着最终需要显示在屏幕上的像素数据 | 最终显示在屏幕上的目标 | 帧缓冲直接将渲染结果输出到屏幕 | 直接输出, 性能更高 | 简单的渲染场景 |
离屏渲染(Off-Screen Rendering) | 将渲染结果先渲染到一块离屏内存区, 然后再将结果复制到帧缓冲显示 | 将渲染结果先存储在一块内存, 然后再复制到帧缓冲显示 | 先将结果渲染到一块内存, 然后再将这块内存复制到帧缓冲 | 多了一次内存复制的过程, 性能相对较低 | 需要多次修改渲染结果的复杂场景, 如进行特效处理 |
总结:
- 帧缓冲是最终渲染输出的目标, 离屏渲染是一种先渲染到内存再输出的方式
- 离屏渲染主要用于处理那些无法通过单次遍历帧缓冲就能完成渲染的复杂场景
# 光照类型、光照模型
光照类型主要分为两种类型:
直接光照: 光源直接照射到物体表面上, 产生的光照效果
间接光照: 光源光线首先照射到其他物体上, 然后再反射或透射到目标物体上, 产生的光照效果
直接光照比较直接和明显, 主要影响物体的明暗程度. 间接光照则会影响物体的亮度分布和阴影效果
光照模型是根据光学定律,模拟自然界中光照物理过程的计算机模型. 主要有以下:
光照模型
环境光模型: 只考虑环境光的影响
漫反射模型(Lambert模型): 考虑漫反射效果
镜面反射模型(Phong模型): 考虑镜面反射效果
Blinn-Phong模型: 改进自Phong模型, 加速了镜面反射计算
基于物理的渲染方程: 基于物理光学原理的模型, 考虑了多重反射和全局光照
简单的光照模型只考虑直接光照, 称为局部光照模型. 而考虑间接光照和全局光照效果的模型称为全局光照模型.
常见的全局光照模型有: 光线跟踪、辐射度方法和光子映射. 它们能产生更真实的光照效果, 但计算量也相对较大
# 如何进行大模型的渲染、八叉树优化
八叉树: 通过将模型分组,加速模型的遍历和选取,从而改进交互体验
主要思路:
建立八叉树数据结构。将整个场景空间划分为多个相互不重叠的八叉树叶节点(cell)。
将模型添加到对应的八叉树叶节点中。
进行拾取操作时,首先根据鼠标位置找到包含该位置的八叉树叶节点。
然后逐级遍历八叉树,直到找到包含鼠标位置的叶节点。
只对该叶节点中的模型进行相交测试,从而加速拾取
# 光线追踪、实时光线追踪
光线追踪(Ray Tracing)是一种计算机图形学中用于图像合成的算法。它模拟光线从光源出发,沿着指定方向传播,与场景中的物体相交,最后到达观察者眼睛的物理过程
光线追踪基本思想
光线追踪模拟了光在物理世界中实际的传播过程,可以生成更真实逼真的图像
- 从观察者眼睛出发,发射光线入场景
- 计算这些光线与场景中的物体的交点
- 计算交点处的着色,包括直接照明和间接照明
- 将各个像素的最终颜色合成为渲染图像
光线追踪
与光栅化渲染相比, 优势在于
- 可以处理复杂的几何体和非平滑表面。
- 可以产生高质量的透视效果和阴影。
- 可以模拟镜面反射、折射、全局光照等复杂效果
常见光线追踪算法:
- Whitted 光线追踪: 使用递归追踪反射和折射光线
- 分布式光线追踪: 基于随机采样的光线追踪
- 路径追踪: 每次只追踪一条光线,通过多次采样来减少噪点
- 双向路径追踪: 同时从视点和光源出发追踪路径
- Metropolis 光线追踪: 使用 Metropolis 采样方法探索路径空间
总结: 光线追踪算法模拟了光在物理世界中真实的传播过程。它能生成更逼真的图像效果,但是计算量很大
实时光线追踪是一种利用光线追踪算法在高性能图形处理器上实现的技术。它能够以每秒几十或几百帧的速度模拟光线在场景中的物理行为,产生出逼真的全局光照、反射和透明效果.
主要依赖于专门用于光线追踪的GPU加速器(如RT Core)和降噪算法。目前主流的API有 DirectX Raytracing(DXR)
和 Vulkan
实时光线追踪
与传统的光栅化渲染相比, 优势:
- 更逼真的全局光照效果。考虑到屏幕外的反射和折射
- 更准确的区域阴影。根据光源大小产生柔化阴影
- 更好的半透明材质效果。考虑到正确的反射、吸收和折射
- 更精细的反射效果。考虑到屏幕外的反射
# 实战示例
To be Continued...