Unity Shader基础

Unity 材质的创建

我们可以在Unity的菜单栏中选择Assets->Create->Material来创建。当创建了一个材质后,就可以把它赋给一个对象,将材质直接拖拽到Scene视图中的对象上。

将材质直接拖曳到模型的Mesh Renderer组件中

Unity Shader的创建

我们可以在Unity的菜单栏中选择Assets->Create->Shader来创建。同时Unity给我们提供了4种Unity Shader模板来供我们选择。

  • Standard Surface Shader会产生一个包含了标准光照模型的表面着色器模板。
  • Unlit Shader则会产生一个不包含光照(但包含雾效)的基本的顶点/片元着色器。
  • Image Effect Shader则为我们实现各种屏幕后处理效果提供了一个基本模板。
  • Compute Shader会产生一种特殊的Shader文件,这类Shader利用GPU的并行性来进行一些与常规渲染流水线无关的计算。

Unity Shader的导入

Project视图中选中某个Unity Shader即可看到该Shader的导入设置面版。

Unity Shader的导入设置面板

Default Maps可以指定该Unity Shader使用的默认纹理。
Surface shader是否是一个表面着色器。
Fixed function是否是一个固定函数着色器。
Compiled code下拉列表可以让开发者检查该Unity Shader针对不同图像编程接口(列如OpenGL、D3D9、D3D11等)最终编译成的Shader代码。
Render queue使用的渲染队列。
Disable batching是否关闭批处理。
Properties属性列表。

Gompile and show code下拉列表

Shader Lab

Unity Shader是Unity为开发者提供的高级层渲染抽象层。Unity希望通过这种方式来让开发者更加轻松的控制渲染。在Unity中所有的Unity Shader都是使用ShaderLab来编写的。

Unity Shader为控制渲染过程提供了一层抽象。如果没有使用Unity Shader(左图), 开发者需要和很多文件和设置打交道,才能让画面呈现出想要的效果;而在Unity Shader的帮 助下(右图),开发者只需要使用ShaderLab来编写Unity Shader文件就可以完成所有的工作

Unity Shader的结构

1.Shader的起名
每个Unity Shader文件的第一行都需要通过Shader语义来指定该Unity Shader的名字。
当为材质选择使用的Unity Shader是,这些名称就会出现在材质面板的下拉列表里。

Shader "Custom/MyShader" {}

那么这个Unity Shader在材质面板中的位置就是
Shader->Custom->MyShader

在Unity Shader的名称定义中利用斜杠来组织在材质面板中的位置

2.Properties
Properties语义块中包含了一系列的属性,这些属性将会出现在材质面板中。

 Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }

在Unity中这些属性名字通常由一个下划线开始。显示的名称会出现在材质面板上。我们需要指定每个属性的类型。除此之外,我们还需要给每个属性指定一个默认值,我们第一次把这个Unity Shader赋给某个材质是,材质面板上显示的就是这些默认值。

常见的属性类型
Shader "Unity Shaders Book/Chapter 3/MyShader" {
    Properties {
        // Numbers and Sliders
        _Int ("Int", Int) = 2
        _Float ("Float", Float) = 1.5
        _Range("Range", Range(0.0, 5.0)) = 3.0
        // Colors and Vectors
        _Color ("Color", Color) = (1,1,1,1)
        _Vector ("Vector", Vector) = (2, 3, 6, 1)
        // Textures
        _2D ("2D", 2D) = "" {}
        _Cube ("Cube", Cube) = "white" {}
        _3D ("3D", 3D) = "black" {}
    }
不同属性类型在材质面板中的显示结果

3.SubShader
SubShader中定义了一系列的Pass以及可以选的状态标签设置。每个Pass定义了一次完整的渲染流程。

  • 状态设置
    Shader Lab提供了一系列渲染状态的设置指令。当在SubShader块中设置了渲染状态时,将会应用到所有的Pass,如果我们希望这样,可以在Pass语义块中单独的进行设置。
常见的渲染状态设置选项
  • SubShader的标签
    SubShader的标签是一个键值对,他的键和值都是字符串类型。它们用来告诉Unity的渲染引擎:SubShader我希望怎样以及何时渲染这个对象。
SubShader的标签类型
  • Pass语义块
Pass{
  [Name]
  [Tags]
  [RenderSetup]
  //Other code
}

首先,我们可以在Pass中定义该Pass的名称

Name "MyPassName"

通过这个名字,我们可以使用Shader Lab的UsePass来直接使用其他的Unity Shader中的Pass来提高代码的复用性。在Unity内部会把所有的Pass名称转换为大写字母,所以使用UsePass必须使用大写形式的名字。

UsePass "MyShader/MYPASSNAME"

我们也可以对Pass设置渲染状态,SubShader的渲染状态同样适用于Pass。在Pass中我们还可以使用固定渲染管线着色器。
Pass同样可以设置标签,但是它不同于SubShader的标签,这些标签适用于告诉渲染引擎我们希望如何来渲染物体。

Pass的标签类型

4.Fallback
Fallback用于告诉Unity,“如果上面的所有SubShader在这块显卡上都不能运行,那么就用这个最低级的Shader吧!”

Fallback "Name"
//或者关闭
Fallback off

Unity Shader的形式

在Unity中,我们可以使用下面三种形式来编写Unity Shader。

Shader "MyShader"
  ProPerties{
    //各种所需的属性
  }
  SubShader{
    //真正意义上的Shader代码
    //表面着色器(Surface Shader)或者
    //顶点/片元着色器(Vertex/Fragment Shader)或者
    //固定函数着色器(Fixed Function Shader)
  }
  SubShader{
    //和上一个一样
  }
}
  • 表面着色器
    表面着色器是Unity自己创造的一种着色器代码类型,但它在背后仍旧要转换成对应的顶点/片元着色器。它存在的价值在于Unity帮我们处理了很多光照细节,让我们不用心焦这些琐事。
一个简单的表面着色器示例代码

从代码中可以看出表面着色器被定义在SubShader语义块内(非Pass语义块)的CGPROFGAMENDCG中,CGPROFGAMENDCG中的代码时使用CG/HLSL来编写的。。

  • 顶点/片元着色器
一个简单的顶点/片元着色器

和表面着色器类似,顶点/片元着色器的代码也需要定义在CGPROFGAMENDCG中,不同的是,顶点/片元着色器是写在Pass语义块内,而非SubShader内。

  • 固定函数着色器
    上面的两种Unity Shader形式都使用了可编程管线,而对一些比较老旧的设备,其GPU支持DirectX 7.0或OpenGL 1.5或OpenGL ES1.1),这时候我们就需要使用固定函数着色器来完成渲染,这些着色器往往只能完成一些非常简单的效果。固定函数着色器是定义在Pass语义块中的,且不需要定义在CGPROFGAMENDCG中,完全使用Shader Lab的语法。
一个简单的固定函数着色器
  • 选择哪种Shader形式
    1.如果与各种光源打交道,可以使用表面着色器,但需要担心它在移动平台的表现。
    2.如果光照数目非常少,或者需要自定义很多渲染效果,那么请选择顶点/片元着色器。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,639评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,277评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,221评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,474评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,570评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,816评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,957评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,718评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,176评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,511评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,646评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,322评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,934评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,755评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,987评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,358评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,514评论 2 348

推荐阅读更多精彩内容

  • 多元线性回归是想在简单线性回归的基础上,建立两个或者两个以上的解释变量与反应变量之间的关系。它的步骤和一元线性回归...
    何同尘阅读 1,445评论 0 0
  • 迷醉的是死亡般的吟笑 如刀割的撕裂 是灵魂爱上的缝合 把所有的不甘与龌龊 都藏在鲜艳的面子下面 然后欲望 自己点燃...
    湛蓝黑眼圈凡徒阅读 1,273评论 1 0