VTK 学习----3D基础知识-着色器和图形管道

2.5 着色器和图形管道

2.5.1 图形管道

在三维绘图引擎中,一切物体都在三维空间,但屏幕和窗口是2D像素阵列,因此三维引擎的大部分工作是将所有3D坐标转换为合适屏幕的2D像素。将3D坐标转换为2D像素的过程由图形管道完成。图形管管分为两部分:第一部分将3D坐标转换为2D坐标,第二部分将2D坐标转换为实际的彩色像素。

图形管道将一组3D坐标作为输入,并将这些坐标转换为屏幕上的彩色2D像素。图形管道可以分为几个步骤,其中每个步骤都需要前一步骤的输出作为其输入。所有这些步骤都是高度专业化的(它们具有一个特定的功能),并且可以轻松地并行执行。由于其并行特性,今天的显卡拥有数千个小型处理内核,可以通过在GPU的每个步骤上运行GPU上的小程序来快速处理图形管道中的数据。这些小程序被称为着色器。

其中一些着色器可由开发人员配置,允许我们编写自己的着色器来替换现有的默认着色器。这使我们对管道的特定部分进行了更细粒度的控制,并且因为它们在GPU上运行,它们还可以节省宝贵的CPU时间。

下面是图形管道所有阶段的抽象表示。请注意,蓝色部分表示我们可以注入自己的着色器的部分。

从上图可以看出,图形管道包含大量部分,每个部分处理将顶点数据转换为完全渲染像素的特定部分。

作为图形管道的输入,我们传递一个三个3D坐标的列表,这三个坐标应该在一个数组中形成一个三角形,这里称为Vertex Data;此顶点数据是顶点的集合。一个顶点基本上是每个3D坐标的数据集合。该顶点的数据用表示顶点属性 它可以包含我们想要的任何数据但是为了简单起见,我们假设每个顶点只包含一个3D位置和一些颜色值。

管道的第一部分是顶点着色器将单个顶点作为输入。顶点着色器的主要目的是将3D坐标转换为不同的3D坐标(稍后更多),顶点着色器允许我们对顶点属性进行一些基本处理。

该原始集会stage将顶点着色器中的所有顶点(或顶点,如果选择了GL_POINTS)作为输入,形成一个图元并组合给定图元形状中的所有点;在这种情况下是三角形。

原始汇编阶段的输出传递给几何着色器。几何着色器将形成基元的顶点集合作为输入,并且能够通过发射新顶点来生成其他形状以形成新的(或其他)基元。在此示例中,它生成给定形状的第二个三角形。

然后将几何着色器的输出传递给光栅化阶段它将得到的图元映射到最终屏幕上的相应像素,从而产生片段着色器要使用的片段。片段着色器运行之前,剪裁执行。剪切会丢弃视图外的所有片段,从而提高性能。

片段着色器的主要目的是计算像素的最终颜色。通常,片段着色器包含有关3D场景的数据,可用于计算最终像素颜色(如灯光,阴影,灯光颜色等)。

在确定了所有相应的颜色值之后,最终的对象将通过我们称之为的另一个阶段 阿尔法测试和混纺阶段。这个阶段检查片段的相应深度(和模板)值(我们将在后面得到),并使用它们来检查结果片段是在前面还是在其他对象后面,并且应该相应地丢弃。舞台也会检查α值(alpha值定义对象的不透明度)和共混物相应的对象。因此,即使在片段着色器中计算像素输出颜色,在渲染多个三角形时,最终像素颜色仍然可能完全不同。

从上面的描述可以看出,图形管道是一个非常复杂的整体,包含许多可配置的部分。但是,对于几乎所有情况,我们只需要使用顶点和片段着色器。几何着色器是可选的,通常保留为其默认着色器。

2.5.2 着色器

2.5.2.1 GLSL

OpenGL的着色器是用类似C语言的GLSL编写的。GLSL专为图形使用而定制,包含专门针对矢量和矩阵操作的有用功能。

着色器始终以版本声明开头,后跟输入和输出变量列表,一致性和主要的功能。每个着色器的入口点都在其中主要函数,我们处理任何输入变量并将结果输出到其输出变量中。不要担心,如果你不知道什么是制服,我们很快就会到达那些。

着色器通常具有以下结构:

着色器本身就是很好的小程序,但它们是整体的一部分,因此我们希望在各个着色器上有输入和输出,以便我们可以移动它们。GLSL 专门为此目的定义了in和out关键字。每个着色器都可以使用这些关键字指定输入和输出,以及输出变量与下一个着色器阶段的输入变量匹配的位置。顶点和片段着色器略有不同。顶点着色器应该接收某种形式的输入,否则它将非常无效。顶点着色器的输入不同,因为它直接从顶点数据接收输入。要定义顶点数据的组织方式,我们使用位置元数据指定输入变量,以便我们可以在CPU上配置顶点​​属性。

2.5.2.2 着色器的分类

OpenGL渲染管道定义了以下着色器阶段及其枚举器名称:

  1. 顶点着色器:GL_VERTEX_SHADER
  2. 面细分控制评估着色器:GL_TESS_CONTROL_SHADER和GL_TESS_EVALUATION_SHADER。
  3. 几何着色器:GL_GEOMETRY_SHADER
  4. 片段着色器:GL_FRAGMENT_SHADER
  5. 计算着色器:GL_COMPUTE_SHADER。

下面对顶点着色器和片段着色器这两个重要的着色器做详细说明:
(1)顶点着色器

顶点着色器是可编程的Shader舞台渲染管线。顶点着色器通过绘图命令顶点数组对象指定的顶点属性数据。顶点着色器从顶点流接收单个顶点,并生成到输出顶点流的单个顶点。从输入顶点到输出顶点必须有1:1的映射。

顶点着色器通常对投影后空间执行变换,供顶点后处理阶段使用。它们还可用于执行逐顶点光照,或用于以后着色器阶段的设置工作。

调用频率

OpenGL规范对渲染系统调用顶点着色器的次数相当宽松。顶点规范顶点渲染定义顶点流:要消耗的有序顶点序列。对于流中的每个顶点,顶点着色器将大致执行一次。

顶点着色器(通常)与其输入不变。也就是说,在单个Drawing命令中,两个获得完全相同输入属性的顶点着色器调用将返回二进制相同的结果。因此,如果OpenGL可以检测到顶点着色器调用被赋予与先前调用相同的输入,则允许重用前一次调用的结果,而不是浪费宝贵的时间来执行它已经知道答案的内容。 。

OpenGL实现通常不会通过实际比较输入值(这将花费太长时间)来做到这一点。相反,此优化通常仅在使用索引渲染 功能时发生。如果多次指定特定索引(在同一个Instanced Rendering),则保证此顶点产生完全相同的输入数据。

因此,实现在顶点着色器的结果上使用高速缓存。如果索引/实例对再次出现,并且结果仍在缓存中,则不会再次执行顶点着色器。因此,可以存在比指定顶点更少的顶点着色器调用。

但是,对于我们使用的每个唯一属性集,保证至少有一个顶点着色器调用。

注意:如果曲面细分处于活动状态,则顶点着色器的调用频率完全可能会发生变化。特别是如果曲面细分控制着色器处于活动状态。因此,在细分时,您可能用来保存顶点着色器调用的技巧可能不起作用。然后,他们也可以工作。但是,确保它们不会保存TCS调用,因为TCS无法使用这些优化

(2)片段着色器

片段着色器是着色器处理将一个阶段片段光栅化到一组颜色和单个深度值。

片段着色器是光栅化基元后的OpenGL管道阶段。对于由基元覆盖的像素的每个样本,生成“片段”。每个片段都有一个窗口空间位置,一些其他值,它包含来自最后一个顶点处理阶段的所有插值的每顶点输出值。

片段着色器的输出是深度值,可能的模板值(由片段着色器未修改),以及可能写入当前帧缓冲区中的缓冲区的零个或多个颜色值。

片段着色器将单个片段作为输入并生成单个片段作为输出。

片段着色器在技术上是可选的着色器阶段。如果未使用片段着色器,则输出Fragment的颜色值具有未定义的值。但是,输出片段的深度和模板值与输入具有相同的值。这对于进行渲染非常有用,其中唯一有用的输出是片段的深度,并且您希望使用系统计算的深度,而不是其他深度。这种仅深度渲染用于阴影映射操作以及深度预通过优化。

与其他每个着色器阶段不同,片段着色器生成隐式衍生物。因此,他们可以使用大多数纹理功能。您仍然需要注意不均匀的流量控制

2.5.2.3 Gouraud Shading和Phong Shading

Gouraud着色法是计算机图形学中的一种插值方法,可以为多边形网格表面生成连续明暗变化。实际使用时,通常先计算三角形每个顶点的光照,再通过双线性插值计算三角形区域中其它像素的颜色。

Phong着色法,三维电脑图像的绘图技巧之一,结合了多边形物体表面反射光的亮度,并以特定位置的表面法线作为像素参考值,以插值方式来估计其他位置像素的色值。

相同点:

(1)二者都是明暗处理技术;

(2)都要先应用多边形的法线算出其公共顶点的法线(如下图);

https://images0.cnblogs.com/blog/490586/201302/08082952-eff9c819ef2e48dfa01ee783dae934bb.jpg

(3)都应用Phong局部反射模型计算多边形顶点处的光强(算式如下图)。

https://images0.cnblogs.com/blog/490586/201302/08083235-34d8542b9473457cb5703bae38c80106.jpg

即 反射光 = 环境光 + 漫反射 + 镜面反射

其中环境光是一个常量,就好比将一条直线上移的截距值,基于这个基本光强,再加上漫反射和镜面反射。

漫反射和镜面反射是点光源在该点上的漫反射和镜面反射。

其中环境光是一个常量,就好比将一条直线上移的截距值,基于这个基本光强,再加上漫反射和镜面反射。

漫反射和镜面反射是点光源在该点上的漫反射和镜面反射。

(4)都不考虑物体间的相互作用,即将物体的反射光、折射光(漫反射光实际上是上头提到的环境光,我们将其看成常量处理,比较简单)作为入射光强的一部分来考虑,这样是相对不真实的情况,ray tracing会解决这一问题。

下图为Phong局部反射模型中漫反射和镜面反射的示意图:

不同点:

Gouraud着色法的效果优于平直着色法,所需的处理也比Phong着色法少,但缺点是着色后仍然可以看出一个个小平面的效果。

与Phong着色法相比,Gouraud着色法的长处和短处都在于插值。计算单点光照是相对昂贵的操作,如果网格在屏幕空间所覆盖的像素数量比它本身的顶点数目多,那么计算插值显然要比像Phong着色法一样对每个像素都计算一遍光照要高效。然而,渲染一些与位置相关的光照效果(比如高光)时,得到的效果就会有问题。如果在多边形的中心有高光,而且这个高光没有扩散到该多边形的任何顶点,使用Gouraud着色法就不会渲染出任何效果;而如果正好是多边形的顶点上有高光,那么这个点上的高光是正确的,但插值会导致高光以很不自然的形式扩散到相邻的多边形上。

https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Gouraud_low_anim.gif/180px-Gouraud_low_anim.gif

Gouraud着色的球体,注意高光处的表现

https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/Gouraud_high.gif/180px-Gouraud_high.gif

仍然是同一个球体,但是提高多边形数目后的效果

Gouraud着色法比较,Phong着色法的效果更逼真,能够提供更好的光滑曲面的近似值。Phong着色法假设一个平滑变化的曲面为一矢量。在对于有较小的高光曲线区的反射模型,例如PHONG模型时,Phong着色法比Gouraud着色法更优。但运算程序也比前者为复杂。Gouraud着色法在遇到在较大的多边形模型中央有高光曲线区时会产生严重的问题。因为这些高光曲线区在多边形的顶点处会产生缺失,而Gouraud着色法是基于顶点的颜色的,这些高光曲线区会从多边形的内部缺失。这个问题在Phong着色法中得到了解决。不同于通过多边形差值的Gouraud着色法,Phong着色法中一个矢量是从多边形顶点的法线到多边形表面进行差值的。为了或得到最后的像素颜色,面的法线被差值,应用于一个反射模型。由于Phong着色法需要逐像素点进行计算,因此运算量远大于Gouraud着色法。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dylan55_you

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值