shader入门精要读书笔记05 Unityshader基础

终于到第三章了,Unity shader概述

一、材质 与 unity shader

物体的渲染是由材质和unity shader一起工作来控制的。
我们需要创建一个材质,
再创建一个Unity shader ,并把shader赋值给材质。
再把材质赋值给需要渲染的对象。
再在材质面板中调整unity shader的属性,用来达到我们满意的效果。

unity shader中定义了渲染所需要的各种代码(顶点、片元着色器),一些属性(使用哪些纹理),指令(渲染和标签设置)。
而材质允许我们调节这些属性,并赋值给我们最终需要渲染的模型。

1.unity中材质(Material)

模型上组件(Mesh Render)中赋值Materials。
后可以在material资源中调节渲染参数。

2.Unity Shader(注意Unity shader与 渲染管线 shader区别)

Unity shader分为4种(Standard Surface Shader(包含标准光照模型,使用Unity5中基于物理的渲染方法)、Unlit Shader(产生一个不包含光照但包含雾效的基本顶点/片元着色器)、Image Effect Shader(为我们实现各种屏幕后处理效果提供基本模板)、Compute Shader(特殊的Shader文件))。

我们基础学习大多使用Unlit Shader。

shader 面板介绍:
在这里插入图片描述

Default Maps : 描述Unity Shader使用的默认纹理
Surface Shader : 是否是一个表面着色器
Fixed Function Shader : 是否是一个固定函数着色器
投射阴影
渲染队列
LOD值
忽视投影
是否关闭批处理

属性列表

按钮 Show generated code: 打开文件显示Unity背后为该表面着色器生成的 顶点/片元着色器。

如果 unity shader 是一个固定函数着色器,那么其相应位置也会多一个 Show generated code 按钮,用来查看固定函数着色器生成的 顶点/片元着色器。

Compile and show code 按钮后方的下拉列表 让开发者检查Unity Shader针对不同图像编程接口最终编译成的Shader代码,我们通过代码来分析和优化着色器。

3.ShaderLab

Unity 内部为了方便学习,提供的一层高级层的渲染抽象层叫 Unity Shader,我们与这层抽象打招呼的语言就叫做 ShaderLab。

Unity中所有的 Unity Shader都是使用ShaderLab来编写的。
ShaderLab定义了一个材质需要的所有东西,而不仅仅是着色器代码。
ShaderLab使用了一些嵌套在花括号里的语义来描述Unity Shader文件结构。
其中包含许多渲染所需要的数据(例如 Properties语句块中定义了着色器所需要的各种属性,这些属性也会显示在材质面板中)

Unity Shader 基础结构(Unity在背后会根据使用的平台来把这些结构编译成真正的代码和Shader文件,而开发者只需要和Unity Shader打交道即可):

Shader "ShaderName"{
Properties{
		//属性
}
SubShader{
		//显卡A使用的子着色器
}
SubShader{
		//显卡B使用的子着色器
}
Fallback “VertexLit”
}

4.Unity Shader 结构
(1)名字
Shader “Custom/MyShader” { }
Unity shader 在面板中出现的 位置及名字
Shader/Custom/MyShader
(2)材质与Unity Shader之间的桥梁——属性(Properties)
properties的语义块定义:

Properties {
		Name(“display name”,PropertyType)= DefaultBValue
		Name(“display name”,PropertyType)= DefaultBValue
		//更多属性
}

声明的属性可以在材质中方便调整
当我们在Shader中进行访问时,使用的就是上面定义的名字。
默认类型有(举例):

Shader “Custom/ShaderLabProperties”{
	Properties{
	//Numbers and Sliders
	_Int ("Int",Int)=2
	_Float("Float",Float)=1.5
	_Range("Range",Range(0.0,5.0))=3.0
	//Color and Vectors
	_Color("Color",Color)=(1,1,1,1)
	_Vector("Vector",Vector)=(2,3,6,1)
	//Textures
	_2D("2D",2D)=""{}
	_3D("3D",3D)="black"{}
	_Cube("Cube",Cube)="white"{}
	}
	FallBack "Diffuse"
}

对于2D、3D、Cube,默认值是字符串加上一个花括号,
字符串是用来定义内置的纹理名称,花括号指定纹理属性(原来),后被移除,如果想实现类似功能,需要在顶点着色器中编写计算相应的纹理坐标的代码。

上面说的这些属性的定义仅仅是为了使之显示在材质面板中。
在Cg代码块中使用使用属性值时,需要通过脚本向Shader中传递这些属性。

(3)重量级成员: SubShader
一个Unity Shader文件可以包含多个SubShader文件,但至少要有一个。
当Unity加载一个Unity Shader时,会按顺序依次扫描SubShader语义块,然后选择第一个能够在目标平台上运行的SubShader。如果都不支持,Unity会选择Fallback语义指定的Unity Shader。
以上语义是因为不同显卡有不同的能力。在不同的显卡上定义不同的操作数,使不同性能的显卡有不同的显示画面。

SubShader中包含的定义通常如下

SubShader
{
		//可选的,定义标签设置
		[Tags]
		//可选的,状态设置
		[RenderSetup]
		Pass{}   //定义一次完整的渲染流程
		//Other Passes
}

每个pass定义的都是一次完整的渲染流程。
但是Pass过多会导致性能浪费。所以我们要尽量使用较小数目的Pass。

状态(RenderSetup)和标签(Tags)也可以定义在Pass中,
SubShader中
标签设置是特定的,与在Pass中的不同。
状态设置使用语法相同,
在SubShader中定义的,会适用于所有Pass。

状态设置:

31页表3.2 SubShader中标签设置是特定的,与在Pass中的不同,会适用于所有Pass。
例如要在 双面渲染中 我们想在第一个 Pass 中剔除正面对背面渲染,在第二个 Pass 中剔除背面对正面渲染,此时我们需要在Pass语块中单独进行上面的设置。

标签设置:

结构:

Tags{"TagName1"="Value1" "TagName2"="Value2"}

标签是一个键值对,它的键和值都是字符串类型。
这些键值对是SubShader与渲染引擎之间的沟通桥梁,它们用来告诉Unity引擎,我希望怎么样以及何时进行渲染这个对象。

类型:32页表3.3, 表中仅可在SubShader中声明,与Pass中的不同。

Pass块
语义结构:

Pass{
	[Name]   
	[Tags]
	[RenderSetup]
	//Other code
}

定义名称举例

 Name “MyPassName”

通过定义名称,我们可以使用ShaderLab中的UsePass命令来在其他Shader中调用此Pass,提高代码的复用性。
例如:

UsePass “MyShader/MYPASSNAME”				//需要全部更改成大写字母形式

定义设置标签

此标签与SubShader中的不同,此处是告诉引擎我们是希望怎样渲染引擎。标签类型详细见 33页表3.4。

定义渲染状态

与SubShader中的相同,除此之外我们还可以使用固定管线着色器命令。

另外两种Pass:
UsePass:使用其他Shader中的Pass。
GrabPass:此Pass负责抓取屏幕并将结果存储在一张纹理中,用于后续的Pass处理。

(3)Fallback
定义语义

Fallback  “name”
//或者
Fallback Off

//举例
Fallback “VertexLit”

为了确定每一个SubShader都不能使用时,有一个最低级的默认,如果有Off,那就是不需要使用SubShader了。
Fallback另外一个作用是会影响阴影的投射,Unity会在每个Unity Shader中寻找一个Pass来实现阴影的投射,正常情况,我们不需要单独设置,因为Fallback内置的shader包含了这个通用Pass,所以我们还是要尽可能地去正确设置Fallback。

(4)其他语义
CustomEditor语义来扩展编辑界面,自定义材质面板编辑界面。
Category对命令分组等等。

总结

所有的着色器代码都在SubShader语义块中,
表面着色器通常直接写在SubShader中,
顶点/片元/固定函数着色器通常写在 Pass 语块中。

1.表面着色器:
写在SubShader中,它是Unity自创的,有很多的背后封装,我们使用表面着色器时,Unity会浪费很大的资源代价转换成 顶点/片元着色器。所以它相对于 顶点/片元 更加方便,不需要我们具体的进行光照、法线等很多事情。
在很多光源时,多被使用,但你需要小心其在移动平台的表现。

2.顶点/片元着色器:
写在Pass中,相对于表面着色器灵活性更高,可以自己实现细节。
可以实现更多的渲染效果,适用于光源较少时。

以上三种着色器都是下面的格式(只是需要注意在不同位置):

CGPROGRAM
//中间写Cg/HLSL代码(Untiy封装后的,与正常的有些不同)。
ENDCG

3.固定函数着色器:
老旧设备不支持可编程管线着色器,所以只能使用固定函数着色器实现简单效果。也被定义在Pass中。
使用ShaderLab,而不是Cg/HLSL。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值