渲染流水线

 

一、渲染流水线

  渲染流水线的工作任务在于由一个三维场景出发、生存(或者说渲染)一张二维图像。换句话说,计算机需要从一系列的顶点数据、纹理等信息出发,把这些信息最终转换成一张人眼可以看到的图像。而这个工作通常是由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. 山寨版Quartz.Net任务统一调度框架

    TaskScheduler 在日常工作中,大家都会经常遇到Win服务,在我工作的这些年中一直在使用Quartz.Net这个任务统一调度框架,也非常好用,配置简单,但是如果多个项目组的多个服务部署到一台 ...

  2. Android 中ViewPagerIndicator的使用

    1.https://github.com/JakeWharton/Android-ViewPagerIndicator 2.http://blog.csdn.net/xiaanming/article ...

  3. ARM Linux启动代码分析

    前言 在学习.分析之前首先要弄明白一个问题:为什么要分析启动代码? 因为启动代码绝大部分都是用汇编语言写的,对于没学过或者不熟悉汇编语言的同学确实有一定难度,但是如果你想真正深入地学习Linux,那么 ...

  4. javap生成的字节码

    https://www.zhihu.com/question/49470442/answer/135812845http://blog.csdn.net/tzs_1041218129

  5. C8051 PCA实现红外遥控接收

    这里使用的处理器是C8051F005.红外接收头接处理器引脚,中断方式接收按键数据. 一 PCA介绍 1.1 PCA 可编程计数器阵列(PCA)提供增强的定时器功能,与标准8051计数器/定时器相比, ...

  6. 看上去很美 国内CDN现状与美国对比

    CDN的理想与现实 多年以前,当<Kingdom of Heaven>这部史诗电影发行的时候,中国的影迷使用电驴和BT来寻找种子,而那个时候,高清也才刚刚进入电影领域,我的同事不惜用自家的 ...

  7. 彻底理解JAVA动态代理

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 代理模式的结构如下图所示. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public ...

  8. cakePHP的controller回调

    1. afterFilter(), executed after all controller logic, including the rendering of the view2. beforeF ...

  9. VisualSFM for Structure from Motion

    VisualSFM是Changchang Wu编写的使用 Structure from Motion (SfM)进行3D重建的交互界面,具体内容详见http://homes.cs.washington ...

  10. windbg入门

    1.下载安装windbg Windows 10 调试工具 (WinDbg) 如果你仅需要 Windows 10 调试工具,而不需要 WDK 10 或 Visual Studio 2015,你可以将调试 ...