Unity3D shader简介

可以肯定的说Unity3D使得很多开发者开发游戏更容易。毫无疑问,shader(着色器)编码,仍有很长的路要走。shader是一个专门运行在GPU的程序,经常被神秘包围,它最终绘制3D模型的三角形。如果你想给游戏一个特殊的显示,学习如何编写shader是必要的。Unity3D使用shader做后期处理,对2D游戏也是必不可少的。这个系列的文章将逐步介绍shader编程,并面向几乎没有任何shader知识的开发者。

简介

下图大致表示了在Unity3D渲染流程中发挥作用的3个不同实体:

3D模型本质上是,被称为顶点的3D坐标集合。他们连接在一起构成一些三角形。每个顶点包含一些其它的信息,如颜色、点指的方向(法线)、纹理映射坐标(UV数据)。

没有材质模型是不能被渲染的。材质包含一个shader和其属性值的封装。因此,不同材质可以共享相同的shader,赋予不同的数据。

shader剖析

Unity3D支持两种不同的shader:表面shader、片段和顶点shader。还有第三种类型:固定管线shader,但是如今已经过时了,将不包含在本系列文章。无论你需要的是哪种类型,shader的结构都一样:

Shader "MyShader"

{

Properties

{

// The properties of your shaders

// - textures

// - colours

// - parameters

// ...

}

SubShader

{

// The code of your shaders

// - surface shader

//    OR

// - vertex and fragment shader

//    OR

// - fixed function shader

}

}

可以包含多个SubShader,一个接一个。他们包含GPU的实际指令。Unity3D将找到与你显卡兼容的SubShader,并顺序执行他们。这对多平台编码是非常有用,因为你可以在一个文件中编写同一shader的不同版本。

属性

shader的属性在某种程度上相当于C#脚本中的public字段,他们将出现在材质的inspector面板,给你机会来调整。但不像脚本,材质是资源:编辑中游戏运行时修改材质的属性值是永久的。甚至游戏停止后,修改的属性值也是有效的。

下面的代码片段涵盖了你可以在shader中使用的所有基本类型的定义:

3~4行中的2D,表示参数是纹理。他们可以初始化为white、black、gray。你也可以使用bump表示使用法线贴图,这种情况下,它将自动初始为颜色#808080,这用来表示没有任何凸凹。Vector和Color总是有4个元素(分别为xyzw和rgba)。

下图展示了一个shader附着到一个材质上之后,在inspector面板中是如何显示的。

不幸的是,这对我们使用属性还不够。事实上,Properties块被Unity3D用来从inspector访问shader隐藏变量。这些变量仍需定义在shader中,它们包含在SubShader块中。

纹理的类型为sampler2D。向量是float4、颜色一般是half4,分别使用32和16位表示。用来编写shader的语言为Cg/HLSL,很迂腐:参数的名称必须与先前定义的匹配。然而类型不需要,例如把_MyRange声明为half而不是float不会报任何错误。一些令人困惑的是,如果你定一个向量类型的属性,关联到一个float2变量,额外的2个值将被Unity3D忽略。

渲染顺序

正如已提到的,SubShader块包含实际代码,使用Cg/HLSL(非常像C)编写。不严格地说,一个shader为图像的每个像素执行,它的性能非常关键。由于GPU的体系结构,一个shader中能够执行的指令数量有限制。可以通过分割几个部分执行,但本教程不包含这块。

一个SubShader通常看起来像这样:

第8~11行包含实际的Cg代码,通过CGPROGRAM和ENDCG指令示意。

第3行,在实际代码之前,介绍tags的概念。tags用来告诉Unity3D我们写的shader的某些属性。例如,shader渲染的顺序(Queue)和应该如何渲染(RenderType)。

当渲染三角形时,GPU通常根据它们离摄像机的距离,远的先绘制。这在渲染不透明的几何形状时够用了,但是透明物体将失败。这也是为什么Unity3D运行指定Queue标签,可以控制每个材质的渲染顺序。Queue接受正整数(越小越先绘制),预定义(mnemonic)的标签也可以使用:

l  Background(1000):用于背景和天空盒

l  Geometry(2000):默认标签,用于大部分不透明物体

l  Transparent(3000):用于包含透明属性的材质,例如玻璃、火、粒子、水

l  Overlay(4000):用于镜头耀斑,GUI元素和文本

Unity3D还允许指定相关顺序,例如Background+2,表示1002队列值。搞乱了Queue值会导致恶劣的情况,一个对象总是被绘制,即使它应该被其他模型遮挡住了。

Ztest

记住,一个包含透明属性(Transparent)的对象并不总是显示在不透明(Geometry)对象上面。默认情况下,GPU执行ZTest避免隐藏的对象被绘制。原理是,它使用了一个额外的缓冲区,其大小与屏幕渲染的相同。每个像素包含绘制对象在该像素的深度(离相机的距离)。如果我们要绘制一个像素比当前深度更大,像素就被丢弃。ZTest剪裁被其它对象遮挡住的像素,无论他们绘制到屏幕上的顺序。

表面 VS 顶点和片段

shader代码的最后一部分。在渲染之前,需要决定使用那种类型的shader。本节将给出shader效果惊鸿一瞥的样子,但不会深入解释。表面、顶点和片段shader将在本教材的下一部分覆盖。

表面shader

当材质需要根据光照模拟实际效果时,那么你就需要一个表面shader。表面shader在函数surf中隐藏光线如何被反射的计算,并允许指定“直观”的属性,如反照率、法线、反射率等。然后将这些值插入到光照模型,将输出每个像素的最终RGB值。或者,当需要非常高级的效果是,你也可以编写自己的光照模型。

一个典型的表面shader的Cg代码如下所示:

第5行指定输入的纹理,然后在第12行将指定Albedo属性。第3行指定使用Lambertian光照模型,这个是非常典型光照如何影响对象的模型。shader仅使用反照率属性通常称为漫反射(diffuse)。

顶点和片段shader

顶点和片段shader的工作贴近GPU渲染三角形的方式,并没有光照如何表现的概念。模型的几何形状首先通过一个调用函数vert,改变他的顶点。然后各个三角形通过另一个调用函数frag,这决定了最终每个像素的RGB颜色。这对2D效果非常有用,后期处理和特殊的3D效果非常付出需要使用表面shader。

下面的顶点和片段shader简单只是使用红色,没有光照:

第15~17行,将原始的3D空间顶点转换到最终的2D屏幕位置。Unity3D使用UNITY_MATRIX_MVP实现,隐藏了底层的实现数学运算。在此之后,第22行,给定每个像素为红色。只需要记住,顶点和片段shader的Cg部分需要封装到Pass块中。它跟简单的表面shader不一样。

结论

本篇文章逐渐引入了两种类型的Unity3D shader,并说明何时需要使用。接下来四篇文章,将介绍实现它们的细节。还有一个附加篇,将介绍屏幕shader,用于2D图像的后期处理。

Unity3D shader简介的更多相关文章

  1. 【译】Unity3D Shader 新手教程(1/6)

    本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 刚开始接触Unity3D Shader编程时,你会发现有关shader的文档相当散,这也造成初学者对Unity3D ...

  2. 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)  ...

  3. 【淡墨Unity3D Shader计划】五 圣诞用品: Unity在Shader三种形式的控制&混合操作编译

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/42060963 作者:毛星云(浅墨)  ...

  4. 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 & 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨)  ...

  5. 转 猫都能学会的Unity3D Shader入门指南(二)

    猫都能学会的Unity3D Shader入门指南(二) 关于本系列 这是Unity3D Shader入门指南系列的第二篇,本系列面向的对象是新接触Shader开发的Unity3D使用者,因为我本身自己 ...

  6. Unity3D Shader入门指南(二)

    关于本系列 这是Unity3D Shader入门指南系列的第二篇,本系列面向的对象是新接触Shader开发的Unity3D使用者,因为我本身自己也是Shader初学者,因此可能会存在错误或者疏漏,如果 ...

  7. Unity3d Shader

    Unity3d Shader 预览Surface Shader主要用来实现光照相关处理,可能更简洁. Vertex and Fragment Shader 如果不与光照交互, 则可以用这个shader ...

  8. 【淡墨Unity3D Shader计划】四 热带雨林的文章: 排除、深度测试、Alpha测试和基本雾编译

    本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1222/163.html 作者:毛星云 ...

  9. 猫都能学会的Unity3D Shader入门指南(二)

    关于本系列 这是Unity3D Shader入门指南系列的第二篇,本系列面向的对象是新接触Shader开发的Unity3D使用者,因为我本身自己也是Shader初学者,因此可能会存在错误或者疏漏,如果 ...

随机推荐

  1. 史上最全的常用iOS的第三方框架

    文章来源:http://blog.csdn.net/sky_2016/article/details/45502921 图像: 1.图片浏览控件MWPhotoBrowser       实现了一个照片 ...

  2. 一个程序员眼中的好UI

    最近接到一个项目发来的UI设计图,我觉得她给的材料很专业,特此分享. 发的RAR压缩包里面有一个images目录,里面放的都是切片好的图片. 图片切片基本上都是靠近边线切的,边上留的空白很少,这样切的 ...

  3. Linux下GDB调试

    GDB 是一个强大的命令行调试工具.大家知道命令行的强大就是在于,其可以形成执行 序列,形成脚本.UNIX 下的软件全是命令行的,这给程序开发提供了极大的便利,命令行 软件的优势在于, 他们可以非常容 ...

  4. html5 上传头像的裁剪

    本示例使用HTML5 canvas,简单的编写了上传头像的裁剪效果,移动端支持拖拽后裁剪, 虽然样式不好看,但是功能还算全: 下图为裁剪后的效果: html部分: <!DOCTYPE html& ...

  5. 如何用Matlab将cell数据写入文件

    我们知道,一般的文件读写函数是不接受直接将cell内容(非数值)直接写入文件的, 例如:dlmwrite('o.txt', C, 'delimiter', '\t');%C 为cell类型数据,会报错 ...

  6. MFC修改初始窗口大小和窗口名字禁止窗口最大,最小化

    2,在里面就可以修改初始窗口大小和窗口名字 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs){if( !CFrameWnd::PreCrea ...

  7. Win7 64位 VS2015环境使用SDL2-2.0.4

    之前在VS中使用SDL2,如果只链接SDL2.lib,会提示 error LNK2019: unresolved external symbol _main referenced in functio ...

  8. Object-C内存管理的理解总结

    今天看到了OC的内存管理这块,觉得很亲切. 自己的习惯是尽量自己掌控程序的空间和时间,有点强迫症的感觉.用C和C++做项目的时候,时时刻刻都在操心这new和delete的配对使用和计数,学习stl和b ...

  9. 在c#中使用bitblt显示图片

    使用bitblt比DrawImage有更好的性能 using AForge.Video.DirectShow; using System; using System.Collections.Gener ...

  10. Hbase随笔2

    Hbase是建立在HDFS上的分布式数据库,下图是Hbase表的模型: Hbase这个数据库其实和传统关系数据库还是有很多类似之处,而不是像mongodb,memcached以及redis完全脱离了表 ...