专栏首页Unity Technology【技术创作101训练营】unity中的shader概述

抱歉,你查看的文章已删除

原创

【技术创作101训练营】unity中的shader概述

1

开场白:

大家好,其实我们在第一次做游戏的时候,应该大概率会听到两个大佬在谈论shader,虽然都是做游戏的把,但是只要你对shader有见解,能说出不一样的东西,别人立马对你刮目相看,说点实在的,就是你会说几句shader的见解,你就是在面试中,你也有底气多要几百块,会不会shader,已然成了你是不是中高级unity工程师的参考标准.今天我来和大家聊一聊shader.

2

Gpu的前世

那么首先我们来了解一下,显卡是怎么产生的,再到后来是怎么有一种专门面对GPU编程的,像有的程序员,java ,C#等等,它们都是面对着CPU编程,那么GPU怎么会走入大众的视野呢?

其实在图形卡发明以前,所有的屏幕上渲染都是交给CPU来完成的,但是由于GPU的局限性,并不能发挥很好的渲染效果,所以,GPU诞生了.

1962年MIT的一个博士的画板程序奠定了图形学的基础。但是在随后的20年例,计算机图形学一直在不断发展,不过没有专门的图形处理芯片。

1984年SGI推出了专业的高端图形工作站,有了专门的图形硬件,叫做图形加速器。引入了许多经典的概念,如顶点变换和纹理映射。随后的10多年里,SGI又研发了很多图形工作站,但都是面向专业领域,价格昂贵,没法进入消费级市场。不过消费级市场还是出现了一些2D加速卡。

1995年3dfx公司发布了全球第一款消费级3D图形加速卡voodoo。开山鼻祖。随后几年,NVIDIA和ATI分别分别发布了自己的TNT和Rage系列,从硬件上实现了Z缓存和双缓存,还可以进行光栅化,CPU从繁复的像素填充任务中解脱了。但是顶点变换还是由CPU负责,光栅化也是能力很有限。

3

Gpu的今生

1999年,NVIDIA发布了Geforce 256, 第一款提出GPU概念,开天辟地的产品。Geforce 256的核心技术有T&L硬件(硬件级的几何与光照转换引擎),纹理压缩,凹凸映射,双重纹理等等。同时期的OpenGL和DirectX7也提供了硬件顶点变化的编程接口。

2001年微软发布DirectX8, 包含了Shader Model1.0标准。遵循该标准的GPU可以支持顶点和像素编程。不过当时N和A两家的产品都不支持像素编程。

2003年微软发布DirectX9.0b,Shader Model更新到2.0, shader成为其标准配置。NVIDIA和ATI的产品都具备了可编程顶点着色器和可编程像素着色器。

2006年微软发布DirectX10,迎来了Shader Model4.0。核心就是着色器采用了统一渲染架构。

2009年微软发布DirectX11,包含了Shader Model5.0。可编程方面支持的更多了,比如计算,Hull和Domain。

2014年微软发布了DirectX12, 目前Windows10有了,但是不能用。充分发挥多核CPU的性能,CPU和GPU的交互效率提升。Shader Model6.0

其实发展到这里,我们的gpu就非常的强大了

4

GPU的优越性

由于GPU具有高并行结构,所以GPU在处理图形数据和复杂算法方面拥有比CPU更高的效率。CPU大部分面积为控制器和寄存器,与之相比,GPU拥有更多的ALU(Arithmetic Logic Unit,逻辑运算单元)用于数据处理,这样的结构适合对密集型数据进行并行处理。GPU采用流式并行计算模式,可对每个数据进行独立的并行结算,所谓“对数据进行独立计算”,即,流内任意元素的计算不依赖于其它同类型数据.

5

GPU的缺陷

由于“任意一个元素的计算不依赖于其它同类型数据”,导致“需要知道数据之间相关性”的算法,在GPU上难以得到实现,一个典型的例子是射线与物体的求交运算。GPU中的控制器少于CPU,致使控制能力有限。

6

shader的语言:

Shader Language目前主要有3种语言:

基于 OpenGL 的 OpenGL Shading Language,简称 GLSL;

基于 DirectX 的 High Level Shading Language, 简称 HLSL;

还有 NVIDIA 公司的 C for Graphic,简称 Cg 语言。

7

opengl是什么?

OpenGL(全写Open Graphics Library)是一个定义了跨编程语言、跨平台的编程接口规格的专业图形程序接口。它用于三维图像(二维亦可),是一个功能强大,调用方便的底层图形库。OpenGL是行业领域中最为广泛接纳的2D/3D图形API,其自诞生至今已催生了各种计算机平台及设备上的数千优秀应用程序。它独立于视窗操作系统或其他操作系统的,亦是网络透明的。在包含CAD、内容创作、能源、娱乐、游戏开发、制造业及虚拟现实等行业领域中。OpenGL是一个与硬件无关的软件接口,可以在不同的平台如Windows 95、Windows NT、Unix、Linux、MacOS、OS/2之间进行移植。因此,支持OpenGL的软件具有很好的移植性,可以获得非常广泛的应用。

  OpenGL的发展一直处于一种较为迟缓的态势,每次版本的提高新增的技术很少,大多只是对其中部分作出修改和完善。1992年7月,SGI公司发布了OpenGL的1.0版本,随后又与微软公司共同开发了Windows NT版本的OpenGL,从而使一些原来必须在高档图形工作站上运行的大型3D图形处理软件也可以在微机上运用。1995年OpenGL的1.1版本面世,该版本比1.0的性能有许多提高,并加入了一些新的功能,其中包括改进打印机支持,在增强元文件中包含OpenGL的调用,顶点数组的新特性,提高顶点位置、法线、颜色、色彩指数、纹理坐标、多边形边缘标识的传输速度,引入了新的纹理特性等等。OpenGL 1.5又新增了“OpenGL Shading Language”,该语言是“OpenGL 2.0”的底核,用于着色对象、顶点着色以及片段着色技术的扩展功能。

8

dx是什么?

DirectX(Direct eXtension,简称DX)是由微软公司创建的多媒体编程接口。由C++编程语言实现,遵循COM。被广泛适用于Microsoft Windows、Microsoft XBOX、Microsoft XBOX 360和Microsoft XBOX ONE电子游戏开发,并且只能支持这些平台。最新版本为DirextX 12,创建在最新的Windows 10。DirectX是这样一组技术:它们旨在使基于Windows的计算机成为运行和显示具有丰富多媒体元素(例如全色图形、视频、3D动画和丰富音频)的应用程序的理想平台。DirectX包括安全和性能更新程序,以及许多涵盖所有技术的新功能。应用程序可以通过使用DirectX API来访问这些新功能。

  DirectX加强3D图形个声音效果,并提供设计人员一个共同的硬件驱动标准,让游戏开发者不必为每一品牌的硬件来写不同的驱动程序,也降低了用户安装及设置硬件的复杂度。从字面意义上说,Direct就是直接的意思,而后边的X则代表了很多意思,从这一点上可以看出DirectX的出现就是为了众多软件提供直接服务的。

  举例来说,以前在DOS下玩家玩游戏时,并不是安装上就可以玩了,他们往往首先要设置声卡的品牌和型号,然后还要设置IRQ(中断)、I/O(输入和输出)、DMA(存取模式),如果哪项设置不对,那么游戏声音就发不出来。这部分的设置不仅让玩家伤透脑筋,对游戏开发者来说就更为头痛,为了让游戏能够正确运行,开发者必须在游戏制作之初,把市面上所有声卡硬件数据都收集过来,然后根据不同的API(应用编程接口)来写不同的驱动程序。这对于游戏制作公司来说,是很难完成的,所以在当时多媒体游戏很少。微软正是看到了这个问题,为众厂家推出了一个共同的应用程序接口——DirectX。只要游戏是依照DirectX来开发的,不管显卡、声卡型号如何,统统都能玩,而且还能发挥最佳的效果。当然,前提是使用的显卡、声卡的驱动程序必须支持DirectX才行。

9

cg是什么?

GLSL与HLSL分别基于OpenGL和Direct3D的接口,两者不能混用,事实上OpenGL和Direct3D一直都是冤家对头,争斗良久。OpenGL在其长期发展中积累下的用户群庞大,这些用户会选择GLSL学习。GLSL继承了OpenGL的良好移植性,一度在Unix等操作系统上独领风骚。但GLSL的语法体系自成一家。微软的HLSL移植性较差,在Windows平台上可谓一家独大,这一点在很大程度上限制了HLSL的推广和发展。但是HLSL用于DX游戏领域却是深入人心。

  Cg语言(C for Graphic)是为GPU编程设计的高级着色语言,Cg极力保留C语言的大部分语义,并让开发者从硬件细节中解脱出来,Cg同时也有一个高级语言的其它好处,如代码的易重用性,可读性得到提高,编译器代码优化。Cg是一个可以被OpenGL和Direct3D广泛支持的图形处理器编程语言。Cg语言和OpenGL、Direct3D并不是同一层次的语言,而是OpenGL和DirectX的上层,即Cg程序是运行在OpenGL和DirectX标准顶点和像素着色的基础上的。Cg由NVIDIA公司和微软公司相互协作在标准硬件光照语言的语法和语义上达成了一致开发。所以,HLSL和Cg其实是同一种语言。

10

看这3个渲染的阶段,在屏幕上渲染一个像素点就得经过这3个阶段,当然还有其它的处理,比如这个像素点会跑到屏幕外,还要做剔除,这是后面会讲的,我们来具体的看:

11

这是应用阶段,当把要渲染的数据加载到显存中的时候,内存中的数据同样是存在的,也就是这个阶段,会存在两个完全相同的渲染数据.

渲染状态是什么呢?就是比如你的模型有一半在屏幕里,剩下的一般怎么办呢?数据是不是也要传呢?这就是要设置它的渲染状态.

调用drawcal下面会讲,大概就是一条drawcall就代表着,cpu发出一条指令,让gpu渲染某一个模型或者贴图,或者一个像素点.

12

当数据加载在显存中,gpu的工作就开始了,如果模型在屏幕的外面,这里的gpu也有一个剔除操作,但是这个剔除与cpu剔除不一样.这个的剔除是不会将数据计算.

13
14

我们在unity编程只会干涉绿色的部分,黄色的部分一般也不会有接触.

15

顶点数据为输入,顶点数据是由应用阶段加载到显存中,再由Draw Call指定的。这些数据随后被传递给顶点着色器。

顶点着色器是完全可编程的,它通常用于实现顶点的空间变换,顶点着色器等功能。曲面细分着色器是一个可选着色器,用于细分图元。

几何着色器同样是可选着色器,可以被用于执行逐图元的着色操作,或者被产生于更多的图元。

裁剪,这一阶段的目的是将那些不在摄像机视野内的顶点裁剪掉,剔除某些三角图元的面片。这个阶段可配置。

屏幕映射,这一阶段不可配置和编程,负责把每个图元的坐标转换到屏幕坐标系中。

光栅化概念阶段中的三角形设置三角形遍历都是固定函数的阶段。

片元着色器则是完全可编程的,用于实现逐片元的着色操作。

逐片元操作阶段负责很多重要操作,如修改颜色,深度缓冲,进行混合等,不可编程,但是可配置。

16

那么模型空间是什么意思呢?换句话说就是三维的物体显示在二维的屏幕上它们之间的转换.会有坐标,大小等等的数据计算.

17

那么这里就解释了上面说的一些在屏幕外的模型裁剪.

18

这里再多说一句,光栅化可能有些不太好理解,其实光栅化就是像素化,怎么理解呢?就是将渲染计算好的数据,转换成一个一个的像素显示在电脑屏幕上.

19

其实对于建模有点了解的朋友一定会听过三角面,这个概念.不管你在建模软件中是几边面,但是在unity中的模型你会发现,统统都会变成三角面

20

纹理,即贴图与贴图的效果,模型其实是一个光滑的平面,但是,为什么有的人物模型看上去会有皱纹,会有血管呢?这就是纹理的渲染.

21

什么是混合呢?因为渲染一个模型,首先线框,贴图,法线,高光,等这一些列的计算要合在一个像素电上.这个称之为合并.

22

模板测试,与之相关的是模板缓冲(Stencil Buffer)。模板缓冲和颜色缓冲,深度缓冲几乎是一类东西。如果开启了模板测试,Gpu首先读取(使用读取掩码)模板缓冲区中该片元位置的模板值,然后将该值和读取(使用读取掩码)到的参考值进行比较,这个比较函数可以由开发者指定的,例如小于等于舍弃该片元,或者大于等于舍弃该片元。如果这个片元没有通过测试,该片元就会被舍弃。不管一个片元有没有通过模板测试,我们都可以根据模板测试和之后的深度测试结果来修改模板缓冲区,这个操作也是由开发者指定的。模板测试通常用于限制渲染区域,或者渲染阴影,轮廓渲染等。

23

如果开启了深度测试,Gpu会把该片元的深度值和已经存在于深度缓冲中的深度值进行比较。这个比较函数也是可由开发者设置的,例如小于时舍弃该片元,或者大于时舍弃该片元。通常这个比较函数是小于等于,即如果这个片元的深度大于等于当前深度缓冲区中的值,那么就舍弃它。这是因为我们总想只显示出离摄像机最近的物体,而那些被其他物体遮挡的就不需要出现在屏幕上。和模板测试不同的是,如果一个片元没有通过深度测试,它就没有权利更改深度缓冲区的值。如果一个片元通过了测试,那么开发者可以指定是否要用这个片元的深度值覆盖所有的深度值。

24

合并 ,渲染过程是一个物体接着一个物体画到屏幕上,而每个像素的颜色信息被储存在一个名为颜色缓冲的地方。因此,当我们执行这次渲染时,颜色缓冲中往往已经有了上次渲染之后的颜色结果,那么,我们使用这次渲染得到的颜色完全覆盖掉之前的结果还是进行其他处理,就是合并需要解决的。

对于不透明物体,开发者可以关闭混合(Blend)操作。这样片元着色器计算得到的颜色值就会之间覆盖掉颜色缓冲区中的像素值。但对于半透明物体,就需要混合操作来让这个物体看起来是透明的。

25
26

1.CPU与GPU如何并行工作?

我们之前看到的是一个流水线式的模式,如果需要CPU和GPU并行工作,就需要使用命令缓冲区(Command Buffer)。

命令缓冲区包含了一个缓冲队列,由Cpu向其中添加命令,而由Gpu从中读取命令,添加和读取过程是相互独立的。命令缓冲区使得Cpu和Gpu可以相互独立工作。当Gpu需要渲染一些对象时,它就可以从命令队列中取出一个命令并执行。

命令缓冲区有很多种类,Draw Call就是一种。其他命令还有改变渲染状态等。

2,什么是固定管线渲染?

固定函数的流水线(Fixed-Function Pipeline),简称固定管线,通常是指在较旧的Gpu上实现的渲染流水线。这种流水线只给开发者提供一些配置操作,但开发者没有对流水线阶段的完全控制权。

在Unity中目前的固定管线shader都会自动编译顶点片元shader。

3,什么是Shader?

Gpu流水线上一些可高度编程的阶段,而由着色器编译出来的最终代码是会在Gpu上运行的;

有一些特定类型的着色器,如顶点着色器,片元着色器等。

依靠着色器我们可以控制流水线中的渲染细节,例如用顶点着色器来进行顶点变换及传递数据,用片元着色器来进行逐像素渲染。

27
28

Unity Shader实际上指的就是一个ShaderLab文件。以.shader作为后缀的一种文件。在Unity shader里面,我们可以做的事情远多于一个传统意义上的Shader。

在传统的shader中,我们仅可以编写特定类型的Shader,例如顶点着色器,片元着色器等。在Unity Shader中,我们可以在同一个文件里面同时包含需要的顶点着色器和片元着色器代码。

在传统shader中,我们无法设置一些渲染设置,例如是否开启混合,深度测试等,这些是开发者在另外的代码中自行设置的。而Unity shader中,我们通过一行特定的指令就可以完成这些设置。

在传统shader中,我们需要编写冗长的代码设置着色器的输入和输出,要小心的处理这些输入输出的位置对应关系等。而在Unity shader中,我们只需要在特定语句块中声明一些属性,就可以依靠材质来方便的改变这些属性。而对于模型自带的数据(如顶点,纹理坐标,法线等),Unity Shader也提供了直接访问的方法,不需要开发者自行编码来传给着色器。

结束语

谢谢大家的聆听,当我们在玩游戏时,如果能想到在你的屏幕华丽的背后是cpu+gpu的若干次计算才展现出来的效果,是不是对写这些功能的程序员们多了一丝敬畏之情.

代码是神圣的,我们编写代码的人也要对代码心存敬畏,战战兢兢,如履薄冰.向代码致敬!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 数据结构与算法(四)

    大O记法能客观的衡量各种算法的时间复杂度,是比较各个算法好坏的利器.比如上篇文章中介绍的二分查找的时间复杂度O(logN)就比线性查找O(N)快得多.

    LittleU
  • Jtro的开发杂记

    当高版本(unity2018)的项目迁移到低版本(unity2017)中的时候,需要将项目中的“Packages”文件夹中的json文件删除并让它重新生成。

    LittleU
  • Jtro的技术分享:获取传感器消息通过mqtt通讯传给网页前端

    标题虽然这么长,但是做法却十分简单 总共分为两个步骤 第一:获取传感器消息 第二:传给mqtt网络 第三:网页根据mqtt消息采取动作 总结:就是硬件...

    LittleU
  • go linux 根据进程名查找进程

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    地球流浪猫
  • hadoop基础入门教程--DKHadoop配置安装教程

    使用hadoop版本是DKH标准三节点发行版,DKHadoop版本的易用性比较好,环境部署要简单的多,参考此篇安装前请先下载DKHadoop版本,网盘链接:ht...

    IT小白龙
  • golang flag 命令行参数解析

    copy_left
  • java开发操作系统:一个程序向另一个程序伸出的咸猪手

    望月从良
  • LeetCode 800. 相似 RGB 颜色

    RGB 颜色用十六进制来表示的话,每个大写字母都代表了某个从 0 到 f 的 16 进制数。

    Michael阿明
  • ASP.NET Identity 2新增双重认证、帐号锁定、防伪印章功能并修复了一些bug

    Microsoft最近发布了ASP.NET Identity 2,该版本支持双重认证、帐号锁定以及防伪印章功能,还增强了用户帐号和索引。此外新版本还包含一个改进...

    张善友
  • Akka-Cluster(4)- DistributedData, 分布式数据类型

    在实际应用中,集群环境里共用一些数据是不可避免的。我的意思是有些数据可以在任何节点进行共享同步读写,困难的是如何解决更改冲突问题。本来可以通过分布式数据库来实现...

    用户1150956

扫码关注云+社区

领取腾讯云代金券