浏览器和图形引擎渲染对比


73c9cff1c2b0cdf26fe821712337a262.png

本文受众是专业的图形开发者和前端开发者,从介绍浏览器渲染引擎开始,逐渐引出和图形引擎的比较,尝试从图形视角探索和理解浏览器的渲染原理。

浏览器引擎

浏览器引擎是浏览器的核心部分,负责解析网页内容(如 HTML、CSS 和 JavaScript)并呈现给用户。各种浏览器可能使用不同的引擎,这导致了不同浏览器之间在渲染页面时可能会有细微的差异。以下是一些主要的浏览器引擎及与其关联的浏览器:

  • IE: Trident

  • WebKit: Safari

  • Blink: Chrome、Edge

WebKit

2ca2d636cadd4b0e66239feec1fc21f5.pngwebkit

以 WebKit 为例,WebKit 是一个开源的 Web 浏览器引擎,它为多种浏览器提供支持,如 Apple 的 Safari 浏览器。它起源于 KDE 项目的 KHTML 和 KJS 库,但后来由 Apple 进一步发展并开源,从而产生了 WebKit。WebKit 代码库主要是用 C++ 编写的,其中包含一些 C 和汇编代码。

主要特点和组件:

  • WebCore: 这是 WebKit 的主要部分,负责渲染 HTML 和 CSS。这基于原先的 KHTML。

  • JavaScriptCore: 负责执行 JavaScript,基于原先的 KJS。
    02564b87625266a2addcd51febb9fe0f.png

在 WebKit 的成功之后,Google 最初使用 WebKit 为其 Chrome 浏览器提供支持,但后来 Google 选择分叉并创建了自己的引擎,名为 Blink。

时间线

de17d79c637318930dcedf6c423af0fc.png

WebCore

88ebb02372aec115719be4839f77bb59.png

WebCore 是 WebKit 浏览器引擎的核心部分,将网页内容转化为用户可以看到和与之互动的视觉表示。

WebCore 是 WebKit 最大的组件,该层实现了大部分 Web API ,最重要的是负责解析 HTML 和 CSS,计算布局,并渲染页面。它处理页面中的所有元素,包括文本、图像、视频、SVG、Canvas、WebGL、动画、音频等。它还实现了 CSS JIT,这是现有的唯一 CSS 即时编译器。

渲染过程

WebCore 的渲染过程涉及多个步骤,从接收原始的 HTML、CSS 和 JavaScript 资源开始,到生成用户在屏幕上看到的最终像素结束。以下是基本的渲染步骤:

91683e04878835ee300a9073cae65a6c.png
  1. 解析(CPU):

  • WebCore 开始通过解析 HTML 生成一个 DOM(Document Object Model)树。

  • CSS 也会被解析,生成一个叫做 CSSOM(CSS Object Model)的结构。CSS 是告诉引擎如何在屏幕上呈现 DOM 树的语言。每个 Web 引擎都使用复杂的机制来遍历 DOM 中的所有内容并应用 CSS 定义的规则。

  1. 合并 DOM 和 CSSOM(CPU): DOM 和 CSSOM 被结合,生成一个渲染树(Render Tree)。这个树只包含实际需要被渲染的元素,不包括例如 display: none 的元素。

  2. 布局(CPU): 布局阶段开始,浏览器确定所有有可视表现的元素在屏幕上的确切位置和大小。每个元素将获得一个确定的屏幕坐标。

  3. 划分图层(CPU): 图层是独立于其他内容进行合成的渲染单位,它的决策是基于布局完成后的信息。图层的创造是为了优化性能。一些特定的 CSS 属性和操作,如动画、3D 变换、视频播放等,如果能在它们自己的图层上运行,通常可以更高效地渲染。

  4. 绘制(CPU + GPU): 绘制阶段开始时,WebCore 会遍历渲染树,并使用 UI 后端层来绘制每个元素的具体像素。

  5. 合成(GPU): 对页面上的元素进行分层,并在合成阶段将它们按正确的顺序合并为一个图层,然后呈现给用户。合成通常是渲染流程的最后一个阶段。在这个阶段,浏览器会处理那些可以被 GPU 直接处理的工作,例如页面的滚动、元素的移动和透明度的变化。因为这些操作不需要重新计算布局或重绘整个页面,所以它们通常会比其他操作更加高效。

绘制和合成

绘制和合成大部分是在 GPU 中进行的,对于我们图形开发者来说,进入到了我们熟悉的语境。

绘制

绘制(Painting)过程可以涉及到调用 GPU API,但这取决于具体的渲染场景和浏览器的优化策略。

在浏览器的渲染流程中,"绘制" 通常指的是将渲染树中的每个元素转换为像素数据的过程。这个过程可能首先在 CPU 上完成,并产生一个位图。然后,这个位图可以被上传到 GPU 并存储为纹理,随后在合成阶段由 GPU 处理。

但是,随着硬件加速绘图技术的普及,越来越多的绘图任务直接在 GPU 上进行,特别是当涉及到复杂的图形效果(如 CSS 滤镜、渐变等)时。在这种情况下,浏览器会直接调用 GPU API(例如 OpenGL 或 DirectX)来进行绘图。

所以,有时浏览器的绘制过程是通过调用 GPU API 来完成的,但并不总是这样。具体情况取决于浏览器的实现、页面的内容以及用户设备的硬件和驱动支持。

UI 后端层则负责与特定平台的图形和 UI 系统进行交互。这样,渲染引擎可以“写一次,到处运行”,而不必为每个平台编写特定的绘图代码。UI 后端层为浏览器提供了一个平台无关的方法来绘制其内容,使得浏览器可以跨多个操作系统平台工作,而无需担心每个平台的绘图特定细节。

  • Windows:UI 后端层可能使用 DirectX 进行绘图

  • macOS: Core Graphics、Metal

  • Linux:它可能使用 X11 或 Wayland 等

  • iOS :Core Graphics 和 Metal

  • Android:OpenGL ES 或 Vulkan

绘制过程

当 WebCore 进入绘制阶段并开始遍历渲染树时,其主要目的是将每个可见的渲染对象绘制到屏幕上。以下是在这个阶段中的主要步骤和发生的活动:

  1. 确定绘制顺序: WebCore 会根据渲染树中的层次结构确定绘制的顺序。基本的原则是,先绘制在底部的元素,再绘制在其上方的元素。这确保了层叠上下文和 z-index 的正确处理。

  2. 裁剪和隐藏: 不是渲染树上的所有元素都需要绘制。有些元素可能位于视口之外,或者被其他元素完全遮盖。通过裁剪和优化,WebCore 可以跳过这些元素,从而提高绘制的性能。

  3. 调用平台相关的绘图 API: WebCore 本身不直接处理低级的图形操作。相反,它依赖于底层的图形 API(例如 macOS 上的 Core Graphics 或 Windows 上的 Direct2D)来执行实际的绘制。

  4. 背景和边框: 对于每个需要绘制的渲染对象,WebCore 首先绘制背景颜色和背景图片(如果有的话),然后绘制边框。

  5. 文字和图像: 接下来,WebCore 会绘制文本、图像和其他内容。对于文本,它会处理字体、大小、颜色和其他样式。对于图像,它可能还会进行缩放或其他转换。

  6. 子元素绘制: 对于容器元素(例如一个具有子元素的 <div>),WebCore 会递归地遍历其子渲染对象,并对每个子对象重复上述的绘制过程。

  7. 处理透明度和复合效果: 如果渲染对象有透明度、阴影或其他复合效果,WebCore 在绘制时会应用它们。

  8. 处理交互状态: 某些元素可能具有交互状态,如:hover 或 :active。WebCore 会确保这些状态下的样式得到正确的反映。

一旦遍历完成并且所有可见的渲染对象都被绘制到了屏幕上,绘制阶段就结束了。

合成

为了提高性能,现代浏览器会尽可能地利用合成。例如,当你使用像transformopacity这样的 CSS 属性时,浏览器可能会为该元素创建一个新的合成层。这样,当该元素发生变化时,浏览器只需要更新那个合成层,而不是整个页面。这大大提高了性能,特别是在移动设备和低功耗设备上。

合成(Compositing)主要是在 GPU 中进行的。现代浏览器为了提高渲染性能,尤其是动画和页面的平滑滚动,会尽量将合成任务交给 GPU 处理。这是因为 GPU 在处理像素和图层操作上特别高效,特别是涉及大量并行计算时。

当浏览器决定为某个元素创建一个新的合成层时(例如,使用了transformopacityfilters或其他会触发合成的 CSS 属性时),该元素的渲染内容会被发送到 GPU,存在一个称为纹理(texture)的结构中。随后,当这个元素需要移动或进行其他视觉变化时,GPU 只需简单地操作这个纹理,而无需重新计算或重绘整个页面。这样可以大大提高性能。

简而言之,合成是在 GPU 中进行的,利用了 GPU 的并行处理能力和专门的图形处理技术来实现高效渲染。

合成主要是在 GPU 中将不同的图层组合到一起以形成最终的页面视图。在这个过程中,各个图层可以独立地进行移动、缩放或调整透明度等操作,而不需要重新绘制整个页面。利用 GPU 进行合成可以提高渲染速度和效率。

对比图形引擎

3D 图形引擎是专门用于创建、渲染和操作 3D 内容的软件框架。它通常包括物理模拟、光照计算、动画、模型加载等功能。

以 three.js 为例,它使用 WebGL API 在浏览器中进行 3D 渲染。而浏览器中的常规页面渲染,例如 WebCore 的渲染,是基于浏览器的标准渲染流程,主要处理 2D 内容。

three.js 旨在创建 3D 世界和效果,而浏览器的 2D 渲染更关心内容的结构和样式。

核心概念对比

当我们试图类比浏览器的 2D 页面渲染和 three.js 的 3D 渲染时,可以发现一些相似的核心概念,尽管这些概念在每个上下文中可能有所不同。以下是一些相似性:

元素/物体

f9c3135e0c52cc778e488c4596f4202d.pngCCS 盒模型

8b3a777aed49dd4bc9324725ce5877ed.png3D中简单物体

e62bacc62a15c147dec9c50bca554166.png复杂人物

3e1ca440939929eaf60fef9aa249c60f.pngCG渲染

  • 2D 页面渲染:页面上的每个 HTML 元素,如<div><img><p>等。

  • three.js/3D 渲染:场景中的每个 3D 物体,如THREE.MeshTHREE.Group等。

样式/材质

e7b3d24d2c9f648dd8599ad4c57f4360.png 7e13a7dfb4fae987e8a10f10ff701e52.png
  • 2D 页面渲染:CSS 样式决定了元素的外观,如背景色、字体、边框等。

  • three.js/3D 渲染:材质决定了 3D 物体的表面外观,如颜色、光泽、纹理等。

层次结构/场景

fa6db6b00cb18dc73fbebab8f21f3288.png 75836af5d4d3b65f934dfb52bb2b442e.png
  • 2D 页面渲染:DOM 树表示了元素之间的层次关系。

  • three.js/3D 渲染:场景(THREE.Scene)包含了所有 3D 物体,并定义了它们在 3D 空间中的关系。

视图/摄像机

  • 2D 页面渲染:视口定义了用户当前可以看到的页面部分。

  • three.js/3D 渲染:摄像机定义了用户从哪个角度和位置看到 3D 场景。

127b72e296f8e3df6997d5644ffb025d.png 1e73c1c58a3e758ce3bcf949952999e9.png

光照/颜色

  • 2D 页面渲染:颜色定义了元素的背景、文本和边框颜色。

  • three.js/3D 渲染:光源影响了物体的颜色和明暗,与物体的材质和纹理结合,决定了其最终的外观。

95852181937401ca7d357c9bcc1ab61f.png c6ca3843b283e0cb0899cf02873c8e99.png

动画/变换

  • 2D 页面渲染:CSS 动画和转换可以改变元素的位置、大小、颜色等。

  • three.js/3D 渲染:动画库和变换方法可以改变物体的位置、大小、旋转等。

交互/事件

  • 2D 页面渲染:可以使用事件监听器捕捉元素的点击、鼠标悬停、焦点等事件。

  • three.js/3D 渲染:通过光线投射,可以监听物体的点击、交叉、拖放等事件。

渲染过程对比

8c6de0d5476d25e5ff99c2365a5be0a2.png

进化中的变和不变

图形引擎的演变

从 2005 年 Unity 的亮相,到 2010 年 Three.js 的出现,再到 2013 年 Babylon.js 的发布,不断演进出新的图形引擎并在各自领域发挥作用。

  • 变的是底层技术和上层框架:在时间的长河中,上层的应用框架持续调整、优化,底层的渲染技术也衍生出从前向渲染、后向渲染、全局光、基于物理的渲染等技术,再到到 WebGL1、WebGL2、WebGPU 等底层的进化。

  • 不变的是概念模型:即使技术在进步,某些核心元素如网格、材质、纹理和灯光等概念始终保持不变。

浏览器的演进

浏览器的历史自 1995 年 IE 的诞生开始,经历了 2003 年 Safari 的发布,再到 2008 年 Chrome 的出现。

  • 变的是底层技术和上层框架:在各种应用框架如 jQuery、Angular、React 的推出与退场中,底层的渲染技术也在不断的升级与优化。

  • 不变的是概念模型:尽管浏览器技术在飞速进化,但盒模型、结构树、样式树和渲染树这些核心概念始终保持其原始的形态。

所以,无论是图形引擎还是浏览器,面对各种创新与挑战,都需要有一个稳固的基础。这就像建筑,无论外部如何装修,基石始终不变。当我们面对不同的领域,构建系统的解决方案时,构建模型是首先要思考的问题。在应用层面,需要不断为特定的细分领域找到最佳的解决方案;而在底层,持续优化效率是确保长远发展的关键。

加入我们

🚕 汽车驱动美好人生,DCarFE 超百人团队等你加入!

我们致力于成为汽车领域最专业、最开放的前端技术团队,打造懂车帝这辆卓越战车上最极致,最酷炫的引擎。我们深耕汽车互联网行业,为汽车 C 端用户、汽车内容创作者、厂商经销商、销售交易环节提供极致、丰富、好用的产品体验,为懂车帝 30+ 业务方向的提供高质高效的研发工作。同时团队还聚焦在 3D 沉浸式看车、行业 SAAS 系统解决方案、WebAR/VR 在汽车领域的深度应用、AI 与前端的结合及应用、汽车智能营销创意平台、车机互联等方向的探索和实践。我们主要技术栈有 React、TypeScript、Web3D、Golang。

懂车帝北京、重庆、杭州均设立了研发团队,点击左下角“阅读原文”或扫描下方二维码,我们期待你的加入!

d70dc013e6413d8b6bda4dd252b3c389.png

  • 懂车帝 - 前端开发工程师:https://job.toutiao.com/s/idwN1FqS

  • 社招 - 懂车帝 - Web3D 开发高级工程师:https://job.toutiao.com/s/rweXPdL

参考资料

  • https://github.com/WebKit/WebKit/blob/main/Introduction.md

  • https://webkit.org/blog/3271/webkit-css-selector-jit-compiler

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值