文档章节

图形学理论-渲染流水线

大鲸鱼锅锅
 大鲸鱼锅锅
发布于 2017/04/14 19:44
字数 3056
阅读 13
收藏 0
点赞 0
评论 0

渲染流水线的三个阶段#

  • 应用阶段
    应用阶段是完全由自己编程实现的,是CPU进行工作的部分。在应用阶段,我们要做的有以下几个任务:

    1. 准备场景数据,包括摄像机的位置、视锥体、场景中的模型、使用的光源等;
    2. 为了提高渲染性能而进行的遮挡提出(culling)工作;
    3. 设置渲染状态,渲染状态包括每个模型使用的材质、纹理、shader等等。

    应用阶段最重要的任务就是在最后输出渲染图元,这些渲染图元将传递给几何阶段。在应用阶段的最后,我们会调用DrawCall命令,它指向了一个等待被渲染的图元列表,然后GPU根据渲染状态中设置的材质纹理等等信息,对所有输入的图元进行几何阶段和光栅化阶段的计算。所以在实际的应用中,我们针对DrawCall的优化就是尽可能的复用材质,然后根据材质来排序合并模型顶点,以减少DrawCall调用次数,因为CPU同GPU的通信是非常消耗性能的。

  • 几何阶段
    几何阶段将会执行逐顶点、逐多边形的操作,几何阶段是在GPU上执行的。在几何阶段,我们主要执行以下几个阶段任务:

    1. 顶点着色器阶段

    顶点着色器(Vertex Shader)必须由开发者实现,是完全可编程的,它通常用于实现顶点的着色和空间变换。输入进来的每个顶点都会调用一次顶点着色器,由于GPU有较多的并行运算单元,所以执行速度会非常快,但同时我们无法通过顶点着色器创建或销毁任何顶点,也无法得到任何顶点与顶点间的关系对顶点的着色包括逐顶点光照,逐顶点着色等等,对顶点的空间变化必须包括将顶点从模型空间转换到齐次裁剪空间,后面硬件会做透视除法,得到归一化的设备坐标NDC,以用于以后进行的裁剪操作。对顶点的空间变化也可以通过UV进行一些其他的变化以实现一些特殊的效果,例如动态的水面等等。关于这些图形理论和数学细节可以查阅相关文档,我有空也会进行一些博客的更新。

    1. 曲面细分阶段

    曲面细分着色器(Tessellation Shader)是一个可选择的着色器,主要用于细分图元。具体的讲,就是通过增加三角形来对一个网格的三角形进行细分,使得网格细节更加丰富。我们可以通过使用曲面细分操作来执行LOD(level -of-detail),也可以在低细节的模型上处理动画和物理效果,降低对CPU的性能消耗,而同时在GPU中进行曲面细分,增加细节表现。同时,在内存中维护一个低细节模型,而在GPU中动态的增加模型细节也是个很好的节省内存的方法。

    在Direct3D11之前,曲面细分是在CPU中完成的,这显然是种吃力不讨好的办法。而在Direct3D 11中提供了一个可以完全在硬件上实现的曲面细分API,曲面细分就显得很有价值了。

    1. 几何着色器阶段

    几何着色器(Geometry Shader)也是一个可选择的着色器。这个阶段的输入是完整的图元,也就是说,如果图元的基本单位是三角形,那么输入的就是三角形的三个顶点,这三个顶点是由顶点着色器或曲面细分着色器输入的。几何着色器可以根据某些条件完整的剔除图元,或者是拓展创建新的图元,例如将一个点拓展为一个四边形等。这与顶点着色器阶段不同,顶点着色器是输入一个顶点就输出一个顶点。

    1. 裁剪阶段

    顾名思义,裁剪就是将齐次裁剪空间外的图元舍弃,在齐次裁剪空间内的图元保留,部分在齐次裁剪空间内的图元进行裁剪。这样做的好处是减少GPU要处理图元数量,提升性能。难点在于处理部分在齐次裁剪空间内的图元,这里会在图元和齐次裁剪空间相交的部分生成新的顶点,而原来在外部的顶点被舍弃。这个阶段是不可编程的,但是可以通过给定一个裁剪操作来进行配置。裁剪完成后,会将齐次裁剪空间做透视除法,得到归一化的设备坐标NDC。

    1. 屏幕映射

    屏幕映射阶段(Screen Mapping)的输入是NDC内的坐标,我们的目标是将每个顶点的x,y坐标转换到屏幕坐标系(Screen Coordinates)。根据屏幕分辨率的不同,或者说窗口大小的不同,可能会对图元进行一些拉伸。屏幕映射不会对z坐标做任何处理,同时,屏幕映射后的x,y坐标和z坐标一起构成了窗口坐标系,这些顶点值会传递给光栅化阶段。

    注意一点,direct3d的屏幕坐标系原点在左上角,而opengl的坐标系原点在左下角,d3d中NDC的z值为[0,1]而opengl是[-1,1]。

  • 光栅化阶段
    现在我们得到了屏幕坐标系下,每个顶点的xy坐标以及他们的深度值z,还有诸如顶点的法线方向、视角方向等。在光栅化阶段我们主要要计算每个图元占据哪些像素,以及这些像素的颜色。光栅化流水线有以下阶段:

    1. 三角形设置

    在顶点着色器阶段我们得到的都是一个三角形的顶点信息,即每个三角形每条边的两个端点,我们要光栅化一个三角形网格,就是要得到这个三角形网格对每个像素的覆盖情况,那么我们就必须计算每条边上的像素坐标,为了这个目标,我们就要知道三角形边界的表示方式,这样的一个计算三角形网格表示方式的过程就叫三角形设置(Triangle Setup),它为下个阶段做准备。

    1. 三角形遍历

    三角形遍历(Triangle Traversal)会计算每个三角形网格覆盖的像素,并用顶点对覆盖区域像素进行插值。如果一个像素被一个三角形网格所覆盖,那么就会生成一个片元,这个片元包含了屏幕坐标、深度信息、法线信息、纹理坐标等等,用于计算像素的最终颜色,但片元并不是真正的像素,它与像素最大的区别在于,一个像素可能对应着深度不同的多个片元。

    1. 片元着色器

    片元着色器(Fragment Shader)在direct3d也叫像素着色器(Pixel Shader),可是片元并不是真正的像素,所以这个名字并不准确。在三角形设置和三角形遍历阶段,我们得到了每个片元的数据信息,这些信息包括屏幕坐标、纹理坐标、法线、深度等等,我们通过对片元信息的处理,得到每个片元的最终颜色数据,供后面的阶段使用。

    片元着色器是一个完全可编程的阶段,所以我们可以在这个阶段完成很多的渲染技术,最重要的例如纹理采样。我们的片元是通过对顶点信息进行插值得到的,在顶点着色器阶段,我们输出每个顶点对应的纹理坐标,通过插值,我们得到了每个片元对应的纹理坐标。

    片元着色器虽然可以完成很多重要的效果,但是它每次只能影响单个片元,不能将自身的结果发送给其他的片元。

    1. 逐片元操作

    逐片元操作(Per-Fragment Operations)在direct3d中叫输出合并阶段(Output Merger,OM),这一阶段对片元依次进行模板测试、深度测试、混合后,得到最终的像素颜色。

    模板测试(Stencil Test)是做什么的呢?对于每个像素,给定一个模板参考值,这个参考值可以指定,对每个片元,拥有一个模板值,将每个片元的模板值和其所对应的像素的模板参考值进行比较,比较的函数也可以由开发者指定,符合的通过,不符合的舍弃。当然,最终是否通过,还要取决于深度测试。最后还要根据比较结果,对该模板参考值做指定的修改处理,这个修改处理也可以由开发者指定,例如在模板测试失败的时候,模板缓冲区保持不变,在通过时将模板缓冲区对应的位置的模板参考值加1等。模板测试通常用于限制渲染的区域。也可以做一些更高级的使用,例如渲染阴影、渲染轮廓等等。

    深度测试(Depth Test)也是高度可配置的。深度测试会将每个片元的深度值和深度缓冲区中的深度参考值进行比较,这个比较函数可以由开发者设置。通常情况下,当一个片元的深度值大于深度缓冲区中的值的时候,我们就会舍弃这个片元,因为我们只想显示出离摄像机最近的物体,而被其他物体遮挡的物体就没必要显示在摄像机上面了。和模板测试不同的是,一个片元如果没有通过深度测试,那么他就没有权利修改修改深度模板缓冲区对应的深度参考值,即使一个片元通过了深度测试,他是否能够覆盖深度模板缓冲区的参考值,还取决于是否开启了深度写入。这让我们很方便的制作透明效果。

    对于不透明物体,我们关闭混合(Blend),让它的颜色值直接覆盖颜色缓冲区的像素值,对于透明物体,我们使用混合操作来让这个物体看起来是透明的。混合操作也是高度可配置的,不论是对原像素值进行相加、相减、还是相乘等,通常和透明通道相关。

    在Unity3d中,深度测试被放到了片元着色器之前,这个技术叫做Early-Z技术,不难理解,我们希望在片元着色器中处理更少的片元,而那些早就被抛弃的片元应该在片元着色器处理之前就舍弃掉。但是这也带来了一个问题,可能会与我们在片元着色器中的一些操作冲突,例如如果我们在片元着色器中进行透明度测试,如果一个片元没有通过透明度测试,我们手动调用API将其舍弃了,但是在深度测试的时候,我们已经舍弃了它后面的片元,这就会导致显示出现错误。这种冲突导致我们无法使用Early-Z,所以在现代的GPU中,会判断片元着色器是否进行了一些会导致冲突的操作,如果有这种操作,那么就会禁用Early-Z,这也带来了一定的性能下降。

© 著作权归作者所有

共有 人打赏支持
大鲸鱼锅锅
粉丝 5
博文 13
码字总数 15885
作品 0
武汉
程序员
Activiz 使用笔记-3 数据源(1)

activiz本身自带的user guide 比较简单,所以我按着vtk的user guide来慢慢学。从简单例子入手去学习VTK。当然我之前已经看过很多VTK相关的东西了,但是没有自己去写去总结,导致我一段时间不...

小王爷和老王爷 ⋅ 2015/09/07 ⋅ 0

如何学好游戏3D引擎编程

注:本文是网上看到的一篇文章,感觉写的很好,因此收藏了下来 《如何学好游戏3D引擎编程》 此篇文章献给那些为了游戏编程不怕困难的热血青年,它的神秘要我永远不间断的去挑战自我,超越自我...

loving_forever_ ⋅ 2016/07/28 ⋅ 0

How To Learn Computer Graphic——如何学习计算机图形学

Q:计算机图形学是什么? A:计算机图形学Computer Graphic是一门交叉学科,可以说与娱乐业的兴起有相当大的关联。它的主要目的是在现有计算条件下,根据实际需求进行数字图象的绘制。 Q:我在学...

teacheryang ⋅ 2010/09/04 ⋅ 0

光栅化软件渲染器--SALVIA

SALVIA是一款光栅化的软件渲染器,设计目标是达到Direct3D 10/11的核心功能的实现。我们的设计目的主要包括以下几点: 一个高度可移植的光栅化图形管线的软件实现 图形硬件工作原理的展现和教...

匿名 ⋅ 2010/04/19 ⋅ 0

[Unity Shader] Shader学习笔记1 - 概述1

GPU发展 GPU英文全称Graphic Processing Unit,中文翻译为“图形处理器”。NVIDIA在1999年发布GeForce 256图形处理芯片时首先提出GPU的概念。GPU所采用的核心技术有硬件T&L、立方纹理(Cube m...

NickHomeSelf ⋅ 2016/08/07 ⋅ 0

Android中的OpenGL ES使用基础

一、OpenGL/EGL 因为Android的GUI系统是基于OpenGL/EGL实现的,所以先介绍相关基础知识。 OpenGL(Open Graphics Library)已占据虚拟现实、CAD、能源、游戏研发等多个行业领域,是跨语言,跨平...

liaowenhao ⋅ 2017/11/23 ⋅ 0

基于CoreGraphics的3D渲染方案

前言 今年的首要研究对象OpenGL基本研究的差不多了,突发奇想,想用CoreGraphics根据OpenGL的渲染流水线,渲染出3D图形来。折腾了2天,写出了个demo,效果如下。 其实这种通过2D渲染引擎渲染...

handyTOOL ⋅ 2017/12/22 ⋅ 0

HPC高性能计算知识: GPU的工作原理(含视频)

在GPU出现以前,显卡和CPU的关系有点像“主仆”,简单地说这时的显卡就是画笔,根据各种有CPU发出的指令和数据进行着色、材质的填充、渲染、输出等。 较早的娱乐用的3D显卡又称“3D加速卡”,...

btb5e6nsu1g511eg5xeg ⋅ 04/18 ⋅ 0

计算机图形/图像(GPU/OpenGL)

> OpenGL ES 《OpenGL ES应用开发实践指南 -Android卷》-https://download.csdn.net/download/donkor/9931418 《计算机图形学(openGL版)第三版(中文版)》 矩阵变换:《线性代数》和《3D 数学...

shareus ⋅ 04/25 ⋅ 0

【Visual C++】游戏开发笔记二十四 由DirectX的几个版本说开去

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 http://blog.csdn.net/zhmxy555/article/details/7629288 作者:毛星云 邮箱: happylifemxy@qq.com 期待着与志同道合的朋友们相互交...

长平狐 ⋅ 2012/11/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 56分钟前 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 1

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

CentOS开机启动subversion

建立自启动脚本: vim /etc/init.d/subversion 输入如下内容: #!/bin/bash## subversion startup script for the server## chkconfig: 2345 90 10# description: start the subve......

随风而飘 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部