找回密码
 立即注册
查看: 336|回复: 0

第三章 Unity Shader基础

[复制链接]
发表于 2022-7-19 08:50 | 显示全部楼层 |阅读模式
1.Unity Shader概述

1.1 一对好兄弟:材质和Unity Shader

unity中需要配合使用材质(Material)和Unity Shader才能达到需要的效果。一个常见的流程是:
(1)创建一个材质;
(2)创建一个Unity Shader,并把它赋给上一步创建的材质;
(3)把材质赋给要渲染的对象;
(4)在材质面板中调整Unity Shader的属性,以得到满意的效果。
Unity Shader定义了渲染所需的各种代码(如顶点着色器和片元着色器)、属性(如使用哪些纹理)和指令(渲染和标签设置等),而材质则允许我们调节这些属性,并将其最终赋值给相应的模型。
1.2 Unity中的材质

要在 Unity 中绘制某物,必须提供描述其形状的信息以及描述其表面外观的信息。使用网格(Mesh)可描述形状,使用材质(Material)可描述表面的外观。材质包含着Shader对象。
1.3 Unity中的Shader

着色器程序,通常称为着色器,是在 GPU 上运行的程序。本质上是一个文本文件。必须和材质配合使用。
2. Unity Shader的基础:ShaderLab

什么是ShaderLab?
Unity Shader是Unity为开发者提供的高层级的渲染抽象层。在Unity中,所有的Unity Shader都是用ShaderLab来编写的。ShaderLab是Unity提供的编写Unity Shader的一种说明性语言。


一个Unity Shader的基本结构如下:
Shader "ShaderName"
{
    Properties {//属性 }

    SubShader {//显卡A使用的子着色器 }

    SubShader {//显卡B使用的子着色器}

        Fallback  "VertexLit"
} 3. Unity Shader的结构

3.1 给我们的Shader起个名字

每个Unity Shader第一行都需要通过Shader语义指定该Unity Shader的名字。例如:
Shader "Custom/MyShader" {}通过在字符串中添加(“/”),可以控制Unity Shader在材质面板中出现的位置。


3.2 材质和Unity Shader的桥梁:Properties

Properties语义块中包含了一系列属性(Property),这些属性将会出现在材质面板中。其中Name是Shader中调用需要的属性,Display name是出现在材质面板山的名字,PropertyType则是属性的类型。
Properties {
    Name ("Display name", PropertyType) = DefaultValue
    Name ("Display name", PropertyType) = DefaultValue
    //更多属性
}

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   
        // 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"{}
    }
    FallBack "Diffuse"
}3.3 重量级成员:SubShader

一个Unity Shader文件可以包含多个SubShader语义块,但最少要有一个。当Unity需要加载这个Unity Shader时,Unity会扫描所有的SubShader语义块,然后选择第一个能够在目标平台上运行的SubShader。如果都不支持的话,Unity就会使用Fallback语义指定的Unity Shader。这种做法是为了支持Unity在不同的显卡上执行不同的渲染操作。


SubShader中定义了一系列Pass以及可选的状态[RenderSetup]和标签[Tags]设置。一个Pass通道代表一个完整的渲染流程。所以Pass通道数目越少越好。
3.3.1 状态设置


状态设置的目的是为了设置渲染状态。渲染状态将会应用于目标SubShader下的所有的Pass通道,比如说各类测试的开关,合并模式的开关等。如果需要Pass通道差异化,则需要在Pass通道模块中进行单独的设置。
3.3.2 SubShader的标签
标签的结构如下:
Tags{"TagName1"="Value1" "TagName2"="Value2"}
状态设置是为了定义渲染状态,而标签设置是为了定义何时以及怎样渲染。


3.3.3 Pass语义块


我们可以定义名称,然后通过UsePass命令使用其它Shader中的Pass。
Usepass "MyShader/MYPASSNAME"由于Unity内部会把所有Pass的名称转换为大写,因此,使用UsePass命令时必须使用大写。
Pass通道同样可以设置标签和渲染状态:


除此之外,Unity Shader还支持一些特殊Pass:
Use Pass:可以用这个命令来赋值其他的Unity Shader中的Pass、
GrabPass:负责抓取屏幕并将结果存储在一张纹理中,以用于后续Pass的处理。
3.3.4 Fallback
紧跟在各个SubShader语义块后面,如果所有SubShader都不能运行,则使用这个默认Shader。


3.3.5 ShaderLab的其他语义
可以用CustomEditor语义来扩展编辑界面。
可以用Category来对UnityShader中的命令进行分组。
3.4 Unity的形式



3.4.1 表面着色器
表面着色器是Unity自己创造的一种着色器代码类型,但它的本质仍然是顶点着色器或者片元着色器,可以理解为Unity将表面着色器最终转化为了顶点/片元着色器。而表面着色器的意义在于为我们处理了很多光照细节。
表面着色器的代码定义是写在SubShader内的。


3.4.2 最聪明的孩子:顶点/片元着色器


顶点/片元着色器的代码定义是写在Pass通道内的,而非SubShader,原因是为了更高的灵活性,我们需要在每个Pass通道中自定义代码。
CG/HLSL语言。
3.4.3 被抛弃的角落:固定函数着色器
上面两种Unity Shader形式都使用了可编程管线。一些较旧的设备不支持可编程管线着色器。已逐渐被抛弃使用。
3.4.4 Unity Shader的选择
如果要和各种光源打交道,那么使用表面着色器最方便,但是要注意性能优化问题,尤其是在移动平台。
如果需要的光照数目很少,那么请使用顶点/片元着色器。
如果有很多自定义的渲染效果,那么请选择顶点/片元着色器。
3.5 答疑解惑

3.5.1 Unity Shader和CG/HLSL之间的关系
Unity Shader是用Shader Lab语言编写的,但对于表面着色器和顶点/片元着色器,我们可以在ShaderLab内部嵌套CG/HLSL语言来编写着色器代码。
通常CG代码块是位于Pass语义块内部的,如下所示:


3.5.2 GLSL
Unity Shader同样支持用GLSL进行编写,但是编写的产品则只能上架支持OpenGL的平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 07:16 , Processed in 0.089261 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表