文章目录

  • 第二章 Unity中的Shader(着色器)的形态
    • 2.1 Unity通过ShaderLab来组织Shader
      • 2.1.1 关键字 Shader
    • 2.1.2 使用SubShader组织Shader的不同实现
    • 2.1.3 SubShader的重要标签
    • 2.1.4 SubShader中的Pass块
    • 2.1.5 Pass块的标签及其名字的意义
    • 2.1.6 使用FallBack保证Shader的广泛使用性\
  • 2.2 UnityShaderLab所支持的编程语言
  • 2.3 Unity中Shader的3种形态
    • 2.3.1 固定管线
    • 2.3.2 可编程的Shader
    • 2.3.3 ShaderLab的骄傲:Surface Shader
  • 2.4 Shader的数据接口:属性和uniform变量
    • 2.4.1 在Properties块中定义属性
    • 2.4.2 通过图形界面操作属性
    • 2.4.3 通过脚本操控属性
    • 2.4.4 矩阵:不能在属性块定义的变量
    • 2.4.5 在Cg代码中使用属性

第二章 Unity中的Shader(着色器)的形态

2.1 Unity通过ShaderLab来组织Shader

作为一款号称跨平台性最好的游戏开发引擎,Unity3D使用Mono这个开源的.NET来实现,对于要适应不同GPU的Shader来说,Unity使用自定义ShaderLab来组织Shader的内容,并会针对不同的平台进行编译。

2.1.1 关键字 Shader

Unity的Shader文件是通过Shader这个关键字开始的,用户可以像目录一样组织Shader的命名。Shader的文件名和引用名不必一样,举例如下:

Shader "FirstShader"{Properties{_MainTex("Base (RGB)", 2D) = "white"{}}SubShader{......}SubShader{......}FallBack "Diffuse"
}

2.1.2 使用SubShader组织Shader的不同实现

真正用于呈现渲染物体的内容是在SubShader中实现的。之所以使用SubShader,是为了能让开发者针对不同性能的显卡编写不同的Shader,因为现实中并不是每个人都用相同的显卡。由于显卡千差万别,为了能让用户编写的游戏最大化地在各种GPU上运行,尽可能的呈现出最好的效果,就用SubShader来组织具体的实现,使Unity在运行时会针对实际的运行环境,从上到下选出最优的SubShader实现来呈现开发者的作品。从理论上来说SubShader的数量是没有限制的,但实际操作中为了减少文件的大小,一般写两三个SubShader就可以了,即针对目前最流行的一代显卡写一个,针对老旧显卡写一个。

2.1.3 SubShader的重要标签

给SubShader添加标签(Tags{}块),其实这就是一系列指示牌,这些标签可以告诉Unity渲染引擎或者其他用户如何认证这个SubShader。下面代码是适用于SubShader的BuildIn类的Tags:

SubShader{
Tags{"Queue"="Geometry""RenderType"="Opaque""IgnoreProjector"="True"}
...
}

Queue就是队列的意思,在这里就是渲染队列的意思,表示希望Uniy引擎在什么时候渲染自己。Queue有5个可选值,它们是Background、Geometry、AlphaTest、Transparent和Overlay,分别对应数字1000、2000、2450、3000和4000。既然可以对应成数字,当然也可以把这些单词当做整型变量来看待,例如:
Tags{“Queue”=“Geometry+1234”}
当混合使用定义的Shader和Unity内置的Shader时,一定要尊重上面的单词和字母的对应关系,因为,unity的内置Shader就是按这个顺序来渲染的。
下面是RenderType标签,其常用的内置值有Opaque、Transparent、TransparentCutout、Background和overlay。这个标签在代替渲染做Post Effects时很重要,Unity内置的Image Effects就是要根据它来决定如何替代渲染。此外,如果想得到一张ZDepth和Normals的快照。一个正确的RenderType是必不可少的。
IgnoreProjector比较简单,值为True时,表示当前物体忽略Projector的影响。
我们还可以为SubShader添加自定义标签,例如:
Tags{“MyTag”=“Lucifer”}
这种做法一般会在做替代渲染时用到。

2.1.4 SubShader中的Pass块

SubShader包装了一个渲染方案,而这个方案是由一个个Pass块来执行的。SubShader可以包含多个Pass块,每一个Pass块都包含了渲染一个几何体的具体代码。

2.1.5 Pass块的标签及其名字的意义

Pass块内置的那些标签都是针对渲染路径的,告诉渲染引擎这个Pass应该在什么渲染路径下被渲染,这些先别着急,我们一点点的提到。
Pass块的Name一般用来引用此Pass。这意味着可以定义一个Pass块,然后在其它Shader的Pass块中多次引用它。例如下面代码:

Shader "SecondShader"{
Subshader{Pass{Name "XGS"Material{Diffuse(1,0.7,0.4,1)Ambient(1,0.7,0.4,1)}Lighting OnSetTextture[ _ ] { combine primary}}
}
}

这个Shader命名了一个Pass块,由于Unity的原因,命名时必须使用大写。下面这个Shader则通过名字应用了此Pass块:

Shader "ThirdShader"{
SubShader{Use "SecondShader/XGS"}
}

2.1.6 使用FallBack保证Shader的广泛使用性\

如果用户所有的SubShader都失败了,为了在用户的计算机上呈现设定的机制,一般会使用FallBack。FallBack是Unity自己预制的Shader实现,一般能够在所有的显卡上运行。我们在开发Shader的时候一般不使用FallBack,只有在实际发布应用时才会为了追求平台的最大适用性而加上。

2.2 UnityShaderLab所支持的编程语言

不说那么多,在unity中我们开发游戏用的是Shader,至于其它的我不会也不敢妄下猜测,有兴趣的话各位请自行百度吧

2.3 Unity中Shader的3种形态

2.3.1 固定管线

固定管线是在旧的GPU能力比较有限时,对Shader的约束比较高的一种形态。为了市场占有率,新一代的显卡仍对其有所选择的进行支持,但是在未来会逐步淘汰。在ShaderLab中,固定管线的形态、语法和NVIDIA的CgFX以及微软的FX文件比较类似。下面是固定管线的一个例子:

Shader "BaseForm_1"{Proteries{_Color ("Main Color", Color) = (1,1,1,0.5)_SpeColor("Spec Color", Color) = (1,1,1,1)_Emission("Emmisive Color", Color) = (0,0,0,0)_Shininess("Shininess", Range(0.01,1)) = 0.7_MainTex("Base (RGB)", 2D) = "white" {}}SubShader{Pass{Material{Diffuse [_Color]Amibent[_Color]Shininess[_Shininess]Specular[_SpecColor]Emission[_Emossion]
}Lighting OnSeparateSpecular OnSetTexture [_MainTex]{ConstantColor [_Color]Combine texture * primary DOUBLE, texture *constant}}}
}

固定管线的相关代码都必须处于一个Pass块中。这里我们先了解其大致形态,具体的我们在日后慢慢详细讲解。

2.3.2 可编程的Shader

如果你想自己处理照明,可以写Vertex+fragment Shader,这是Unity对可编程Shader的一种支持。下面是可编程Shader的一个例子:

Shader "FourthShader"{Properties {_MyTexture ("Texture (RGB)", 2D) = "white" {}_MyColor("Color of Object",Color)=(1,1,1,1)}SubShader {Tags{"Queue"="Geometry" "RenderType"="Opaque" "IgnoreProjector"="True"}pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 2.0#include "UnityCG.cginc"sampler2D _MyTexture;float4 _MyColor;struct v2f{float4 pos:SV_POSITION;};v2f vert(appdata_full v){v2f o;o.pos=UnityObjectToClipPos(v.vertex);return o;}float4 frag(v2f i):COLOR{return float4(1,1,1,1);}ENDCG}} FallBack "Diffuse"
}

2.3.3 ShaderLab的骄傲:Surface Shader

如果你想写一个程序能处理不同的照明、点光源、平行光、光照贴图等,又能够处理不同的阴影选项,还同时能在Unity的两个渲染路径(Forward和Deferred)下正常工作,是一件很复杂很烦人的事情。Unity通过Surface Shader把上面这一切复杂性包装了起来 。下面是这样一个Surface Shader的例子,其实也就是在编辑器中创建Shader的默认结果:

Shader "Custom/NewSurfaceShader"
{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}SubShader{Tags { "RenderType"="Opaque" }LOD 200CGPROGRAM// Physically based Standard lighting model, and enable shadows on all light types#pragma surface surf Standard fullforwardshadows// Use shader model 3.0 target, to get nicer looking lighting#pragma target 3.0sampler2D _MainTex;struct Input{float2 uv_MainTex;};half _Glossiness;half _Metallic;fixed4 _Color;// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.// #pragma instancing_options assumeuniformscalingUNITY_INSTANCING_BUFFER_START(Props)// put more per-instance properties hereUNITY_INSTANCING_BUFFER_END(Props)void surf (Input IN, inout SurfaceOutputStandard o){// Albedo comes from a texture tinted by colorfixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;o.Albedo = c.rgb;// Metallic and smoothness come from slider variableso.Metallic = _Metallic;o.Smoothness = _Glossiness;o.Alpha = c.a;}ENDCG}FallBack "Diffuse"
}

在Surface函数surf中,SurfaceOutput是一个包含描述一个物体表面渲染特征的结构,例如:
struct SurfaceOutput{
half3 Albedo;//颜色纹理
half3 Normal;//法线
half3 Emission;//自发光,不受照明影响
half Specular;//高光指数
half Gloss;//光泽度
half Alpha;//Alpha通道
};
Surface Shader最终会被编译为一个复杂的vertex+fragment Shader,不过通过Surface Shader我们所需要做的就是简单的调色,这个说法也许比较笼统,有基础的可以简单的做一下调试理解一下,是在不能理解以后的学习中我们在慢慢介绍如何调试,一下子想把所有的知识点搞明白是不太现实的,不求甚解此时是必须的。关于Surface Shader在以后我们会更详细的的说明。

2.4 Shader的数据接口:属性和uniform变量

如果我们想设定一个特定的值到Shader,即为了在实例化Shader为Material时,可以通过为属性赋值达到创建具体对象的目的,我们需要在Properties块中定义自己的属性。如果以上不能理解的话,随便找本unity3d入门的书,一般第一章就会讲解以上的操作,说白了就是在软件中进行拖拽就ok了。

2.4.1 在Properties块中定义属性

我们能够定义如下属性:
Properties{
_MyTexture (“Texture (RGB)”, 2D) = “white” {}//图片形式的属性
_MyColor(“Color of Object”, Color) = (1,1,1,1)//颜色属性
_MyCube(“Environment map”, Cube) = “white” {}//3D贴图,需要6张图片
_MyVector(“Vector”,vector) = (1,1,1,1)//4个元素的向量
_MyFloat(“Float value”, float) = 1.0//浮点小数
_MyRange(“Another type of float”,range(-13,14))=1.0//限定范围的浮点数
}

2.4.2 通过图形界面操作属性

在Properties块中定义了这些属性后,我们可以在编译器中通过图形界面来给他们赋值。

2.4.3 通过脚本操控属性

除了图形界面以外,还能够通过脚本来读取和写入定义的属性。下面是一个C#脚本对属性的读取操作:

public Material mat;
public Texture myPic;
public Color purple;
public Cubemap cube;
public Vector4 vec;
public float val_1;
public float val_2;void Update(){//对在Shader中定义的属性进行设置mat.SetTexture("_MyTexture", mypic);mat.SetColor("_MyColor",purple);mat.SetTexture("_MyCubr",Cube);mat.SetVector("_MyVector",vec);mat.SetFloat("_MyFloat",val_1)'mat.SetFloat("_MyRange",val_2);//对在Shader中定义的属性进行读取myPic = mat.GetTexture("_MyTexture");purple = mat.GetColor("_Mycolor");cube=(Cubemap)mat.GetTexture("Mycube");vec = mat.GetVector("_MyVector");val_1 = mat.GetFloat("_MyFloat");val_2 = mat.GetFloat("_MyRange");}

cube属性是3D贴图,是Texture2D贴图的子类,range属性则是一种限制了范围的float类型,本质和float一样。如果在脚本中进行操作的属性在Shader中不存在,那么Unity只会将此操作忽略,而不会报错

2.4.4 矩阵:不能在属性块定义的变量

矩阵目前是不能再Properties块中定义的,必须首先在Shader中声明它,然后通过脚本来进行读取和写入。下面是在一个Shader中对一个矩阵的声明:
uniformfloat4×4 myMatrix;
下面是在脚本中对该矩阵的读取和写入:
mat.SetMatrix(“myMatrix”,matrix);
matrix = mat.GetMatrix(“myMatrix”?

2.4.5 在Cg代码中使用属性

除了Unity的固定管线因为有其固定语法之外,在Properties块中定义的属性必须在代码中再声明一次才能被使用。它们在Cg代码中的声明方式如下:
sampler2D _MyTexture;
float4 _Mycolor;
samplerCUBE _MyCube;
float4 _MyVector;
float _MyFloat;
float _MyRange;
除了上面提到的这些类型的变量外,还可以使用half4、fixed4和half、fixed,这两种类型的变量在空间上比float4和float分别减少了一半和又一半,因此在精度问题不是很突兀的情况下可以使用它们略微提高性能。

第一篇 初识庐山真面目 ——Unity 3D Shader(2)相关推荐

  1. 第一篇 初识庐山真面目 ——Unity 3D Shader(4)

    文章目录 第四章 基本的光照模型 4.1 光源对物体照明的分类 4.1.1 间接照明 4.1.2 直接照明 4.2 照明的计算方式:光照模型 4.2.1 漫反射和Lambert 4.2.2 镜面高光和 ...

  2. 【Linux入门指北】第一篇 初识Linux

    目录 前言 一.Linux操作系统的发展历史 1.Linux操作系统的诞生 2.Linux操作系统的发展 1.自由软件基金会(FSF) 2.GPL协议 3.GUN工程 二.Linux的不同发行版本 1 ...

  3. 【C初阶】第一篇——初识C语言(万字篇,带你敲响C语言的大门)

    接受平凡,努力出众,承认普通,但拒绝沉沦于平庸.大家好,我是你们的老朋友,小KK.  满满的 ​前言 ​什么C语言? ​数据类型 ​变量和常量 ​定义变量的方法 ​变量的分类 ​变量的作用域和生命周期 ...

  4. HPM6750系列--第一篇 初识HPM6750

    一.目的 HPM6750系列--第二篇 搭建Ubuntu开发环境_coder.mark的博客-CSDN博客https://blog.csdn.net/tianizimark/article/detai ...

  5. STL 第一篇 初识STL

    STL 什么是STL STL组成--六大组件 组件一:容器 容器分类 组件二:空间配置器(alloctor) 组件三--算法 组件4--迭代器 什么是迭代器 常见的迭代器 组件五---仿函数 另名:函 ...

  6. 微软实习生日记 第一篇 初识微软

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本人有幸 ...

  7. spring el表达式解析_Spring之旅第一篇-初识Spring

    目录 一.概述 二.模块 三.动手创建 一.概述 只要用框架开发java,一定躲不过spring,Spring是一个轻量级的Java开源框架,存在的目的是用于构建轻量级的J2EE应用.Spring的核 ...

  8. Dialogue System for Unity文档中文对照版(简雨原创翻译)第一篇(我们开始仙剑demo的剧情)

         这篇文档本身有快300页,因为实在太多,所以不像前面的插件那样翻译的,很多地方直接用了机翻,因为文字量实在太大,如果翻译完全套,再加上讲解的话,估计要花几个月的时间,对于普通的程序来说,其实 ...

  9. 【Unity3D Shader编程】之五 圣诞夜篇 Unity中Shader的三种形态对比 混合操作合辑

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

最新文章

  1. [转].NET学习网站收集
  2. 能pingt通外部的Ip和dns,但上不了网络
  3. 七夕秀恩爱新姿势!这波操作我给十分!
  4. C++笔记-空指针加强、auto自动类型
  5. python学到哪知道baseline_Python NLTK学习6(创建词性标注器)
  6. Python模拟大整数乘法的小学竖式计算过程
  7. Youki的笔记本配置要求
  8. OOP 术语:Arguments(参量)和 Parameters(参数)的区别(转载)
  9. bootsect.exe linux,bootsect.exe
  10. 【UWA 学堂】部分渲染课程的调价通知
  11. 数字图像处理-直方图均衡化,直方图规定化
  12. 设计一个时间片轮转调度算法实现处理机调度的程序,具体内容如下
  13. 产品经理,设计师,前端工程师必备的绘图工具(原型图,思维导图,UML,流程图,架构图)
  14. 计算标准偏差c语言,C ++程序计算标准偏差
  15. 透明网桥对数据帧的处理方式
  16. Java的依赖对象是什么意思_面向对象编程依赖注入详解
  17. 计算机视觉 响应_视觉响应式布局的自动化测试
  18. 80x86 汇编语言,大写变小写,小写变大写,数字原样输出
  19. [luogu P4230]连环病原体
  20. 有没有什么好的可以做读书笔记的APP推荐?

热门文章

  1. 关于 TEST EAX,EAX
  2. 记一次springboot+mybatis事务无效的处理
  3. Unity 3D 完成地形凹陷、水面、成品树
  4. 跟我学习如何搭建直播页面-直播知识体会~(1)
  5. DWORD是什么意思?
  6. Python之路 | 骰子游戏和最大数
  7. linux栈溢出检测原理,操作系统栈溢出检测之ucosII篇
  8. 【数论:组合数学】卢卡斯定理
  9. 基于Qt的仿酷狗音乐播放器设计(一)
  10. 网络安全态势感知及防御控制系统操作