ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

渲染流水线(笔记)

2021-01-16 17:02:17  阅读:229  来源: 互联网

标签:渲染 投影 笔记 列表 坐标 顶点 流水线 三角形 着色器


《DirectX 12 3D游戏开发实战》
第一阶段:
输入装配阶段:
会从显存中读取几何数据(顶点和索引,vertex and index),在将他们装配为几何图元(三角形和线条这种构成图形的基本元素);
1)顶点
2)图元拓扑
在Direct3D中,通过一种名为顶点缓冲区的特殊数据结构,将顶点与渲染流水线绑定。顶点缓冲区利用连续的内存来存储一系列顶点。但是仅仅凭这一点并不能说明这些顶点究竟是怎么组成的几何图元。
通过指定图元拓扑来告知Direct3D如何组成利用顶点数据来表示几何图元。(在用户通过命令列表修改图元拓扑之前,所有绘制调用都会沿用当前设置的图元拓扑方式)。
3)点列表:
当使用点列表拓扑时,所有的顶点都将在绘制调用的过程中被绘制成一个单独的点;
4)线条带
当使用线条带拓扑时,顶点将在绘制调用过程中被连接为一系类的连续线段。所以,在这种拓扑模式下,如果有n+1个顶点就会生成n条线段;
5)线列表
当使用线列表的使坏,每对顶点在绘制调用的过程中都会组成单独的线段;所以2n个点就会生成n条线段。线列表与线条带的区别是:线列表中的线段可以彼此分开,而线条带中的线段则是相连的。如果线段相连的话,绘制同样数量的线段便会占用更少的顶点,因为每个处于线条带中间位置的顶点都可以同时被两条线段所公用;
6)三角形带
当使用三角形拓扑时,所绘制的三角形图像将被连接成带状。在这种三角形连接的结构中,处于中间位置的顶点将被相邻的三角形所共同使用;利用n个顶点将生成n-2个三角形;
重点:在DirectX中置换的是后两个顶点的书序,在OpenGL中置换的才是前两个顶点的顺序。为了保证三角面的正反向(剔除的时候),需要把连续组成的三角形顶点进行绕序,保证他们的三角形都是同一个方向!(GPU会在对这些顶点顺序进行调换)
7)三角形列表
当使用三角形列表来进行拓扑时,在绘制调用的过程中会将每3个顶点独立装配成三角形。所以每3n个顶点会被装配成n个三角形;
三角形列表和三角形带的区别是:三角形列表中的三角形可以彼此分离,而三角形带中的三角形是相连的。
8)具有邻接数据的图元拓扑
对于存有邻接数据的三角形列表而言,每个三角形都有3个与之相邻的邻接三角形;在几何着色器中,往往需要访问这些邻接三角形来实现特定的几何着色算法。为了几何着色器可以顺利的获得这些邻接三角形的信息,就需要借助顶点缓冲区与索引索引缓冲区将他们随着主三角形一并提交至渲染流水线中;只有这样,渲染流水线才能得知如何以顶点缓冲区中的顶点来构建主三角形及其邻接三角形。
注意:邻接图元的顶点只能用作几何着色器的输入数据,却不会被绘制出来。即便程序没有用到几何着色器,但依旧不会绘制邻接图元;
9)控制点面片列表
将顶点数据解释为具有N个控制点的面片列表。此图元常用在渲染流水线的曲面细分阶段(此环节为可选阶段)。以后再说。
10)索引
三角形是3D实体对象的基本组成部分。(三角形由三个顶点构成)
为三角形指定顶点顺序是一个非常重要的工作,这个顺序成为绕序。
构成3D物体的不同三角形,会有很多顶点是共用的。如果共用两个顶点而去复制两个顶点的数据的情况还不太糟糕,但是如果例如八边形那种,每个三角形不仅都复制了一分中心数据顶点,而且八边形每个边上的顶点都被两个三角形公用,一般来说:随着模型的细节和复杂度增加,复制顶点的数量会急剧上升!
不希望复制顶点数据的两个原因:
1、增加内存的需求——为什么要多次存储同一个顶点数据呢?
2、增加图形硬件的处理负荷——为什么要多次处理同一个顶点数据呢?
借助三角形带可以在某些情况下改变顶点的复制问题,提前是这些几何体能够被组织为带状结构。但是,由于三角形列表更为灵活(三角形列表都是独立的三角形,无需连接),所以值得花心思研究这个玩意。
三角形列表移除重复顶点的设计方案:
采用的方法是使用索引。整个工作流程如下:先创建一个顶点列表和一个索引列表;在顶点列表中收录一份所有独立的顶点,并在索引列表中存储顶点列表的索引,这些索引定义了顶点列表中的顶点是如何组合在一起的,从而构建三角形的。
待处理玩顶点列表中那些独立顶点之后,显卡就能通过索引列表吧顶点组合成一系列三角形。可以看到:已经将"复用的顶点数据"转换为索引列表,但是这样的做的效果要比之前的方法更好。这是因为:
1、索引都是简单的整数,不会像使用整个顶点结构那样占用更多的内存(而且随着顶点结构体中的分量不断的增加,将会使内存的需求变得更加急迫)。
2、若辅以是定的顶点缓存排序,则图形硬件将不必再次处理重复使用的顶点,从缓存中直接取得即可(这种情况十分普遍);
每个图像适配器都具有特定大小的缓存,刚处理过的顶点可以被临时存储在缓存当中,由于缓存的读取速度比较顶点缓冲区快,因此可以利用这一点来提升软件的性能。不同硬件的缓存大小有区别。因此应当安排好顶点顺序,首先引用需要复用的顶点,在这些顶点仍位于缓存之中时尽快引用;

第二阶段: 顶点着色器阶段
待图元被装配完毕以后,其顶点就会被送入顶点着色器阶段(vertex Shader stage)。可以把顶点着色器看做一种输入与输出数据都是单个顶点的函数;每个要被绘制的顶点都经过顶点着色器的处理在送完后续阶段。
顶点着色函数就是用户自己需要实现的部分,因为这一阶段中对顶点的操作实际上是由GPU执行的,所以速度非常快;
可以利用顶点着色器实现很多特效:变换、光照、和位移贴图(置换贴图,位移映射)。类似的还有在之后学的:纹理贴图,法线贴图等。
重点:在顶点着色器中,不但可以访问输入的顶点数据,也能够访问纹理和其他存储在显存中的数据(如变换矩阵和场景的光照信息!);
1)局部空间和世界空间
2)摄像机空间(观察空间)
3)投影和齐次裁剪空间(规范化设备坐标NDC,矩阵表示投影公式(齐次除法),归一化深度值)
在3D模型各自的局部坐标系中定义他们有若干的优点:
1、易于使用。例如物体的中心通常位于局部空间的原点,并且和主轴对称。当采用一个以立方体为中心的原点,并且坐标轴正交于个立方体面的局部坐标系,我们就能轻易而举的确定出立方体的各个顶点。
2、物体可以跨越多个场景重复使用。所以将物体坐标相对于某个特定场景进行硬编码并不是明智之举。更爱好的办法则是保存物体低昂对于局部坐标系的顶点坐标,在通过坐标变换矩阵去定义每个场景中局部坐标系之间的关系。
3、最后一点。有事可能需要在场景中多次绘制同一个物体,但是他们的位置、方向、大小却各不相同。(例如森林中的树木)如果在每次创建实例都要复制他的顶点和索引数据,将及其耗费资源。因此通常的做法是存储一份几何体相对于其局部空间的副本(即该几何体的顶点列表和索引列表)。接着,按所需次数来绘制此物体,每次辅以不同的世界矩阵来制定物体在世界空间的位置、方向和大小。这种方法称为实例化。

观察空间:
为了构建场景中的2D图像,我们必须在场景中假设一个虚拟摄像机。该摄像机确定了观察者可见的视野,也就是生成2D图像所需的场景空间范围。对此,首先要给摄像机一个局部坐标系——观察空间。在这个坐标系中,摄像机位于坐标系的原点并沿着z轴正方向观察,x轴指向摄像机的右侧,y轴指向摄像机的上方。与相对与世界空间来描述场景中的物体顶点不同,观察空间用于在渲染流水线的后续阶段中描述这些顶点相对于摄像机坐标系的坐标。由于世界空间到观察空间的坐标变换成为取景变换。这个矩阵:观察矩阵。
投影和齐次裁剪空间:
除了上面说的摄像机在世界空间的位置和朝向,他还有一个关键的组成要素。即摄像机可观察到的空间体积;此范围可用一个由四棱锥截取的平截头体,即四棱台表示。
结果:将平截头体内的3D结合体投影到一个2D投影窗口之内。根据上面的透视投影的远离克制,投影必将沿着众平行线汇聚于小时,也将逐渐变小,而且随着3D物体的深度增加,其投影尺寸也将逐渐变小。将由顶点到观察点的连线成为顶点的投影线;因此就可以定义:将3D顶点v变换到他投影线与2D投影屏幕的交点v的透视投影变换。

定义平截头体:
在观察空间中,可以通过近平面、远平面、垂直视场角,以及纵横比这四个参数,定义一个以原点作为投影的中心:并沿着z轴正方向进行观察的平截头体。
投影窗口实际上就是观察空间的中的2D图像。由于该图像终究被映射到后台缓冲区中,因此我们希望令投影窗口与后台缓冲区的两者纵横比保持一致;如果投影窗口与后台缓冲区的纵横比不一致,那么映射的过程中,就需要对投影窗口在将投影匡舟进行不等比缩放(非均匀缩放,非一致性缩放或者非同一缩放),继而导致图像出现拉伸变形的现象。
投影窗口的实际大小并不重要,关键在于纵横比。

规格化设备坐标:
如何在观察空间计算各个点的投影坐标。在计算过程中,要保证观察空间的投影窗口高为2,宽为2r,这个r就是纵横比。但是如果投影窗口的尺寸依赖于纵横比就是缠身给一个问题:由于硬件会涉及一些与投影窗口大小有关的操作(诸如将投影窗口映射到后台缓冲区等),这意味着我们还需要将纵横比告知硬件。因此,如果能取出投影窗口对纵横比的依赖,那么处理过程会更加简单。对这个:解决办法就是将x坐标上的投影区间从[-r,r]缩放到归一化区间[-1,1]。
注意:在NDC坐标中,投影窗口的高和宽都是2,所以他的大小都是固定的。硬件也就无需知道纵横比。但是,一定要确保将投影坐标映射到NDC空间内(图形硬件假设用户会完成这项工作);

用矩阵来表示投影公式:
为了保证变换的一致性,用矩阵来表示投影变换。由于非线性特征,所以并不存在与之对应的矩阵表示。要点在于要将分为两部分:1、分为线性;2、分为非线性;非线性部分要进行除以z的计算过程,还对z坐标进行归一化处理。这就意味着在执行非线性部分除以z的计算是,却没有最初的z坐标可用。也就是说,一定要在这个变换之前保存之前传入的初始z坐标。为了做到这一点,需要利用齐次坐标将输入的z坐标复制到输出的w坐标。除以w的计算过程有时被称为透视除法或者齐次除法。

归一化深度值:
等到投影操作完毕后,所以的投影点都在2D投影窗口上,从而构建视觉上可见的2D图像。看起来似乎在此时就可以丢弃原始的3D坐标了。然后为了实现深度缓冲算法,我们仍需要保留这些3D深度信息。就想Direct3D希望将x,y坐标映射到归一化范围一样,深度坐标也要被映射到归一化区间以内。因此,必须构建一个保序函数;用来把z坐标映射到[0,1]。因为具有保序性,所以即使对深度值进行归一化以后,深度关系依旧保持不变;所以依旧能够保证深度关系。

第三阶段 曲面细分阶段:
曲面细分阶段是利用镶嵌化处理技术对网格中的三角形进行细分来一次增加物体表面的三角形数量。再将这些三角形便宜到适当的位置,是网格表现出更加细腻的细节;
使用曲面细分的优点:
1、借此来实现一种细节层次(level-of-detail lod)机制,使距离虚拟相机比较近的三角形经过镶嵌化处理得到更加丰富的细节,而对距摄像机较远的三角形不进行任何更改。通过这种方式,即可只针对用户关注度高的部分网格增加三角形,从而提升其细节效果。
2、我们在内存中仅维护简单的低模,低精度模型网格(低模网格是指三角形数量较少的网格,已逐渐形成一门独特画风艺术制作手段),在根据需求为他动态的添加额外的三角形,以此节省内存资源。
3、可以处理动画和物理模拟之时采用简单的低模网格,而金在渲染的过程使用经过镶嵌化处理的高模(high-poly)网格。
曲面细分是在Direct3D 11中引入的处理阶段。他们提供了一种利用GPU即可对几何体进行镶嵌化处理的手段。在Direct3D 11之前只能在CPU上实现这项处理任务。如此一来大大提高了曲线细分技术的魅力,曲面细分是一个可选的渲染阶段。

第四阶段 几何着色器阶段
几何着色器阶段是一个可选渲染阶段。几何着色器接受的输入应该是完整的图元。例如,假设正在绘制三角形列表,那么像几何着色器传入的将使定义三角的三个顶点。(注意:这3个顶点在之前阶段已经经过了顶点着色阶段的处理)几何着色器的主要优点是可以创建或者销毁几何体。比如说,可以利用几何着色器将输入的图元拓展为一个或者多个其他图元,亦或根据某些条件选择不输出任何图元。顶点着色器与之相比,则不能创建顶点:他只能接受输入的单个顶点,经过处理后在将顶点输出。几何着色器常见的拿手好戏是将一个点或者一条线扩展为一个四边形;
几何着色器能够为后续的绘制操作,而将顶点数据流输出至显存中的某个缓冲区之内。

第五阶段 裁剪
完全位于视椎体之外的几何体需要被丢弃,而处于平截体交接以外的集合体部分也一定要接受被裁剪的操作。因此只有在平截体之内的物体对象才会被保留下来。
可以把平截体看做有六个面组成的空间范围,为了裁剪一个和平截体相交的多边形,需要对两者相交的每个平面都注意进行裁剪操作。当对某个存在相交的平面进行裁剪处理,应保留躲避敖兴位于正半空间内的部分,并舍弃其负半空间的部分。在对屏幕相交的凸多边形进行裁剪后,最终得到也一定是一个凸多边形。由于裁剪操作是由硬件来负责的。所以就不研究他的具体细节。
第六阶段 光栅化阶段
光栅化阶段主要任务是投影至屏幕上的3D三角形计算对应的像素颜色。

视口变换:
当裁剪操作完成之后,硬件会通过透视除法将物体从齐次裁剪空间变换为规格化设备坐标(NDC)。一旦物体的顶点位于NDC空间内,构成2D图像的2D顶点xy坐标就会被变换到后台缓冲区中成为视口的矩形里。变换完成以后,这些x,y坐标都将以像素为单位进行表示。通常来说,由于z坐标经常在深度缓冲技术中用作深度值。因此视口变换是不会影响深度值z的。
背面剔除:
如果看到的三角形的正面,就成为这个三角行是正面朝向的。(背面朝向的)。
就目前遇到的所有情况而言,大多数位于3D世界空间中的物体皆为实体对象。(具有边界、表面和体积的对象,除此之外还有线框对象等)。假设按照上述约定,令构建每个物体所用的都是法线指向外侧的三角形,那么摄像机将看不到实体对象中背面朝向的三角形,这是因为正面朝向的三角形会把背面朝向的三角形遮挡起来。由于背面朝向的三角形都被正面朝向的三角形所遮挡,所以绘制他们是没有意义的。背面剔除就是用于将背面朝向的三角形从渲染流水线冲除去的处理流程。这种操作能将待处理的三角形总量小贱一般。
顶点属性插值:
要通过指定顶点来定义三角形。除了位置信息除外,我们还能给顶点附加颜色、法向量和纹理坐标等其他属性。经过视口变换以后,需要为求取三角形内逐像素所附的属性而进行差值运算。而且除了上述顶点属性之外,还需要对顶点的深度值进行插值,继而得到每个像素参与实现深度缓冲算法的深度值。为了得到屏幕空间(即将3D场景渲染为最终图像的2D空间)中各个顶点的额插值属性,往往要通过一种名为透视校正插值的方法。对3D空间中的三角形的属性进行线性插值,从本质上来说,插值法即利用三角形顶点的属性值计算出其内部像素的属性值。
这个阶段是硬件计算的。

第七阶段 像素着色器阶段
编写的像素着色器,是一种由GPU来执行的程序。他会针对每一个像素片段进行处理。(每处理一个像素就要执行一次像素着色器)并根据顶点的色差值属性作为输入来计算出对应的像素颜色。像素着色器可以直接返回一种单一的恒定颜色,也可以实现如逐像素光照、反射以及阴影等更加复杂的效果。

第八阶段 输出合并阶段
通过片元着色器生成的像素片段会被移动到渲染流水线的输出合并阶段。在这个阶段中,一些像素片段可能会被丢弃(例如:那些没有通过深度缓冲区测试或模板缓冲区测试的像素片段),剩下的片元将会被写入后台缓冲区中。混合操作也是在这个阶段,这个技术可以让当前处理的像素和后台缓冲区中的对应的像素进行融合,而不仅是简单的覆盖。例如一些透明这样的效果也是通过混合技术实现的额。

标签:渲染,投影,笔记,列表,坐标,顶点,流水线,三角形,着色器
来源: https://blog.csdn.net/a727674650/article/details/112715441

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有