首页 > 其他分享 >第三章 Unity Shader概述

第三章 Unity Shader概述

时间:2023-06-22 23:23:54浏览次数:31  
标签:SubShader 第三章 Tags Shader Unity Pass 着色器

第三章 Unity Shader概述

目录

Shader和材质

Shader的创建

  • 标准表面着色器(Standard Surface Shader): 会产生一个包含了标准光照模型的表面着色器模板
  • 无光照着色器(Unlit Shader): 会产生一个不包含光照(但包含雾效)的基本的顶点/片元着色器
  • 图像效果着色器(Image Effect Shader): 为我们实现各种屏幕后处理效果提供了一个基本模板
  • 计算着色器(Compute Shader): 会产生一种特殊的Shader文件,这类Shader旨在利用GPU的并行性来进行一些与常规渲染流水线无关的计算。
    Shader不能脱离材质,单独的shader无法发挥作用。在材质的最上方,我们可以选择材质的Shader。

Shader的属性

ShaderLab

Unity Shader是Unity为开发者提供的高层级的渲染抽象层,所有的Unity Shader都是使用ShaderLab来编写的。

一个Unity Shader的基本结构如下

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

Properties 语句块中定义了着色器所需的各种属性,这些属性将会出现在材质面板中

Unity Shader的结构

1. 名字

我们定义Shader叫做NewSurfaceShader

Shader "Custom/NewSurfaceShader"

则可以在Shader中找到

2. 属性

Properties
    {
    	//格式:Name ("display name", PropertyType) = DefaultValue
        _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
    }

在Shader中如上编写,则检查器中会有相应改变。

Property支持的数据类型

属性类型 定义语法 例子
Int number _Int ("Int", Int) = 2
Float number _Float ("Float", Float) = 1.5
Range(min, max) number _Range("Range", Range(0.0, 5.0)) = 3.0
Color (number,number,number,number) _Color ("Color", Color) = (1,1,1,1)
Vector (number,number,number,number) _Vector ("Vector", Vector) = (2, 3, 6, 1)
2D "defaulttexture" {} _2D ("2D", 2D) = "" {}
Cube "defaulttexture" {} _Cube ("Cube", Cube) = "white" {}
3D "defaulttexture" {} _3D ("3D", 3D) = "black" {}

3. SubShader

当Unity需要加载Unity Shader时,Unity会扫描所有的SubShader 语义块,然后选择第一个能够在目标平台上运行的SubShader 。如果都不支持的话,Unity就会使用Fallback 语义指定的Unity Shader。
SubShader主要用来适配不同的显卡,我们在性能较强的显卡上用复杂度较高的SubShader,在性能较弱的显卡上用复杂度较低的SubShader。
SubShader的定义

SubShader {
    // 可选的
    [Tags]

    // 可选的
        [RenderSetup]

	//每个Pass定义了一个完整的渲染过程
    Pass {
    }
    // Other Passes
}
  • 状态设置
    常见的渲染选项
状态名称 设置指令 解释
Cull Cull Back / Front/ Off 设置剔除模式:剔除背面/正面/关闭剔除
ZTest ZTest Less Greater/ LEqual/ GEqual/ Equal/ NotEqual/ Always 设置深度测试时使用的函数
ZWrite ZWrite On/Off 开启/关闭深度写入
Blend Blend SrcFactor DstFactor 开启并设置混合模式
  • 标签
    标签结构如下
Tags { "TagName1" = "Value1" "TagName2" = "Value2" }

支持的标签

标签类型 说明 例子
Queue 控制渲染顺序,指定该物体属于哪一个渲染队列,通过这种方式可以保证所有的透明物体可以在所有不透明物体后面被渲染(详见第8章),我们也可以自定义使用的渲染队列来控制物体的渲染顺序 Tags { "Queue" = "Transparent" }
RenderType 对着色器进行分类,例如这是一个不透明的着色器,或是一个透明的着色器等。这可以被用于着色器替换(Shader Replacement)功能 Tags { "RenderType" = "Opaque" }
DisableBatching 一些SubShader 在使用Unity的批处理功能时会出现问题,例如使用了模型空间下的坐标进行顶点动画(详见11.3节)。这时可以通过该标签来直接指明是否对该SubShader 使用批处理 Tags { "DisableBatching" = "True" }
ForceNoShadowCasting 控制使用该SubShader 的物体是否会投射阴影(详见8.4节) Tags { "ForceNoShadowCasting" = "True" }
IgnoreProjector 如果该标签值为“True”,那么使用该SubShader 的物体将不会受Projector的影响。通常用于半透明物体 Tags { "IgnoreProjector" = "True" }
CanUseSpriteAtlas 当该SubShader 是用于精灵(sprites)时,将该标签设为“False” Tags { "CanUseSpriteAtlas" = "False" }
PreviewType 指明材质面板将如何预览该材质。默认情况下,材质将显示为一个球形,我们可以通过把该标签的值设为“Plane”“SkyBox”来改变预览类型 Tags { "PreviewType" = "Plane" }
  • pass语义块
    pass语义块包含的代码如下
Pass { 
    [Name] //定义pass的名称
    [Tags] 
    [RenderSetup] 
    // Other code
}

我们可以用UsePass方法调用其他Shader中的pass

UsePass "OtherShader/MyPass"

其次,我们可以对Pass 设置渲染状态。SubShader 的状态设置同样适用于Pass

Pass 同样可以设置标签,但它的标签不同于SubShader 的标签。这些标签也是用于告诉渲染引擎我们希望怎样来渲染该物体。

标 签 类 型 说 明 例 子
LightMode 定义该Pass在Unity的渲染流水线中的角色 Tags { "LightMode" = "ForwardBase" }
RequireOptions 用于指定当满足某些条件时才渲染该Pass,它的值是一个由空格分隔的字符串。目前,Unity支持的选项有:SoftVegetation。在后面的版本中,可能会增加更多的选项 Tags { "RequireOptions" = "SoftVegetation" }
  • fallback
    如果所有的SubShader都不能起作用,那么就会调用fallback,代码如下
Fallback "name"
// 或者
Fallback Off

Shader的格式

表面着色器

表面着色器本质是和顶点/片元着色器是一样的,但是代码较为简单。也就是说,Unity会将一个表面着色器转换为一个顶点/片元着色器。
在表面着色器中,Unity会为我们处理很多光照细节,这些不用我们费心。
代码示例如下:

Shader "Custom/Simple Surface Shader" {
    SubShader {
        Tags { "RenderType" = "Opaque" }
        CGPROGRAM
        #pragma surface surf Lambert
        struct Input {
            float4 color : COLOR;
        };
        void surf (Input IN, inout SurfaceOutput o) {
            o.Albedo = 1;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

从上述程序中可以看出,表面着色器被定义在SubShader 语义块(而非Pass 语义块)中的CGPROGRAM 和ENDCG 之间。原因是,表面着色器不需要开发者关心使用多少个Pass、每个Pass如何渲染等问题,Unity会在背后为我们做好这些事情.

顶点/片元着色器

顶点/片元着色器更复杂,也更加灵活。
代码示例如下:

Shader "Custom/Simple VertexFragment Shader" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            float4 vert(float4 v : POSITION) : SV_POSITION {
                return mul (UNITY_MATRIX_MVP, v);
            }

            fixed4 frag() : SV_Target {
                return fixed4(1.0,0.0,0.0,1.0);
            }

            ENDCG
        }
    }
}

和表面着色器类似,顶点/片元着色器的代码也需要定义在CGPROGRAM 和ENDCG 之间,但不同的是,顶点/片元着色器是写在Pass 语义块内,而非SubShader 内的。原因是,我们需要自己定义每个Pass需要使用的Shader代码。虽然我们可能需要编写更多的代码,但带来的好处是灵活性很高。更重要的是,我们可以控制渲染的实现细节。同样,这里的CGPROGRAM 和ENDCG 之间的代码也是使用Cg/HLSL编写的。

固定函数着色器

对于一些比较旧的设备,他们不支持可编程管线着色器,这个时候就要用固定函数着色器。
示例代码如下:

Shader "Tutorial/Basic" {
    Properties {
        _Color ("Main Color", Color) = (1,0.5,0.5,1)
    }
    SubShader {
            Pass {
            Material {
                Diffuse [_Color]
            }
            Lighting On
        }
    }
}

着色器的选择

  • 除非你有非常明确的需求必须要使用固定函数着色器,例如需要在非常旧的设备上运行你的游戏(这些设备非常少见),否则请使用可编程管线的着色器,即表面着色器或顶点/片元着色器。
  • 如果你想和各种光源打交道,你可能更喜欢使用表面着色器,但需要小心它在移动平台的性能表现。
  • 如果你需要使用的光照数目非常少,例如只有一个平行光,那么使用顶点/片元着色器是一个更好的选择。
  • 最重要的是,如果你有很多自定义的渲染效果,那么请选择顶点/片元着色器。

标签:SubShader,第三章,Tags,Shader,Unity,Pass,着色器
From: https://www.cnblogs.com/anchuan114/p/17498536.html

相关文章

  • 关于我的Shader学习笔记
    由于发布的博客是笔记性质,肯定会在一些方面描述的不够详细。如果对于我的笔记有什么疑问,欢迎私信我提问!本笔记参考书籍:《UnityShader入门精要》冯乐乐著《3D游戏与计算机图形学中的数学方法》《Introductionto3DGameProgrammingwithDir......
  • unity物理系统简介
               FT=MV  FT:冲量  MV:动量   F:物体所受的力 T:力所持续的时间  M:物体的质量  V:速度                          铰链装在哪个轴,锚点参数......
  • visual studio 2022 community 多行编辑
    Alt+鼠标选择Alt+Shift+方向键Ctrl+Alt+鼠标选择Alt+Shift+;......
  • Unity3D:模拟器视图
    推荐:将NSDT场景编辑器加入你的3D工具链3D工具集:NSDT简石数字孪生模拟器视图“模拟器”视图在模拟的移动设备上显示应用程序。使用它来查看应用程序与该设备的屏幕形状、分辨率和方向的显示方式。模拟器视图的屏幕截图使用模拟器视图若要打开模拟器视图,请执行下列操作之一:......
  • Unity 关闭运行自己的exe,结束进程
    ///<summary>///退出程序///</summary>voidQuitProcedure(){#ifUNITY_EDITORUnityEditor.EditorApplication.isPlaying=false;#elseApplication.Quit();#endif}usingUnityEngine;publicclassCloseExe:MonoB......
  • 第三章 流水线技术
    3.1流水线的基本概念3.1.1什么是流水线流水线技术把一个重复的过程分解为若干个子过程,每个子过程由专门的功能部件来实现。把多个处理过程在时间上错开,依次通过各功能段,这样,每个子过程就可以与其他的子过程并行进行。流水线中的每个子过程及其功能部件称为流水线的级或段,段与......
  • 复习笔记-Unity
    泛型与Object区别Object是所有类型的基类,泛型是一种数据类型,将类型参数化达到代码复用提高软件开发效率泛型不用装箱拆箱,泛型是替换,将泛型参数替换成具体的类型,并且不需要强制类型转换,并且编译时自动检查类型安全,避免隐性的类型转换异常。Toggle与Button监听事件:Toggle:On......
  • unity发布后GPU占用过高
    发布后显示GPU占用98%,太夸张了吧同工程哪怕是空场景也是占用很高,除非新建工程对比很久才发现,是垂直同步的问题,场景质量为最低的时候,不开垂直同步反而增大了性能消耗,包括CPUhttps://zhuanlan.zhihu.com/p/453296774......
  • Unity添加键盘控制代码
    publicclassArrowControl:MonoBehaviour{publicfloatmoveSpeed=5f;//实例化两个Cube并赋予初始位置//cube1=Instantiate(cubePrefab,newVector3(-2f,0.5f,0f),Quaternion.identity);//cube2=Instantiate(cubePrefab,newVector3(2f,0.......
  • Unity:Gizmos 菜单
    推荐:将NSDT场景编辑器加入你的3D工具链3D工具集:NSDT简石数字孪生Gizmos菜单Scene视图和Game视图都有 Gizmos 菜单。单击Scene视图或Game视图的工具栏中的 Gizmos 按钮,即可访问 Gizmos 菜单。“场景”视图中的“辅助图标”按钮“游戏”视图中的“辅助图标”按钮......