渲染流水线

 

一、渲染流水线

  渲染流水线的工作任务在于由一个三维场景出发、生存(或者说渲染)一张二维图像。换句话说,计算机需要从一系列的顶点数据、纹理等信息出发,把这些信息最终转换成一张人眼可以看到的图像。而这个工作通常是由CPU和GPU共同完成。
一个渲染流程分三个阶段:应用阶段(Application Stage)几何阶段(Geometry Stage)光栅化阶段(Rasterizer Stage)
  

  1、应用阶段

  从名字我们可以看出,这个阶段是由我们的应用主导的,因此通常由CPU负责实现。换句话说,我们这些开发者具有这个阶段的绝对控制权。这一阶段中,开发者有3个主要任务:
  首先,我们需要准备好场景数据,例如摄像机的位置、视锥体、场景中包含了哪些模型、使用了那些光源等等;
  其次,为了提高渲染性能,我们往往需要做一个粗粒度剔除工作,以把那些看不见的物剔除出去,这样就不需要再移交给几何阶段进行处理;
  最后,我们需要设置好每个模型的渲染状态,这些渲染状态包括但不限于它使用的材质(漫反射颜色、高光反射颜色)、试用的纹理、使用的shader等。
  这一阶段最重要的输出是渲染所需要的几何信息,即渲染图元(Rendering Primitives)。通俗来讲,渲染图元可以是点、线、三角面等。这些渲染图元将会被传递给下一个阶段——几何阶段。

  2、几何阶段

  几何阶段用于处理所有和我们要绘制的几何相关的事情。例如,决定需要绘制的图元是什么,怎么绘制它们,在哪里绘制它们。这一阶段通常在GPU上进行。
  几何阶段负责和每个渲染图元打交道,进行逐顶点、逐多边形的操作。这个阶段可以进一步分成更小的流水线阶段。几何阶段的一个重要任务就是把顶点变换到屏幕空间中,再交给光栅器进行处理。通过对输入的渲染图元进行多步处理后,这一阶段将会输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色等相关信息,并传递给下一阶段。

  3、光栅化阶段

  这一阶段将会使用上个阶段传递的数据来产生屏幕上的像素,并渲染出最终的图像。这一阶段也是在GPU上运行。光栅化的任务主要是决定每个渲染图元中的哪些像素应该被绘制在屏幕上。它需要对上一个阶段的逐顶点数据(例如纹理坐标、顶点颜色等)进行插值,然后再进行逐像素处理。
 

二、CPU和GPU之间的通信

  渲染流水线的起点是CPU,即应用阶段。应用阶段大致可分为下面3个阶段:
  (1)把数据加载到显存中
  (2)设置渲染状态
  (3)调用DrawCall
  DrawCall是一个命令,它的发起方是CPU,就收方是GPU。这个命令仅仅会指向一个需要被渲染的图元列表,而不会再包含任何材质信息

三、GPU流水线

  当给定一个DrawCall时,GPU就会根据渲染状态(例如材质、纹理、着色器等)和所有输入的顶点数据进行计算,最终输出成屏幕上显示的那些漂亮的像素。而这个计算过程,就是GPU流水线。
  从图中可以看出,GPU的渲染流水线接收顶点数据作为输入。这些顶点数据是由应用阶段加载到显存中,再由DrawCall指定的。这些数据随后被传递给顶点着色器。
  顶点着色器(Vertex Shader)是完全可编程的,它通常用于实现顶点的空间变换、顶点着色等功能。
  曲面细分着色器(Tessellation Shader)是一个可选的着色器,它用于细分图元。
  几何着色器(Geometry Shader)同样是一个可选的着色器,它可以被用于执行逐图元(Per-Primitive)的着色操作,或者被用于产生更多的图元。
  裁剪(Clipping)这一阶段的目的是将那些不在摄像机视野内的顶点裁减掉,并剔除某些三角图元的面片。
  屏幕映射(Screen Mapping)这一阶段是不可配置和编程的,它负责把每个图元的坐标变换到屏幕坐标系中。
  三角形设置(Triangle Setup)三角形遍历(Triangle Traversal)阶段也都是固定函数的阶段,片元着色器(Fragment Shader)则是完全可编程的,它用于实现逐片元的着色操作。最后,逐片元操作(Per-Fragment Operation)阶段负责执行很多重要的操作,例如修改颜色、深度缓冲、进行混合等。
 

四、什么是DrawCall

  DrawCall本身的含义很简单,就是CPU调用图像编程接口,如OpenGL中的glDrawElements命令或者DirectX中的DrawIndexedPrimitive命令,以命令GPU进行渲染的操作。
  一个常见的误区是,DrawCall中造成性能问题的元凶是GPU,认为GPU上的状态切换是耗时的,其实不是的,真正“拖后腿”其实是CPU。
  问题一:CPU和GPU是如何实现并行工作的
  想让CPU和GPU可以并行工作,解决方法是使用一个命令缓冲区(Command Buffer)。
命令缓冲区包含了一个命令队列,由CU向其中添加命令,而由GPU从中读取命令,添加和读取的过程是相互独立的。命令缓冲区使得CPU和GPU可以相互独立工作,当CPU需要渲染一些对象时,它可以向命令缓冲区添加命令,而当GPU完成了上一次的渲染任务后,它就可以从命令队列中再取出一个命令并执行它。
  命令缓冲区的命令有很多种类,而DrawCall是其中一种,其他命令还有改变渲染状态等(例如改变使用的着色器,使用不同的纹理等)。
  问题二:为什么DrawCall多了会影响帧率
  在每次调用DrawCall之前,CPU需要向GPU发送很多内容,包括数据、状态和命令等。这一阶段,CPU需要完成很多工作,例如检查渲染状态等。而一旦CPU完成了这些准备工作,CPU就可以开始本次的渲染。GPU的渲染能力是很强的,渲染200个还是2000个三角网格通常没什么区别,因此渲染速度往往快于CPU提交命令的速度。如果DrawCall数量太多,CPU就会把大量时间花费在提交DrawCall上,造成CPU的过载。
  问题三:如何减少DrawCall
  减少DrawCall一个很显然的优化想法就是把很多小的DrawCall合并成一个大的DrawCall,这就是批处理的思想
  在游戏开发过程中,为了减少DrawCall的开销,有两点需要注意:
  (1)避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时,考虑是否可以合并。
  (2)避免使用过多的材质。尽量在不同的网格之间共用一个材质。
 

五、什么是shader

  我们之所以要花很大篇幅来讲述GPU的渲染流水线,是因为shader所在的阶段就是渲染流水线的一部分,更具体来说,shader就是:
  (1)GPU流水线上一些可以高度编程的阶段,而由着色器编译出来的最终代码是会在GPU上运行的(队于固定管线的渲染来说,着色器有时等同于一些特定的渲染设置);
  (2)有一些特定类型的着色器,如顶点着色器、片元着色器等;
  (3)依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换以及传递数据,用片元着色器来进行逐像素的渲染。
 

Unity Shader入门基础(一)的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第7章 基础纹理

    转自 冯乐乐的 <Unity Shader 入门精要> 纹理最初的目的就是使用一张图片来控制模型的外观.使用纹理映射技术,我们可以把一张图“黏”在模型表面,逐纹素地控制模型的颜色. 在美术 ...

  2. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

  3. Unity Shader入门精要学习笔记 - 第3章 Unity Shader 基础

    来源作者:candycat   http://blog.csdn.net/candycat1992/article/ 概述 总体来说,在Unity中我们需要配合使用材质和Unity Shader才能达 ...

  4. Unity Shader入门精要读书笔记(一)序章

    本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数 ...

  5. Unity Shader入门精要学习笔记 - 第11章 让画面动起来

    转自 冯乐乐的 <Unity Shader入门精要> Unity Shader 中的内置变量 动画效果往往都是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化.Unity ...

  6. Unity Shader入门精要学习笔记 - 第9章 更复杂的光照

    转载自 冯乐乐的<Unity Shader入门精要> Unity 的渲染路径 在Unity里,渲染路径决定了光照是如何应该到Unity Shader 中的.因此,如果要和光源打交道,我们需 ...

  7. Unity Shader入门精要学习笔记 - 第8章 透明效果

    转载自 冯乐乐的 <Unity Shader入门精要> 透明是游戏中经常要使用的一种效果.在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道.当开启透明混合后,当一个物体被渲染 ...

  8. Unity Shader入门精要学习笔记 - 第4章 学习 Shader 所需的数学基础

    摘录自 冯乐乐的<Unity Shader入门精要> 笛卡尔坐标系 1)二维笛卡尔坐标系 在游戏制作中,我们使用的数学绝大部分都是计算位置.距离.角度等变量.而这些计算大部分都是在笛卡尔坐 ...

  9. Unity Shader入门

    Unity Shader入门 http://www.cnblogs.com/lixiang-share/p/5025662.html http://www.manew.com/blog-30559-1 ...

随机推荐

  1. mysql自动化安装

    MySQL安装一般使用RPM或者源码安装的方式.RPM安装的优点是快速,方便.缺点是不能自定义安装目录.如果需要调整数据文件和日志文件的存放位置,还需要进行一些手动调整.源码安装的优点是可以自定义安装 ...

  2. Javascript - 栈 和 单链表

    最近在重温数据结构,于是写了一些代码玩玩,都是很初级的,表喷各位.... function Stack() { this.dataStore = []; this.top = 0; } Stack.p ...

  3. Android开发之Canvas rotate方法释疑

    Canvas的rotate()函数本应该是很简单的一个函数,但是由于api手册言之不详,使用中难免有吃不准的地方.下面所记录的几点,都是我在使用中所迷惑过的问题,特此记录. 1,坐标原点在哪里? 如果 ...

  4. U3D包大小优化之microlib

    当迩想把最小类库发上来,迩需要把Stripping Level设置为Use micro mscorlib 这里是MICROLIB所能使用的包的类库列表:http://docs.unity3d.com/ ...

  5. Unity Remote 4安卓机使用指南

    必须U3D版本为4.5以上,可以在Public目录下载.想实时调试IOS版本必须是MAC系统! 优点:可以在不编译的情况下实时的去调试真实Android设备的各种情况,包括使用触摸功能(Remote接 ...

  6. C# 开发者代码审查清单【转】

    这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考.这是为了确保在编码过程中,大部分通用编码指导原则都能注意到.对于新手和缺乏经验(0到3年工作经验)的开发者,参考这份清单编码会很帮助 ...

  7. free命令查看内存使用情况(转载)

    linux free命令查看内存使用情况 时间:2016-01-05 06:47:22来源:网络 导读:linux free命令查看内存使用情况,free命令输出结果的各选项的含义,以及free结果中 ...

  8. 字体文件放入CDN服务器中,跨域问题(IIS版)

    Font from origin 'http:/XXXX' has been blocked from loading by Cross-Origin Resource Sharing policy: ...

  9. GET方法传递中文参数乱码解决办法

    1.在页面中对你的URL进行编码 使用------encodeURI(你要使用的中文参数值)如:...?username"+encodeURI(“小甜甜") 2.在后台通过解码来接 ...

  10. java中如何将JScrollPane的垂直滚动条自动移动到最下端

    JPanel QQP = new JPanel(); JScrollPane jsp = new JScrollPane(QQP); JScrollBar jsb = jsp.getVerticalS ...