Shader是为渲染管线中的特定处理阶段提供算法的一段代码。shader是伴随着可编程渲染管线出现的,它的出现使得游戏开发者可以对渲染过程加以控制,拥有更大的创作空间,因此Shader的出现可以看作是实时渲染技术的一次革命。

为了方便游戏开发者使用,Unity提供了大量的内建Shader,包括从最简单的顶点光照效果到高光,法线,反射等游戏中最常用的材质效果。

内建的shader根据应用对象可以分为以下几大类:

  • 普通Normal Shader Family:用于不透明的对象。
  • 透明Transparent Shader Family:用于透明的对象。
  • 透明镂空效果Transparent Cutout Shader Family:用于包含完全透明部分的半透明对象。
  • 自发光Self-illuminated Shader Family:用于有发光效果的对象。
  • 反射Reflective Shader Family:用于能反射环境立方体贴图的不透明对象。

如何在效果各异的内建Shader中选择最合适的Shader是开发者需要考虑的问题,毕竟视觉效果越好的Shader,一般渲染开销也越大,同时对硬件的要求也越高。游戏开发者需要在游戏画面和游戏性能之间做出平衡。

以下是不同的光照效果从低到高的计算开销排序;

  • Unlit:仅适用纹理颜色,不受光照影响。
  • VertexLit:顶点光照。
  • Diffuse:漫反射。
  • Specular:在漫反射基础上增加高光计算。
  • Normal mapped:法线贴图,增加了一张发现贴图和几个着色器指令。
  • Normal mapped Specular:带高光法线贴图。
  • Parallax Normal Mapped:视差法线贴图,增加了视差贴图的计算开销。
  • Parallax Normal Mapped Specular:带高光视差法线贴图。

三种自定义的Shader

Unity中,开发者可以编写3种类型的Shader:

ü  表面着色器Surface Shaders:通常情况下用户都会使用这种Shader,它可以与灯光,阴影,投影器进行交互。表面着色器的抽象层次比较高,它可以容易地以简洁方式实现复杂的着色器效果。表面着色器可同时正常工作在前向渲染及延迟渲染模式下。表面着色器以Cg/HLSL语言进行编写。

ü  顶点和片段着色器Vertex and fragment Shaders:如果需要进行一些表面着色器无法处理的酷炫效果,或者编写的Shader不需要与灯光进行交互,或者想要的只是全屏图像效果,那么可以使用顶点和片段着色器。这种Shader可以非常灵活地实现想要的效果,但是需要编写更多的代码,并且很难与Unity的渲染管线完美集成。顶点和片段着色器同样是用Cg/HLSL语言编写。

ü  固定功能管线着色器Fixed Function Shaders:如果游戏运行在不支持可编程管线的老旧硬件上,那么就需要编写这种Shader。固定功能管线着色器可以作为片段或表面着色器的备用选择,这在当硬件无法运行那些炫酷Shader的时候哦,还可以通过固定功能管线着色器来绘制出一些基本的内容。固定功能管线着色器完全以ShaderLab语言编写,类似于微软的Effects或者是Nvidia的CgFX。

无论编写哪种Shader代码,都需要嵌在ShaderLab代码中,Unity需要通过ShaderLab代码来组织Shader结构。

shader Language目前主要有三种语言:基于OpenGL的GLSL,基于Direct3D的HLSL,还有NVIDIA公司的Cg语言。

  1. HLSL全称是"High Level Shading Language"
  2. cg全称是"C for Graphic"
  3. GLSL全称是"OpenGL Shading Language"

Shader language原理

使用shader language编写的程序被称之为shader program着色程序。着色程序分为两类:vertex shader program顶点着色程序和fragment shader program片段着色程序。

GPU上有两个组件:Programmable vertex processor可编程点处理器,又称为顶点着色器;Programmable fragment processor可编程片段处理器,又称为片段着色器。

顶点和片段处理器都拥有非常强大的并行计算能力,并且非常擅长于矩阵(不高于4阶)计算,片段处理器还可以高速查询纹理信息(目前顶点处理器还不行,这是顶点处理器的一个发展方向)。

顶点着色器控制顶点坐标转换过程,片段着色器控制像素颜色计算过程。前者的输出是后者的输入。

现阶段可编程图形硬件的输入/输出。输入寄存器存放的是输入的图元信息,输出寄存器存放的是处理后的图元信息,纹理Buffer存放的是纹理数据,目前大多数的可编程图形硬件只支持片段处理器处理纹理;从外部宿主程序输入的常量放在常量寄存器中;临时寄存器存放着色程序在执行过程中产生的临时数据。

shader language被定位是高级语言,但是却没有独立于硬件,而是完全依赖于GPU架构,所以GPU编程技术的发展本质上还是图形硬件的发展。

eg:

 Shader "MyShader"{//Shader的名称

 Properties{

 _MyTexture("My Texture",2D) = "White"{}

 //在这里定义Shader中使用的属性,例如颜色,向量,纹理

 }

 SubShader{

 //在这里编写Shader的实现代码

 //包括表面着色器,顶点和片段着色器的Cg/HLSL代码

 //或者是固定功能管线着色器的ShaderLab代码

 }

 SubShader{

 //在这里实现简化版的备选Shader,用于在不支持高级Shader特性的老硬件上运行

 }

 }

创建Shader

在Unity中开始编写Shader代码前,需要在项目工程中创建一个Shader文件,着点和编写脚本一样。

ShaderLab基础语法

在Unity中提供了一种名为ShaderLab的着色器语言来编写Shader,语法类似Cg语言,该语言能够描述材质所需要的各种特性,并且可以很方便地通过Inspector视图来查看和修改。

eg:

 Shader "Simple colored lighting"{

 Properties{//定义一个名为Main Color的颜色属性

 _Color("Main Color",Color) = (,0.5,0.5,)

 }

 SubShader{//Shader的实现代码

 Pass{

 Material{

 Diffuse[_Color]

 }

 Lighting On

 }

 }

 }

示例运行效果如下:

注意:Unity中的游戏体不能为默认材质添加Shader。要想使用自定义的Shader,首先需要自定义一个材质球,然后才可以使用自定义的Shader。

语法解析

由上面的代码可以看出,Shader的第一行指明了Shader的名字:“Simple colored lighting”。紧跟着就是Shader的第一个重要组成部分,Properties{ }。我们可以在Properties里面定义一系列属性,这些属性被下面的SubShader所共享,它们可以让你在Unity的面板里直观地控制Shader变量,影响渲染结果。

Shader根命令:每个着色器都需要定义一个唯一的Shader根命令。其结构如下:

Shader “着色器名称”{

Properties{}   //属性定义

SubShader{}  //子着色器1

SubShader{}  //子着色器2

...

Fallback "备用着色器名称"  //如果所有子着色器都不能运行,则使用备用着色器

}

Properties属性

定义:用来定义着色器中使用的贴图资源或者数值参数等,这些属性会在Inspector视图的材质界面中显示,可以方便地进行设置及修改。

在示例中,Properties代码块中定义了一个名为Main Color的颜色属性。

着色器的属性定义在属性代码中,语法为:

Properties{
 //属性列表 

  _Name ( "Displayed Name", type ) = default value {options}

}
  • _Name:程序中引用的名字,和我们一般理解的变量名称是一样的。
  • Displayed Name:这个字符串将会出现在Unity材质的编辑面板上。
  • type:该属性的类型。Unity支持以下几种属性类型:
    • Color:表示一个单一的RGBA颜色值;
    • 2D: 表示一张大小为2的次方的纹理贴图,可以使用基于模型UV坐标来进行采样;
    • Rect:表示一张纹理不是2的次方的纹理贴图;
    • Cube:表示一个可用于反射的3D立方体映射贴图,可以进行采样;
    • Range(min, max):一个取值范围在min到max之间的浮点值;
    • Float: 一个可以为任意值的浮点值;
    • Vector:一个4维度的向量。
  • default value:该属性的默认值。
    • Color:使用浮点值表示的(r, g, b, a),例如(1,1,1,1);
    • 2D/Rect/Cube:对于贴图类型的属性,默认值可以是一个空字符串,或者"white", "black", "gray", "bump"这样的字符串;
    • Float/Range:在此范围内的值即可;
    • Vector:以(x,y,z,w)形式表示的4D向量;
  • { options }:只和纹理类型的2D、Rect和Cube相关,它必须至少被指定为{ }。你可以使用空格分隔多个选项,有如下选择:
    • TexGen贴图生成模式:该纹理的自动纹理坐标生成模式。可以为ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal。这些直接对应了OpenGL中的texgen modes。注意,如果你编写了一个顶点函数,那么可以忽略TexGen。

SubShader子着色器

一个着色器包含一个或者多个着色器,当Unity使用着色器渲染时,会从上到下遍历子着色器,找到第一个能被用户设备支持的子着色器,并使用该子着色器进行渲染。如果没有子着色器能够运行,那么会使用备用着色器。

子着色器由标签(可选)、通用状态(可选)、Pass列表组成。定义子着色器的语法结构为:

SubShader{
[Tags标签]
[CommonState通用状态]
Passdef[Passdef... Pass定义]
}

在Unity使用子着色器进行渲染时,每个Pass都会渲染一次对象(有时会根据光照交互情况渲染多次)。由于每次渲染都会有一定的开销,因此尽量减少不必要的Pass的数量。

eg:

SubShader{
Pass{
Lighting Off//关闭灯光
SetTexture [_MainTex]{}//使用纹理MainTex
}
}

Pass

在每个Pass中,对象的几何体都会被渲染一次。定义Pass的语法如下:

Pass{
[Name and Tags名称和标签]
[RenderSetup渲染设置]
[TextureSetup纹理设置]
}
Pass{
Name and Tags名称和标签]
[RenderSetup渲染设置]
[TextureSetup纹理设置]
}

Pass包含一个可选的名称和标签列表、一个可选的渲染命令列表和一个可选的纹理列表。

[Name and Tags名称和标签]:可以定义Pass的名称以及任意数量的标签,为Pass命名后可以在别的着色器中通过Pass名称来重用它。标签可以用来向渲染管线说明Pass的意图,它是键-值对的形式。

[RenderSetup渲染设置]:Pass里可以设置图形硬件的各种状态,例如开启Alpha混合、开启雾效等。Pass里可用的渲染设置命令如下表:

[TextureSetup纹理设置]:在设置渲染状态以后,可以指定一些使用的纹理及其混合模式。纹理设置的语为:

SetTexture 纹理属性{
[命令选项]
}

纹理设置用于固定功能管线,如果使用表面着色器或自定义的顶点及片段着色器,那么纹理设置将会被忽略。

SetTexture的命令选项包括三种:

  • combine:将两个颜色混合,混合的源可以是previous上一次SetTexture的结果、constant常量颜色值、primary顶点颜色、texture纹理颜色的一种。
  • constantColor:设置一个常量颜色值。
  • matrix:设置矩阵对纹理坐标进行变换。

另外Unity里还可以使用两种特殊的Pass来重用一些常用的功能,或者是实现一些高级功能,它们是:

1)UsePass:可以通过UsePass来重用其他着色器里命名的Pass。

eg:

UsePass "Specular/BASE" //使用高光着色器Specular中命名为BASE的Pass

UsePass的使用可以减少代码的重复,提高代码的重用率,提高开发效率。

2)GrabPass:将屏幕抓取到一个纹理中,供后续的Pass使用看,可以通过GrabTexture来访问。

备用着色器Fallback

Fallback语句一般位于所有子着色器之后,它的含义是如果当前硬件不支持任何子着色器,那么将使用备用着色器。

Fallback语句的用法有两种:

Fallback"备用着色器名称",例如Fallback "Diffuse"。

Fallback Off,声明不使用备用着色器,当没有子着色器能够运行时也不会发出警告。

Unity3d之Shader开发介绍的更多相关文章

  1. Unity3D手游开发实践

    <腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/ ...

  2. 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结

    前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...

  3. 《Unity3D/2D游戏开发从0到1》正式出版发行

    <Unity3D/2D游戏开发从0到1>正式出版发行 去年个人编写的Unity书籍正式在2015年7月正式发行,现在补充介绍一下个人著作.书籍信息:      书籍的名称: <Uni ...

  4. Unity3D手机游戏开发

    <Unity3D手机游戏开发> 基本信息 作者: 金玺曾 出版社:清华大学出版社 ISBN:9787302325550 上架时间:2013-8-7 出版日期:2013 年8月 开本:16开 ...

  5. (转)Unity3D手游开发实践

    作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). (转)& ...

  6. Unity3D Built-in Shader详解一

    Unity3D内置了很多Shader,文档很详细,自己翻一下.便于加深印象. 首先先解释下Unity3D的Shader.Unity里面的Shaders是使用一种叫ShaderLab的语言编写的,它同微 ...

  7. Unity3D游戏UI开发经验谈

    原地址:http://news.9ria.com/2013/0629/27679.html 在Unity专场上,108km创始人梁伟国发表了<Unity3D游戏UI开发经验谈>主题演讲.他 ...

  8. 关于《Unity3D/2D游戏开发从0到1》书籍再版说明

    关于<Unity3D/2D游戏开发从0到1>第一版本在2015年7月1日全国发行,累计得到不少国内高校教师.培训机构的好评.但是由于Unity官方对于技术不断的升级与版本的快速迭代,基于U ...

  9. Unity3d 发动机原理详细介绍

    Unity3d 发动机原理详细介绍 www.MyException.Cn   发布于:2013-10-08 16:32:36   浏览:46次 0     Unity3d 引擎原理详细介绍 体系结构 ...

随机推荐

  1. redis实践:用户注册登录功能

    本节将使用PHP和Redis实现用户注册登录功能,下面分模块来介绍具体实现方法. 1.注册 需求描述:用户注册时需要提交邮箱.登录密码和昵称.其中邮箱是用户的唯一标识,每个用户的邮箱不能重复,但允许用 ...

  2. ps换衣服

    1.抠衣服->给衣服新建图层(ctrl+j)->给图层去色,让衣服边黑白色.2.剪贴蒙版(上图:大花布,下形:衣服).作用:大花布替换成衣服3.大花布图层->叠加图层样式或其它图层样 ...

  3. macbook基本配置

    1.安装iterm2, 2.安装搜狗输入法, 3.安装迅雷, 4.安装homebrew 5.安装新版的gcc,bash等等,及升级配置文件.

  4. c语言常量指针赋值给变量指针导致警告

    常量指针定义:常量是形容词,指针是名词,以指针为中心的一个偏正结构短语.这样看,常量指针本质是指针,常量修饰它,表示这个指针乃是一个指向常量的指针.指针指向的对象是常量,那么这个对象不能被更改.常量指 ...

  5. 【Android】3.22 示例22--LBS云检索功能

    分类:C#.Android.VS2015.百度地图应用: 创建日期:2016-02-04 简介:介绍如何使用LBS.云检索用户自有数据. 详述: (1)LBS.云是百度地图针对LBS开发者推出的平台级 ...

  6. 安卓getSystemService

    getSystemService是Activity中的方法,依据传入的name来取得相应的服务对象,这些服务名称參数都是Context类中的常量        Name                 ...

  7. Android App 内存泄露之调试工具(1)

    Android App 内存泄露之工具(1) 使用内存监測工具 DDMS –> Heap 操作步骤 启动eclipse后,切换到DDMS透视图,并确认Devices视图.Heap视图都是打开的, ...

  8. windows xp 创建 Oracle(11G)数据库实例时写入系统日志失败解决方案

    1.查看Windows日志相关服务(Even Log),无异常: 2.清空事件管理器中“应用程序”和“系统节点”的内容,对这两个节点,分别在“属性”页面用增大“最大日志文件大小”的值,并选中“按需要改 ...

  9. Not get deviceToken yet. Maybe: your certificate not configured APNs? or current network is not so good so APNs registration failed? or there is no APNs register code? Please refer to JPush docs.”

    今天在项目中集成了极光推送,一切都配置完毕,把程序运行起来的时候,报了下面的错误: Not get deviceToken yet. Maybe: your certificate not confi ...

  10. Office 2013 Excel 打开文档很慢很慢的解决方法

    这个问题查了很多案例,试了很多方法,但是只有下面这个方法有用! 这几天打开excel文档很慢很慢,双击之后好久没反应,过会儿它才慢慢冒出来,当时将就了,刚刚休息的时候想着查一下吧,不然很影响工作效率! ...