通过OpenGL理解前端渲染原理(1)

简介: 通过OpenGL理解前端渲染原理,本文着重介绍渲染管线工作流程。

通过OpenGL理解前端渲染原理,本文着重介绍渲染管线工作流程。

一、OpenGL

OpenGL,是一套绘制3D图形的API,当然它也可以用来绘制2D的物体。OpenGL有一大套可以用来操作模型和图片的函数,通常编写OpenGL库的人是显卡的制造者。我们买的显卡都支持特定版本的OpenGL。

下图是用OpenGL做的旋转的立方体。

二、渲染原理

2.1 渲染管道

在OpenGL中,所有东西都在一个3D的空间里,而我们的屏幕和窗口都是2D的,所以OpenGL需要将3D的坐标转换成2D的坐标,做这件事的是OpenGL中的渲染管道(graphics pipeline)。

渲染管道可以分成两大部分:第一部分将3D坐标转换成2D坐标;第二部分把2D的坐标转换成实际的像素。

2.2 着色器

通常来说,渲染管道把一组3D坐标转换成屏幕上带有颜色的2D像素需要经过很多步。上一步的输出作为下一步的输入,所有步骤都是高度专一的,每步都有一个特定的函数,且可以很容易地并发执行。显卡有数千个处理核心来快速处理渲染管道中的数据,而这些是在每个步骤中通过运行在GPU上的多个小程序来处理的,这些小的程序被称之为程序着色器(shader)。

其中的一些着色器是可以配置的,开发者可以根据需求配置自己的着色器去替代已经存在的那些,这就让我们能够更自由和细粒度地控制渲染的过程。同时,因为它们运行在GPU上,又给我们保留了珍贵的GPU时间,在平时的开发中,我们也要充分利用GPU渲染来提高软件性能。

着色器通常使用GLSL来写,全称是OpenGL Shading Language。

2.3 举个例子

下图展示了一个抽象的渲染管线中的步骤,其中蓝色部分是我们可以注入自己的着色器。

通过上图我们发现,要把顶点数据转换成全渲染的像素要经过很多步,接下来我们对每一个步骤和代码进行简单的解释。

我们在渲染管线中传入一组可以组成三角形的3D坐标数据,这组数据即顶点数据。顶点数据是顶点的集合,而一个顶点是一个3D坐标的集合。

渲染管线的第一步是顶点着色器(Vertex Shader)。我们这里传入的是一个简单的顶点,顶点着色器可以让我们做一些基础的处理操作,比如顶点的属性。

在初始装配阶段,也就是Shape Assembly阶段,从顶点着色器中输出的顶点会形成一个原始的形状。本例中,输出的顶点形成的是一个三角形。

从初始装配阶段到geometry shader阶段,我们可以通过发散其他顶点来形成新的图形,本例中形成了第二个三角形。

在Tessellation Shader阶段,可以把上一阶段给出的原型图再分割成若干个小的原型图。本例中,可以形成更多的三角形来创造一个更加平坦、顺滑的环境。这么说可能难以理解,我们结合下图来进一步阐述,这就是细分曲面着色器的作用。

细分曲面着色器的下一阶段是光栅化阶段(Rasterzation stage),在这一阶段会对最终的原型和呈现在屏幕上的对应像素做一个映射,形成fragment,供下一阶段的fragment shader使用。

Fragment shader最主要的使命是计算出一个像素的最终颜色,在这个阶段我们可以使用OpenGL中一些高级的特效。通常fragment shader会包含3D界面的多个数据,包括灯光、阴影、颜色等等。

当所有对应的颜色都确定以后,最终的原型将会被传入最后一个步骤,我们称之为Alpha test and blending阶段。这个阶段会判断相应的深度,比如一个物体可能在另一个物体的后面,那它可能采用其他的颜色;或者如果该物体被遮挡,可能会被裁掉。

如上文所述,我们可以看到整个渲染管线的步骤和逻辑是十分复杂的,这其中包含了很多个可以改变的步骤,但我们一般只操作Vertex Shader 和 fragment shader,其他的着色器我们会直接采用默认的。在实际的OpenGL编程中,我们至少需要定义一个Vertex Shader和Fragment shader。(需要说明的是,OpenGL 3.1之前的版本包含了固定管线,从3.1版本开始,固定管线从核心中删掉了,因此我们必须使用着色器去工作)。

三、总结

本文为该系列文章的第一篇,先简单介绍OpenGL的一些原理,后续文章中会添加新的代码分析,包括着色器(Shader)、纹理(Textture)、变形(transformation)、坐标系统(Coordinate systems)、相机(Camera)等。

作者:崔晓迪

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
4月前
|
前端开发 JavaScript 定位技术
一、前端高德地图注册、项目中引入、渲染标记(Marker)and覆盖物(Circle)
文章介绍了如何在前端项目中注册并使用高德地图API,包括注册高德开放平台账号、引入高德地图到项目、以及如何在地图上渲染标记(Marker)和覆盖物(Circle)。
117 1
|
1月前
|
移动开发 缓存 前端开发
深入理解前端路由:原理、实现与应用
本书《深入理解前端路由:原理、实现与应用》全面解析了前端路由的核心概念、工作原理及其实现方法,结合实际案例探讨了其在现代Web应用中的广泛应用,适合前端开发者和相关技术人员阅读。
|
2月前
|
前端开发 开发者
本文将深入探讨 BEM 的概念、原理以及其在前端开发中的应用
BEM(Block-Element-Modifier)是一种前端开发中的命名规范和架构方法,旨在提高代码的可维护性和复用性。通过将界面拆分为独立的模块,BEM 提供了一套清晰的命名规则,增强了代码的结构化和模块化设计,促进了团队协作。本文深入探讨了 BEM 的概念、原理及其在前端开发中的应用,分析了其优势与局限性,为开发者提供了宝贵的参考。
57 8
|
2月前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
81 1
|
2月前
|
监控 前端开发 jenkins
Jenkins 在前端项目持续部署中的应用,包括其原理、流程以及具体的实现方法
本文深入探讨了Jenkins在前端项目持续部署中的应用,涵盖其基本原理、流程及具体实现方法。首先介绍了Jenkins的基本概念及其在自动化任务中的作用,随后详细解析了从前端代码提交到生产环境部署的全过程,包括构建、测试、部署等关键步骤。最后,强调了持续部署中的代码质量控制、环境一致性、监控预警及安全管理等注意事项,旨在帮助开发者高效、安全地实施持续部署。
69 5
|
3月前
|
JavaScript 前端开发 算法
前端优化之超大数组更新:深入分析Vue/React/Svelte的更新渲染策略
本文对比了 Vue、React 和 Svelte 在数组渲染方面的实现方式和优缺点,探讨了它们与直接操作 DOM 的差异及 Web Components 的实现方式。Vue 通过响应式系统自动管理数据变化,React 利用虚拟 DOM 和 `diffing` 算法优化更新,Svelte 通过编译时优化提升性能。文章还介绍了数组更新的优化策略,如使用 `key`、分片渲染、虚拟滚动等,帮助开发者在处理大型数组时提升性能。总结指出,选择合适的框架应根据项目复杂度和性能需求来决定。
|
3月前
|
前端开发 JavaScript API
深度剖析:前端如何驾驭海量数据,实现流畅渲染的多种途径
深度剖析:前端如何驾驭海量数据,实现流畅渲染的多种途径
96 3
|
3月前
|
编解码 前端开发 JavaScript
前端:Rem 及其转换原理
Rem是一种用于前端开发的相对字体大小单位,它基于根元素的字体尺寸来定义文本大小,有助于实现响应式布局和可维护性。Rem的转换原理是通过相对于HTML根元素的字体大小来设置子元素的字体大小,从而实现统一的比例调整,提高页面的适应性和灵活性。此方法简化了跨浏览器和设备的布局调整,增强了用户体验。
|
4月前
|
移动开发 前端开发 JavaScript
浅谈前端路由原理hash和history
该文章详细解析了前端路由的两种模式——Hash模式与History模式的工作原理及其实现方式,并通过实例代码展示了如何在实际项目中运用这两种路由模式。
|
3月前
|
缓存 JavaScript 前端开发
拿下奇怪的前端报错(三):npm install卡住了一个钟- 从原理搞定安装的全链路问题
本文详细分析了 `npm install` 过程中可能出现的卡顿问题及解决方法,包括网络问题、Node.js 版本不兼容、缓存问题、权限问题、包冲突、过时的 npm 版本、系统资源不足和脚本问题等,并提供了相应的解决策略。同时,还介绍了开启全部日志、使用替代工具和使用 Docker 提供 Node 环境等其他处理方法。
1697 0