北京专业网站开发,深圳知名seo公司,c 网站开发案例大全,joomla与wordpress读者可以在开源网站github#xff08;https://github.com/candycat1992/Unity_Shaders_Book#xff09;上下载本书的源代码。 第二章 渲染流水线
渲染流水线的最终目的在于生成或者说是渲染一张二维纹理#xff0c;即我们在电脑屏幕上看到的所有效果#xff0c;它的输入是…读者可以在开源网站githubhttps://github.com/candycat1992/Unity_Shaders_Book上下载本书的源代码。 第二章 渲染流水线
渲染流水线的最终目的在于生成或者说是渲染一张二维纹理即我们在电脑屏幕上看到的所有效果它的输入是一个虚拟摄像机一些光源一些 Shader 以及纹理
Shader 仅仅是渲染流水线的一个环节
一个渲染流程分成3个阶段应用阶段Application Stage、几何阶段Geometry Stage、光栅化阶段Rasterizer Stage。 应用阶段
由应用主导通常由CPU负责
这个阶段主要任务是对渲染数据进行粗颗粒剔除向下阶段输出渲染图元并设置渲染状态主要是设置着色器设置测试开关和参数
视锥体是指场景中摄像机的可见的一个锥体范围。它有上下左右近远共6个面组成。在视锥体内的景物可见反之则不可见。为了提高性能只对其中与视锥体有交集的对象进行绘制
CPU可以做粗粒度剔除culling包括视锥体剔除Frustum Culling和遮挡剔除 Occlusion Culling两种这样可以剔除不可见的物体减少无效数据移交给GPU的数据更精简。CPU做的粗粒度剔除是物体层面的。
漫反射是投射在粗糙表面上的光向各个方向反射的现象。当一束平行的入射光线射到粗糙的表面时表面会把光线向着四面八方反射所以入射线虽然互相平行由于各点的法线方向不一致造成反射光线向不同的方向无规则地反射这种反射称之为“漫反射”或“漫射”这种反射的光称为漫射光。很多物体如植物、墙壁、衣服等其表面粗看起来似乎是平滑但用放大镜仔细观察就会看到其表面是凹凸不平的所以本来是平行的太阳光被这些表面反射后弥漫地射向不同方向。漫反射的每条光线均遵循反射定律。
几何阶段
这一阶段通常在GPU上进行
几何阶段的一个重要任务就是把顶点坐标变换到屏幕空间中再交给光栅器进行处理。通过对输入的渲染图元进行多步处理后这一阶段将会输出屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色等相关信息并传递给下一个阶段。
由顶点着色器处理主要是平移旋转和缩放三种坐标变换通过矩阵运算实现。 在几何阶段执行的Shader叫顶点着色器在光栅化阶段执行的Shader叫片元着色器。
光栅化阶段
这一阶段将会使用上个阶段传递的数据来产生屏幕上的像素并渲染出最终的图像。这一阶段也是在GPU上运行。光栅化的任务主要是决定每个渲染图元中的哪些像素应该被绘制在屏幕上。它需要对上一个阶段得到的逐顶点数据例如纹理坐标、顶点颜色等进行插值然后再进行逐像素处理。
CPU 与 GPU 之间的通信
渲染流水线的起点是CPU即应用阶段。应用阶段大致可分为下面3个阶段
1把数据加载到显存中。2设置渲染状态。3调用Draw Call
把数据加载到显存中
所有渲染所需的数据都需要从硬盘Hard Disk Drive, HDD中加载到系统内存Random Access Memory, RAM中。然后网格和纹理等数据又被加载到显卡上的存储空间——显存Video Random Access Memory, VRAM中
显卡对于显存的访问速度更快而且大多数显卡对于RAM没有直接的访问权利。
开发者还需要通过CPU来设置渲染状态从而“指导”GPU如何进行渲染工作。
设置渲染状态
什么是渲染状态呢一个通俗的解释就是这些状态定义了场景中的网格是怎样被渲染的。 调用 Draw Call
Draw Call就是一个命令它的发起方是CPU接收方是GPU。这个命令仅仅会指向一个需要被渲染的图元primitives列表
当给定了一个Draw Call时GPU就会根据渲染状态例如材质、纹理、着色器等和所有输入的顶点数据来进行计算最终输出成屏幕上显示的那些漂亮的像素
GPU 流水线
GPU渲染的过程就是GPU流水线。
几何阶段顶点着色器必须编程 - 曲面细分着色器可选可编程 - 几何着色器可选可编程 - 裁剪可配置- 屏幕映射不能控制 光栅化阶段三角形设置不能控制 - 三角形遍历不能控制 - 片元着色器可选可编程 - 逐片元操作可配置
顶点着色器Vertex Shader是完全可编程的它通常用于实现顶点的空间变换、顶点着色等功能。曲面细分着色器Tessellation Shader是一个可选的着色器它用于细分图元。几何着色器Geometry Shader同样是一个可选的着色器它可以被用于执行逐图元Per-Primitive的着色操作或者被用于产生更多的图元。下一个流水线阶段是裁剪Clipping这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉并剔除某些三角图元的面片。这个阶段是可配置的。例如我们可以使用自定义的裁剪平面来配置裁剪区域也可以通过指令控制裁剪三角图元的正面还是背面。几何概念阶段的最后一个流水线阶段是屏幕映射Screen Mapping。这一阶段是不可配置和编程的它负责把每个图元的坐标转换到屏幕坐标系中。
光栅化概念阶段中的三角形设置Triangle Setup和三角形遍历Triangle Traversal阶段也都是固定函数Fixed-Function的阶段。接下来的片元着色器Fragment Shader则是完全可编程的它用于实现逐片元Per-Fragment的着色操作。最后逐片元操作Per-Fragment Operations阶段负责执行很多重要的操作例如修改颜色、深度缓冲、进行混合等它不是可编程的但具有很高的可配置性。
顶点着色器
顶点着色器Vertex Shader是流水线的第一个阶段它的输入来自于CPU。顶点着色器的处理单位是顶点也就是说输入进来的每个顶点都会调用一次顶点着色器。顶点着色器本身不可以创建或者销毁任何顶点而且无法得到顶点与顶点之间的关系。
顶点着色器需要完成的工作主要有坐标变换和逐顶点光照 我们可以通过改变顶点位置来模拟水面布料等
一个最基本的顶点着色器必须完成的一个工作是把顶点坐标从模型空间转换到齐次裁剪空间
裁剪
一个图元和摄像机视野的关系有3种完全在视野内、部分在视野内、完全在视野外。
图元——图形元素可以编辑的最小图形单位。图元是图形软件用于操作和组织画面的最基本的素材。 例如一条线段的一个顶点在视野内而另一个顶点不在视野内那么在视野外部的顶点应该使用一个新的顶点来代替这个新的顶点位于这条线段和视野边界的交点处。 无法通过编程来控制裁剪的过程而是硬件上的固定操作
屏幕映射
屏幕映射ScreenMapping的任务是把每个图元的x和y坐标转换到屏幕坐标系Screen Coordinates下。屏幕坐标系是一个二维坐标系它和我们用于显示画面的分辨率有很大关系。
屏幕坐标系和z坐标一起构成了一个坐标系叫做窗口坐标系Window Coordinates 三角形设置
光栅化阶段有两个最重要的目标计算每个图元覆盖了哪些像素以及为这些像素计算它们的颜色。
光栅化的第一个流水线阶段是三角形设置Triangle Setup这个阶段会计算光栅化一个三角网格所需的信息
三角形遍历
三角形遍历Triangle Traversal阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖的话就会生成一个片元fragment。而这样一个找到哪些像素被三角网格覆盖的过程就是三角形遍历这个阶段也被称为扫描变换Scan Conversion。 一个片元并不是真正意义上的像素而是包含了很多状态的集合这些状态用于计算每个像素的最终颜色。这些状态包括了但不限于它的屏幕坐标、深度信息以及其他从几何阶段输出的顶点信息例如法线、纹理坐标等。
片元着色器
。真正会对像素产生影响的阶段是下一个流水线阶段——逐片元操作Per-Fragment Operations。
片元着色器的输入是上一个阶段对顶点信息插值得到的结果 它的局限在于它仅可以影响单个片元
逐片元操作
逐片元操作Per-Fragment Operations是OpenGL中的说法在DirectX中这一阶段被称为输出合并阶段Output-Merger
这一阶段有几个主要任务。
1决定每个片元的可见性。这涉及了很多测试工作例如深度测试、模板测试等。2如果一个片元通过了所有的测试就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并或者说是混合。 模板测试和深度测试的简化流程图
什么是 OpenGL/DirectX
OpenGL和DirectX就是这些图像应用编程接口这些接口用于渲染二维或三维图形。
这些接口架起了上层应用程序和底层GPU的沟通桥梁。一个应用程序向这些接口发送渲染命令而这些接口会依次向显卡驱动Graphics Driver发送渲染命令这些显卡驱动是真正知道如何和GPU通信的角色正是它们把OpenGL或者DirectX的函数调用翻译成了GPU能够听懂的语言同时它们也负责把纹理等数据转换成GPU所支持的格式。一个比喻是显卡驱动就是显卡的操作系统。图2.18显示了这样的关系 什么是HLSL、GLSL、CG
着色语言Shading Language。着色语言是专门用于编写着色器的常见的着色语言有DirectX的HLSLHigh Level Shading Language、OpenGL的GLSLOpenGL Shading Language以及NVIDIA的CGC for Graphic。HLSL、GLSL、CG都是“高级High-Level”语言但这种高级是相对于汇编语言来说的而不是像C#相对于C的高级那样。这些语言会被编译成与机器无关的汇编语言也被称为中间语言Intermediate Language, IL。这些中间语言再交给显卡驱动来翻译成真正的机器语言即GPU可以理解的语言。
什么是Draw Call
Draw Call本身的含义很简单就是CPU调用图像编程接口
Draw Call中造成性能问题的元凶是GPU认为GPU上的状态切换是耗时的其实不是的真正“拖后腿”其实的是CPU。
问题一CPU和GPU是如何实现并行工作的
我们需要让CPU和GPU可以并行工作。而解决方法就是使用一个命令缓冲区Command Buffer。
命令缓冲区中的命令有很多种类而Draw Call是其中一种其他命令还有改变渲染状态等例如改变使用的着色器使用不同的纹理等 问题二为什么Draw Call多了会影响帧率
GPU的渲染能力是很强的渲染200个还是2000个三角网格通常没有什么区别因此渲染速度往往快于CPU提交命令的速度。如果Draw Call的数量太多CPU就会把大量时间花费在提交Draw Call上造成CPU的过载。
问题三如何减少Draw Call
批处理Batching 在游戏开发过程中为了减少Draw Call的开销有两点需要注意。
1避免使用大量很小的网格。当不可避免地需要使用很小的网格结构时考虑是否可以合并它们。2避免使用过多的材质。尽量在不同的网格之间共用同一个材质。
什么是固定管线渲染
固定函数的流水线Fixed-Function Pipeline也简称为固定管线通常是指在较旧的GPU上实现的渲染流水线
所以Shader 是什么
GPU流水线上一些可高度编程的阶段而由着色器编译出来的最终代码是会在GPU上运行的对于固定管线的渲染来说着色器有时等同于一些特定的渲染设置有一些特定类型的着色器如顶点着色器、片元着色器等·依靠着色器我们可以控制流水线中的渲染细节例如用顶点着色器来进行顶点变换以及传递数据用片元着色器来进行逐像素的渲染