开篇
本篇主要讲的是计算机图形学中比较重要的主题之一,渲染,并且着重于讲述光栅化的渲染方式。
当然,我们要了解光栅渲染这个细分领域(当然这个领域也是及其庞大的),就应该知道它在整个的知识框架中是出于一个什么位置。
古希腊的哲学家亚里士多德曾说过,了解一个事物的最佳方式,就是不断的把它进行分类,当分无可分的时候,你就能准确的理解这个事物了。
我们要了解光栅渲染,其实先要理解什么是渲染。这必将引出它的上一层级,计算机图形学。在图形管道当中,渲染是作为最后一个主要步骤而存在的,是为模型或者动画最终呈现外观的主要步骤。渲染是计算机图形学的主要的子主题之一,也是我们将要讨论的重中之中,因为渲染在实践中总是与图形学的其他的模块有着很深的联系。
计算机图形学,实际上是一个具有广泛的学科关联的科学体系,无法使用某种简单的语句进行准确的定义。但这并不妨碍我们去理解它。 通俗来讲,计算机图形就是研究如何使用计算机来创建和显示图形的一门科学。
一、渲染(Rendering)
定义
渲染是通过计算机程序从2D或3D模型生成图像的自动过程。
作用
渲染在建筑,游戏,模拟,电影或电视视觉效果以及设计可视化的各种场景中都被充分的使用,而每个行业都采用不同的特征和技术平衡。
实现
渲染的实现主要是封装成一个个独立的或者集成在其他游戏、建模、动画引擎或者其他软件里的渲染器。渲染器是一个基于与光学物理,视觉感知,数学和软件开发混合而成的程序。
分类
根据实现的技术不同,渲染主要分为
- 光栅化( rasterization):将矢量顶点组成的图形进行像素化的过程
- 光线投射(ray casting):正向投射。从图像的每一个像素,沿视线方向发射光线,光线穿越整个图像序列,并在这个过程中,对图像序列进行采样获取颜色信息,同时依据光线吸收模型将颜色值进行累加,直至光线穿越整个图像序列,最后得到的颜色值就是渲染图像的颜色。
- 光线跟踪(Ray tracing):逆向跟踪。沿着到达视点的光线的反方向跟踪,经过屏幕上每一个象素,找出与视线相交的物体表面点,并继续跟踪,找出影响点光强的所有光源,从而算出点上精确的光线强度。
根据渲染的时机来分类
- 实时渲染:一般在3D游戏中使用。指计算机边计算画面边将其输出显示。优点是可以实时操控,缺点是牺牲画质。
- 离线渲染:主要用于电影动画。指计算出画面时并不显示画面,计算机根据预先定义好的光线、轨迹渲染图片,渲染完成后再将图片连续播放,实现动画效果。
一般来说,实时渲染的技术方式都是使用的光栅化渲染。我们讲的光栅化就是日常 3D游戏当中实时渲染出来的,是遍计算遍显示,所以秒的帧数可能是不稳定的。
二、GPU(graphics processing unit)
为什么要学习GPU
Gpu作为图像处理器,最初被设计时就是用来做实时的图像渲染(光栅化)的加速的。如果实时渲染器中只使用cpu的渲染器叫做软光栅渲染器,速度慢,实际作用仅能当做学习熟悉渲染过程的手段而没有实际的现实用途,所以我们要了解光栅渲染器,就必然要首先了解这个作为现代个人主机中造价最高的配件GPU。
历史
硬件图形加速器GPU首先出现于渲染管线的末端,首先运行的是三角面扫描线的光珊化。紧接着的下一代硬件沿着渲染管线上溯,到达一些更上级的层次,一些应用程序阶段的算法亦被囊括在硬件加速器的范围内。致力于使用硬件唯一的好处是其超过软件实现的速度,速度是它最关心的问题。
在过去的十年,图形硬件经历了一个不可想象变革。第一块包括硬件顶点处理的商业型图形芯片(NIDIA的Geforce256)在1999年问世。NVIDIA杜撰了图形处理单元(GPU)这一术语去区分Geforce256和之前其它只处理光珊化的芯片。在此后的几年,GPU从原来复杂的可配置固定功能管线到高度可编程的实现,就像白纸一样,开发者可在其上实现他们自己算法。各种可编程着色器是GPU控制的主要手段。
定义
图形处理单元(GPU)是专用电子电路,其被设计为快速操纵和改变存储以加速在用于输出到显示设备的帧缓冲器中的图像的创建。
比较
CPU和GPU之所以大不相同,是由于其设计目标的不同,它们分别针对了两种不同的应用场景。
CPU需要很强的通用性来处理各种不同的数据类型,同时又要逻辑判断又会引入大量的分支跳转和中断的处理。这些都使得CPU的内部结构异常复杂。
GPU采用了数量众多的计算单元和超长的流水线,但只有非常简单的控制逻辑并省去了Cache。GPU的特点是有很多的ALU和很少的cache. 缓存的目的不是保存后面需要访问的数据的。
特点
GPU对于计算量大,但是单个计算难度简单的,并且要重复多次的任务使用,这些可并行,且要反复迭代收敛的东西,通常都是GPU相对擅长的领域。除了图形加速,还有机器学习,人工智能,并行计算等等,当然还可以挖矿这样的。
分类
GPU一般而言一般都是光栅化,不过英伟达今年新出了“光线追踪”GPU Quadro RTX GPU。
三、渲染管线(概念,功能)
渲染是如何进行的呢?为什么叫光栅化渲染呢?这就涉及到我们的渲染管线。这里介绍的主要是必须完成的主要功能,是一种概念上的理论模型,而实际的GPU中可能略有不同。
定义:渲染管道或者渲染管线,是一个概念模型,描述了图形系统在将3D场景渲染到2D屏幕时需要执行的步骤。
应用程序阶段 The Application Stage(CPU)
应用程序阶段一般是图形渲染管线概念上的第一个阶段,开发者通过程序的方式对图元数据等信息进行配置和调控,最后传输到下个阶段。
作用:在应用程序阶段通常可以实现的有碰撞检测、加速算法、输入检测,动画,力反馈以及纹理动画,变换、仿真、几何变形,以及一些不在其他阶段执行的计算,如层次视锥裁剪等加速算法就可以在这里实现。
几何阶段 The Geometry Stage(GPU)
几何阶段主要负责大部分多边形操作和顶点操作
模型视点变换 Model & View Transform:由模型自己的坐标系转换到世界坐标系,然后到视觉空间。由于坐标系的的选取不同而进行的变换。
顶点着色 Vertex Shading:什么是着色呢,着色是指确定材质上的光照效果的这种操作,实际就是确定颜色。因为我们对于渲染而言的要求并不是说只是为了要一个形状和位置,我们还要让他真实或者其他的风格,这个时候就需要着色器来编写颜色方程放在GPU里运行,快速的进行颜色的确定。
投影 Projection:从三维到二维空间的映射
裁剪 Clipping:对于在屏幕空间外的物体,我们并没有必要去计算它的颜色等等信息
屏幕映射 Screen Mapping:屏幕映射阶段的主要目的,是将之前步骤得到的坐标映射到对应的屏幕坐标系上。
光栅化阶段 The Rasterizer Stage(GPU)
给定经过变换和投影之后的顶点,颜色以及纹理坐标(均来自于几何阶段),给每个像素正确配色,以便正确绘制整幅图像。这个过个过程叫光珊化(rasterization)。
三角形设定(Triangle Setup)阶段:计算三角形表面的差异和三角形表面的其他相关数据。
三角形遍历(Triangle Traversal)阶段:到哪些采样点或像素在三角形中的过程通常叫三角形遍历。
像素着色(Pixel Shading)阶段:像素着色阶段的主要目的是计算所有需逐像素计算操作的过程。
融合(Merging)阶段:融合阶段的主要任务是合成当前储存于缓冲器中的由之前的像素着色阶段产生的片段颜色。此外,融合阶段还负责可见性问题(Z缓冲相关)的处理。
四、GPU渲染管线(实际)
前面所讲的渲染管线,并不是真正意义上实际的细分步骤,而是一种概念上的理论,那么实际中GPU是如何进行的呢。
GPU实现了之前所描述的几何和光珊化的所有概念管线。
这些阶段被分割成数个硬件实现的阶段,这些阶段支持不同程度的可配置性或可编程性的。下图中通过不同的颜色展示了其可编程性和可配置性。在这里可能和之前的概念模型略有不同。
绿色为完全可编程,黄色为可配置,蓝色为固定功能
可以说,收到我们关注度最高的,应该是三个绿色的着色器阶段。
1. 可编程着色器(名词解释):
现代的着色器DirectX10及后面出现的)是用来实现图像渲染的,用来替代固定渲染管线的可编辑程序。
着色器使用与C语法相似的着色语言如HLSL,Cg和GLSL等进行编程。这些代码被编译成独立于计算机硬件的汇编语言,亦叫作中间语言。这些汇编语言通常在驱动程序中转换成机器码。这种设计能兼容不同的硬件实现。这种汇编语言可被视为定义了一以着色语言编译器为目标的虚拟机。
这虚拟机是一个带有各种寄存器和数据源的处理器,它使用一套指令进行编程。因为很多的图形操作是使用短整形的向量(长度为4),处理器有四道的SIMD(单指令多数据)能力。每个寄存器包含四个独立的数值。32位单精度浮点标量和向量是基本的数据类型;现在也加入了对32位整形数的支持。浮点数何量通常包含了位置(XYZW),法线,矩阵行,颜色(rgba)和纹理坐标(uvwq)等数据。整形数通常用于计数器,索引或位掩码。集合数据类型例如结构件,数组和矩阵等亦被支持。为了方便向量的使用,拌和技术(swizzling)——向量成员的复现,亦被支持。这是何量的单元可以被任意地重排或重复。相似地,掩蔽技术(masking)即使用所指定的向量单元也是被支持的。
在图形计算中常用的操作都能在当代的GPU上是高效地执行的。例如,最快的操作是标量和向量的乘法、加法和它们的混合,例如乘加和点积。另一些操作,例如倒数,平方根,正弦,余弦,指数和对数,相较而言会消耗更多时间,但仍然是相当快速的。
着色语言通过操作符提供了这些普遍的操作(例如通过操作符*和+提供加法和乘法)。其余则通过内置函数提供,例如atan(),dot()log()及其它。内置函数亦处理更复杂情况,例如向量的单位化和反射,叉积,矩阵转置和行列式等。
着色器程序可在程序被装载前离线编译也可以在运行时编译。像其它任何的编译器一样,这有关于不同输出文件和不同代码优化水平的设置。编译好的着色器被以文字字符串形式保存,通过驱动程序传递到GPU。
2. 着色器的历史
关于可编程着器框架的想法可追溯到1984所Cook的着色树。Render Man着色语言就是建基于这种想法,它产生于80年代末而时至今天仍广泛用于电影场景的渲染。在GPU原生地支持可编程语言之前,已有一些以多渲染路径实现实时可编程着色操作的尝试。1999年的《雷神之锤III:竞技场》的脚本语言是第一个在这方面取得普遍的商业化成功的例子。
在2000年,Peercy等人描述一个将Render Man着色器翻译并运行在图形硬件的多个渲染路径的系统。他们发现GPU缺少两项能使这个方法变得非常普遍的特性:像纹理座标那样使用计算结果(附属纹理贴图读取),以及支持扩展和精度的纹理和颜色缓冲数据类型。所提出的新型数据(在当时)是16位的浮点数。在那个时候,没有任何商业化的GPU支持可编程着色,虽然大部分已经有高度可配置的管线。
在2001年的上半年,NVIDIA的GeForce3是第一颗支持可编程顶点着色器的GPU,可通过DirectX8.0和Open GL扩展去使用。这些着色器使用类似汇编的语言进行编程并由驱动程序转换为机器码。像素着色器也包含在DirectX8.0中,但SM1.1中的像素着色器并未达到真正意义上的可编程性——十分有限的“编程”的支持,即通过驱动程序,与硬件的“寄存器组合器”连接,去转换纹理贴图的混合状态。这些程序不仅在长度上有限制(小于等于12个指令),而且缺少两个Peercy等人指出的两个关于可编程性极为关键的元素(附属纹理读取和浮点数据)。
2002年,DirectX9.0对外公布,其包含着色器模型2.0(并扩展到2.X版本)。这个模型是真正的可编程顶点着色器及像素着色器。相同的功能出现在OpenGL的各种扩展库中。支持任意的附属纹理读取和16位浮点数储存,最终完成了所有Peercy等人在2000年提出的一系列需求。有限的着色器资源例如指令,纹理和寄存器有所增加,使得着色器有能力处理更复杂的效果。增加了流程控制。增长中的着色器代码长度和复杂度使得汇编编程模型变复越来越笨拙和难以处理。幸好,DirectX9.0亦包括了一种新的着色器编程语言,叫HLSL(变级着色语言),HLSL由Microsoft与Nvidia合作研发的,Nvidia亦公开发布了其另一种跨平台的变体,叫Cg。与此同时,OpenGL架构检查委员会(Architecture Review Board)公布与之类似OpenGL版本的语言,叫GLSL(亦被称为GLslang)。这些语言受到了C编程语言的语法和设计理念以及Render Man着色语言的重大影响。
Shader Model 3.0在2004年被引入并逐步改进,将可选的特性转化为模型的需求,更进一步的是增加资源的限值和对纹理读取和顶点着色的有限支持。当新的一代游戏主机在2005年下半年(微软的Xbox360)和2006年(索尼的PS3)被引入时,它们都配置了支持Shader Model 3.0的GPU。固定功能管线并非完全废除:2006年问世的任天堂的Wii游戏主机则使用了固定功能GPU,但几乎可以肯定的是这是最后一款这种类型的主机了,因为甚至移动设备,例如手机亦可使用可编程的着色器了。
2007年,业界又向可编程方向迈出又一大步。着色器模型4.0(包括DirectX10.0和通过扩展的OpenGL)引入了一些主要特征,例如几何着色器和流输出。
着色器模型4.0包括了一个针对所有着色器(顶点、像素和几何)的统一的编程模型,其公共着色器核心在关面已经描述过了。资源上限进一步增加,并加入了对整形数据类型的支持(包括位运算)。值得注意的是着色器模型4.0仅支持高层语言着色器(DirectX的HLSL和OpenGL的GLSL)——没有像之前的版本那样,提供用户可写的汇编语言接口。
3. 顶点着色器
专门处理传入的顶点信息的着色器
输入:VertexBuffer,它由一个或多个顶点属性流组成。
输出:颜色
处理信息:颜色、法线、纹理坐标和位置
处理
1. 矩阵变换,从模型空间转换到齐次裁剪空间。
2.修改/创建/忽略顶点相关属性的功能
4. 几何着色器
高效地创建和销毁几何图元
把(一个或多个)顶点转变为完全不同的基本图形(primitive),从而生成比原来多得多的顶点
输入:以一个或多个表示为一个单独基本图形(primitive)的顶点作为输入,比如可以是一个点或者三角形
输出:点线,三角形
处理
把(一个或多个)顶点转变为完全不同的基本图形(primitive),从而生成比原来多得多的顶点
5. 像素着色器
进行像素的处理,是针对光栅化之后的像素操作
输入:进行插值后的各个像素
输出:颜色
处理信息:颜色
处理:
处理场景光照和与之相关的效果(凸凹纹理映射和调色)
通过纹理坐标取得对应的颜色
令人惊艳的 3D 效果动态光线效果大部分都是 使用片段着色器完成的
版权声明:本文为CSDN博主 - Papals 的原创文章,
遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_23030843/article/details/83033825