进击的 Vulkan 移动开发(二)之谈谈对渲染流程的理解

简介: 都说 OpenGL 、Vulkan 是用来绘制二维、三维图形的,那么这个绘制渲染的流程到底是怎么样的呢?这里,谈谈我自己对它的理解。

作者:星陨

从泥巴到工艺品

先来举一个 玩泥巴 的例子,也就是我国的传统工艺 —— 陶瓷工艺

以我国传统的陶瓷工艺为例,先看看伟大的工匠们是如何把泥巴变成了精美的艺术品。

上面是一张粗略的示意图,详细的陶瓷制作流程可以自行网上搜索,或者 参考这里

小时候大家肯定都玩过泥巴啦,沾一点水之后可以捏成各种各样的形状,没玩过的话,橡皮泥也行。

现假设我们要用泥巴做一个陶瓷的彩色方块。

那么首先就得从一堆稀泥里面捏出一个方方正正的小块,注意把小块的六个面都打磨均匀了。

然后再放在火窑经过高温烧制,七七四十九小时之后,就可以出炉了,此时小方块就已经变硬了,而且它的形状就是我们捏完后的样子。

待冷却之后就可以给它上色了,掏出画笔,涂上代表自己心情的颜色,这样就制作完成了一个陶瓷的彩色方块(是不是很简单呢(づ。◕‿‿◕。)づ)。

OpenGL 的渲染

OpenGL 的渲染流程和陶瓷工艺在某些地方是有着相同之处的。

首先,OpenGL 的渲染是讲究先有形后有色。也就是说用 OpenGL 去渲染绘制二维或三维的物体,你得先把物体给勾勒描绘出来。就好比上面提到的陶瓷小方块,在进行高温烧制之前,也是要先把物体的形状给捏出来的。

在 OpenGL 中提供了几种基本的绘制图形,比如点、线、三角形等,就是使用这几个基本图元去描绘这万千世界,比如绘制一个矩形,可以用两个三角形拼接起来。

在陶瓷小方块的例子中,捏完形状之后就可以高温烧制了,然后再涂色。在 OpenGL 中也有类似高温烧制的一步,叫做 光栅化

强调一下这只是类似的对比,因为这两者还是有差别的。

当我们在构建定义物体形状时,是在三维的坐标系里面,而显示的屏幕确实二维坐标系,这里还涉及到一个三维坐标到二维坐标的转换,待会再说。

假设现在已经执行完了坐标转换,物体的坐标转换成了二维的,那么就需要通过 光栅化 来映射到屏幕的二维坐标上。

以上图作为示例,先定义了三个顶点代表三角形基本图元,再把经过坐标转换之后的三角形映射到屏幕上。而屏幕是由一个一个像素点组成的,光栅化的过程就是要把三角形分解成许多个小的片段,再把这些片段映射到屏幕对应位置上,这样就可以让屏幕显示坐标转换后的物体了。

给三角形显示来个特写如下:

光栅化之后的三角形与屏幕显示的关系。实际上屏幕像素并不是小方格而是像素点,肯定不会有这么夸张的锯齿。

当光栅化操作之后,就可以对它进行着色了。这又回到了上面的例子,陶瓷小方块的涂色阶段,在这个阶段,数字图像处理学科开始发挥它巨大的作用了,各种各样的滤镜、图像效果都是在这个阶段进行的。

用上面的图总结一下目前的渲染流程,这个流程比较简化,理解起来就和上面的陶瓷制作相似,也比较形象的阐述了 OpenGL 渲染从 有形有色 的过程。

现在再来看看坐标转换,坐标转换是在光栅化之前的,如下图:

这里会经过几个坐标的转换,分别是局部坐标、世界坐标、观察坐标、裁剪坐标。最后才是显示到屏幕的坐标。

具体的详细分析可以参考之前写过的相关 博客文章

简单说就是我们有了一个立方体形状,那么我们在不同地方、不同角度看到的物体的不一样的,这是人相对于物体的移动变化。另外还有物体相对人的移动变化,物体移出了我们的视线、物体侧放着、物体反过来对着我们,得到的观察结果也是不一样的。

而坐标转换就是约定好观察者与被观察者之间的位置、角度,这样才能确定看到的结果是什么,对这个结果进行光栅化处理,再映射到屏幕上。

写到这,你以为你就懂了 OpenGL 的渲染流程了嘛?想要更好地发挥 OpenGL 的作用,还需要了解它的各种 测试 和 颜色混合

  • 裁剪测试(Scissor Test)

在经过光栅化和片段着色器处理之后,通过裁剪测试可以选择只在某一个矩形区域内进行绘制,不需要绘制整个屏幕范围。这样的话,就可以在同一屏内分别绘制不同的内容。

  • 模板测试(Stencil Test)

模板测试能够让我们预先定义一个任意模板范围,然后在指定的任意范围内绘制。相比裁剪测试只能在矩形范围内,模板测试更加灵活了。对于某些场合实现效果还是很有帮助的。

  • 深度测试(Depth Test)

深度测试是指在三维坐标里面,距离观察点较远的片段会被前面较近的片段挡住,因此就不需要绘制那些被遮挡看不到的内容了,优化绘制。如果只是绘制平面二维的内容,那么深度测试开不开都没太大影响。

  • 混合测试(Alpha Blending)

混合测试指定就是在原有颜色的基础上用另外的颜色绘制时,如何确定这两种颜色混合后的最终颜色。如果是做贴纸相关应用,要特别注意透明度的问题,看到过一些同学透明度没处理好导致贴纸效果不理想。

经过这些个步骤之后,绘制的内容就会映射到指定的大小范围内,也就是 视口(ViewPort) 的大小,一般都是通过代码来指定这个大小。

而装载绘制内容的就是 帧缓冲(FrameBuffer),绘制的结果就是输出到这了。通过绑定到不同的帧缓冲,可以将绘制结果输出到不同的帧缓冲里。而 OpenGL 中,屏幕就是那个默认的帧缓冲,所以一般就直接输出显示到屏幕上了。当然也可以自己创建一个帧缓冲,用来做离屏渲染等操作。

维基百科 上的图来做个总结:

这个流程图就和上文内容提到的大致相同了,如果你明白了渲染流程,那么看懂这个图应该也不是难事了~

以上就是关于 OpenGL 渲染流程的一个看法和理解,如果有什么不足之处欢迎指出~~

Vulkan 的渲染

接下来看看 Vulkan 的渲染。

先上一张 英伟达(NVIDIA) 公司给出的 Vulkan 组件图。

由于本篇只关注渲染流程,所以组件图中很多是现在不用太过关心的,比如 Image、Command-buffer 等,后面的文章会再做讲解。

看到图中有一个 Graphics pipeline 的组件,这个组件里面就包含 Vulkan 的渲染流程。

Pipeline 组件里面都有哪些操作?看下图~

看到图中中的左边内容是不是有似曾相识的感觉,就和 OpenGL 的渲染流程一样的,也是从顶点 -> 到光栅化 -> 到着色器 -> 到帧缓冲,再加上各种测试。

Vulkan 的 Pipeline 组件就是对应了 OpenGL 的渲染流程,或者说就是图形学里面的渲染流程,因为这个流程、这个原理是不会变的,Vulkan 也没有改变它,只是调用的逻辑结构发生了变化,但万变不离其宗,这也是为什么说要先学会 OpenGL 再来看 Vulkan 。

在 Vulkan 中,Pipeline 组件是可以复用的,通过绑定不同的资源而实现。可以预先创建几个 Pipeline ,在使用时选择对应的 Pipeline ,另外 Pipeline 还可以缓存起来,关于 Pipeline 的具体细节等到使用时再详细阐述。

渲染和 Vulkan 的调用是分开的。Vulkan 的调用很复杂,但是很多和图形学并没有关系,比如多线程、比如资源分配等。

只节选了组件图的一小部分来讲解,更多讲解敬请期待后续文章。

当然,这只是个人的学习经验,仅供参考,有讲的不对之处,欢迎指出,也可以加我微信一起交流学习: zh_ying_13 。

系列文章的代码地址:

https://github.com/glumes/vulkan_tutorial

参考

这里有一些不错的参考链接:
https://www.toutiao.com/a6457289342741119502/
https://zhuanlan.zhihu.com/p/20712354
https://zhuanlan.zhihu.com/p/49112352
https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview

Vulkan 系列文章

「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。

阿里云社区.png

相关文章
|
移动开发 API Android开发
进击的 Vulkan 移动开发之 Instance & Device & Queue
针对每个组件进行学习讲解并配上相关的示例代码,首先是 Instance、Device 和 Queue 组件。
399 0
进击的 Vulkan 移动开发之 Instance & Device & Queue
|
移动开发 API 图形学
进击的 Vulkan 移动开发之 SwapChain
在之前的文章中,讲到了 Command-Buffer 提交给 Queue 去执行,也提到了 Vulkan 实现跨平台机制,是有一些拓展的,这里就讲讲 Vulkan 窗口系统的拓展(Vulkan Window System Integration WSI),如下图所示:
1085 0
进击的 Vulkan 移动开发之 SwapChain
|
移动开发 异构计算 索引
进击的 Vulkan 移动开发之 Command Buffer
此篇文章继续学习 Vulkan 中的组件:Command-Buffer 。
575 0
进击的 Vulkan 移动开发之 Command Buffer
|
3月前
|
开发框架 Dart Android开发
移动应用开发中的创新之路:探索跨平台解决方案
【9月更文挑战第21天】在移动应用的海洋中,开发者们面临着一个不断变化的挑战——如何在多个操作系统上提供无缝的用户体验。本文将探讨跨平台开发的魅力与挑战,并深入分析Flutter框架如何成为现代开发者的利器。我们将通过实际代码示例,揭示Flutter简化开发流程、提高生产效率的秘密。从Dart语言的基础到热重载的便捷性,本文旨在为读者提供一次全面而深刻的跨平台开发之旅。
|
1月前
|
C# Android开发 虚拟化
C# 一分钟浅谈:MAUI 跨平台移动应用开发
.NET MAUI 是 Microsoft 推出的跨平台框架,支持 Windows、macOS、iOS 和 Android。本文从基础概念入手,探讨 MAUI 的常见问题、易错点及解决方案,并通过代码示例详细说明。涵盖平台特定代码、XAML 语法、数据绑定、性能优化和调试技巧等内容,帮助开发者更好地掌握 .NET MAUI。
185 55
|
2月前
|
开发框架 前端开发 Android开发
移动应用开发中的跨平台策略与实践
【9月更文挑战第34天】本文将深入探讨移动应用开发的跨平台策略,包括对React Native、Flutter和Xamarin等流行框架的比较。文章还将分享一些实用的跨平台开发技巧和最佳实践,帮助开发者在多个平台上高效地构建和维护应用。无论你是初学者还是有经验的开发者,这篇文章都会为你提供有价值的见解和指导。
|
1月前
|
开发框架 数据安全/隐私保护 开发者
Flutter 是一款强大的跨平台移动应用开发框架,本文深入探讨了其布局与样式设计
Flutter 是一款强大的跨平台移动应用开发框架,本文深入探讨了其布局与样式设计,涵盖布局基础、常用组件、样式设计、实战应用、响应式布局及性能优化等方面,助力开发者打造精美用户界面。
43 7
|
1月前
|
开发框架 Dart 前端开发
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。
Flutter 是谷歌推出的一款高效跨平台移动应用开发框架,使用 Dart 语言,具备快速开发、跨平台支持、高性能、热重载及美观界面等特点。本文从 Flutter 简介、特点、开发环境搭建、应用架构、组件详解、路由管理、状态管理、与原生代码交互、性能优化、应用发布与部署及未来趋势等方面,全面解析 Flutter 技术,助你掌握这一前沿开发工具。
58 8
|
1月前
|
前端开发 Android开发 开发者
移动应用开发的未来:探索跨平台解决方案##
在移动开发的海洋中,跨平台框架如同一艘能够穿梭于iOS和Android两大操作系统之间的航船。本文将探讨这艘航船的构造—从它的起源、它的引擎(技术架构),到它能抵达的岸边(应用场景)。我们将启航,一探究竟如何在波涛汹涌的市场中找到自己的航线。 ##
31 3
|
1月前
|
开发框架 前端开发 JavaScript
移动应用开发的未来之路:探索跨平台框架
【10月更文挑战第42天】在数字时代,移动应用已成为日常生活的一部分。本文将探讨跨平台开发框架,如React Native和Flutter,它们如何改变开发者构建应用的方式。我们将深入了解这些框架的工作原理、优势以及面临的挑战,并展望未来移动应用开发的发展趋势。通过实例分析,我们旨在为读者提供关于选择合适移动应用开发工具的见解,以适应不断变化的技术环境。