Unity3D shader简介
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图像的后期处理。
- Part 1: Unity3D shader简介(A gentle introduction to shaders in Unity3D)
- Part 2: Unity3D表面shader(Surface shaders in Unity3D)
- Part 3: Unity3D基于物理渲染和光照模型( Physically Based Rendering and lighting models in Unity3D)
- Part 4: Unity3D顶点和片段shader(Vertex and fragment shader in Unity3D)
- Part 5: Unity3D传递数组给shader(Passing arrays to a shader: heatmaps in Unity3D)
- Part 6: Unity3D屏幕shader和效果后期处理(Screen shaders and postprocessing effects in Unity3D)
Unity3D shader简介的更多相关文章
- 【译】Unity3D Shader 新手教程(1/6)
本文为翻译,附上原文链接. 转载请注明出处--polobymulberry-博客园. 刚开始接触Unity3D Shader编程时,你会发现有关shader的文档相当散,这也造成初学者对Unity3D ...
- 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...
- 【淡墨Unity3D Shader计划】五 圣诞用品: Unity在Shader三种形式的控制&混合操作编译
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/42060963 作者:毛星云(浅墨) ...
- 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 & 第一个Shader的书写
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
- 转 猫都能学会的Unity3D Shader入门指南(二)
猫都能学会的Unity3D Shader入门指南(二) 关于本系列 这是Unity3D Shader入门指南系列的第二篇,本系列面向的对象是新接触Shader开发的Unity3D使用者,因为我本身自己 ...
- Unity3D Shader入门指南(二)
关于本系列 这是Unity3D Shader入门指南系列的第二篇,本系列面向的对象是新接触Shader开发的Unity3D使用者,因为我本身自己也是Shader初学者,因此可能会存在错误或者疏漏,如果 ...
- Unity3d Shader
Unity3d Shader 预览Surface Shader主要用来实现光照相关处理,可能更简洁. Vertex and Fragment Shader 如果不与光照交互, 则可以用这个shader ...
- 【淡墨Unity3D Shader计划】四 热带雨林的文章: 排除、深度测试、Alpha测试和基本雾编译
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1222/163.html 作者:毛星云 ...
- 猫都能学会的Unity3D Shader入门指南(二)
关于本系列 这是Unity3D Shader入门指南系列的第二篇,本系列面向的对象是新接触Shader开发的Unity3D使用者,因为我本身自己也是Shader初学者,因此可能会存在错误或者疏漏,如果 ...
随机推荐
- mysql.connector操作mysql的blob值
This tutorial shows you how to work with MySQL BLOB data in Python, with examples of updating and re ...
- AC算法 及python实现
零 导言 软件安全课上,老师讲了AC算法,写个博客,记一下吧. 那么AC算法是干啥的呢? ——是为了解决多模式匹配问题.换句话说,就是在大字符串S中,看看小字符串s1, s2,...有没有出现. AC ...
- 先学习下一些基础的js和xpath语法
这两个方法到底是在做什么呢?其实就是克隆了当前指令的节点,并生成子作用域.克隆的节点由transclude定义,如果你的属性是true,则克隆的是指令模板中的ng-transclude所在的DOM节点 ...
- 框架介绍thinkphp
ThinkPHP是一个免费开源的,快速.简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的.ThinkPH ...
- ssh整合,导入structs包后报错 getAnnotation(AnnotatedElement ae,Class<T> annotatetype)找不到
今天在整合ssh(spring-framework-3.2.5.RELEASE-dist+struts-2.3.15.3-all+hibernate-release-4.2.6.Final)环境的时候 ...
- java-base64编码和解码
一.反射/*** * encode by Base64 */ public static String encodeBase64(byte[]input) throws Exception{ Clas ...
- action func用法记记
public partial class Form1 : Form { public Form1() { InitializeComponent(); } public delegate void s ...
- OD使用教程5
怎样恢复数据被改过的代码 点击m进入内存分布图 双击进入文件头 将过大的值一一修改为正常值 普通程序没有动态链接表所以值改为0 保存:首先记住地址 其次 选中差不多的长度,保存 正常的程序
- hdoj 1016 Prime Ring Problem
Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ... ...
- ORACLE导入、导出命令使用方法
oracle导入.导出命令使用方法: 给用户增加导入数据权限的操作 第一,启动sql*puls 第二,以system/manager登陆 第三,create user 用户名 IDENTIFIED B ...