【Unity Shader入门精要 第3章】Unity Shader基础

ops/2025/2/12 4:34:37/

1. Unity提供的四种shader模板

  • Standard Surface Shader:unity自己创建的shader类型,提供了基本的光照处理逻辑,使用者不需要自己实现vertext/fragment着色器,只要指定光照模型,unity会自动编译生成对应的vertext/fragment
  • shader Unlit Shader:一个不含光照处理的基础的vertext/fragment shader
  • Image Effect Shader:用于屏幕后处理效果的基础模板
  • Compute Shader:一种特殊的shader文件,与渲染过程本身无关,主要是为了利用GPU强大的并行计算能力进行快速计算

2. Unity Shader是什么

unity shader就是对渲染流水线中可编程或可配置部分进行实际控制的文件,这里面包括了两个语言的概念

  • ShaderLab
    unity提供的,用于描述shader文件本身的一种语言,可以理解为这种语言是与Unity引擎交互的,用来通知Unity引擎这个shader是谁、都包含哪些内容
  • Cg/HLSL/GLSL
    三种用于编写着色器代码的语言,是相对于通过汇编直接与GPU交互而产生的更易于理解和编写的高级语言,可以理解为Unity用这部分语言的代码通知显卡如何真正进行渲染
    UnityShader中可以使用这三种语言中的任意一种,只需要在shader文件中指明使用的类型即可,为了描述方便,无论实际使用的是哪种语言,后面的文章中都会笼统称之为“CG代码段”

3. Unity Shader的基础结构

Shader "PathA/PathB/.../ShaderName_1"
{Properties {}SubShader{}SubShader{}...FallBack "PathC/PathD/.../ShaderName_2"
}

名字

字符串指定shader路径和名字
路径部分决定了在材质面板下拉框中shader所在的层级位置

属性

PropertyName("DisplayName", PropertyType) = DefaultValue
  • PropertyName:属性名
  • DisplayName:面板显示名
  • PropertyType:属性类型
  • DefaultValue:默认值

常用的属性类型可以分成三大类:

  • 基本数值类
    包括Int, Float, Range
    默认值为一个具体的数值
_IntPro("IntPro", Int) = 1
_FloatPro("FloatPro", Float) = 1.0
_RangePro("RangePro", Range(0.0, 1.0)) = 0.5
  • 矢量类
    包括Vector 和Color
    默认值为一个四维矢量
_VecPro("VecPro", Vector) = (0, 0, 0, 1)
_ColorPro("ColorPro", Color) = (1, 1, 1, 1)
  • 纹理类
    包括2D, 3D, Cube
    默认值为字符串 + 花括号
    字符串可以填内置的纹理名(如"White" “Black” "Gray"等)或空字符串
_Tex2D("Tex2D", 2D) = "White"{}
_Tex3D("Tex3D", 3D) = ""{}
_TexCube("TexCube", Cube) = ""{}

注意:Properties{}是ShaderLab的语义,其作用是通知unity引擎当前shader中有这些属性,需要unity在面板上显示出来可以编辑。但是如果在着色器中要使用的话,还需要在CG代码块中声明变量

4. SubShader

一个SubShader可以理解为一个渲染方案
每个UnityShader中可以有多个SubShader,但至少要有一个
Unity会从上往下依次查找当前平台支持的第一个SubShader使用
如果没有找到可以使用的SubShader,会使用FallBack指定的Shader

SubShader的基本结构

SubShader
{Tags{}[Render Setup]Pass{}Pass{}...
}

Tags

当前SubShader的渲染标签,可选项,如果设置了Tag,会应用于当前SubShader下的所有Pass

Tags{"Tag1Name" = "Tag1Value" "Tag2Name" = "Tag2Value" ...}
Tag说明示例
Queue指定渲染队列“Queue” = “Transparent”
RenderType指定着色器类型,其实并没有什么实际作用,可以用来筛选shader,可以自己任意指定“RenderType” = “Opaque”
DisableBatching是否关闭合批“DisableBatching” = “True”
ForceNoShadowCasting关闭阴影“ForceNoShadowCasting” = “True”
IgnoreProjector不受Projector影响,比如在做透明度检测时使用“IgnoreProjector” = “True”
CanUseSpriteAtlas用于sprite“CanUseSpriteAtlas” = “True”
PreviewType材质在面板中的预览类型“PreviewType” = “Plane”

Render Setup

状态设置,可选项,用于对渲染流水线中的各种可配置项进行配置,如果配置了状态,会应用于当前SubShader下的所有Pass,但会被单个Pass中的设置覆盖

配置项说明示例
Cull剔除模式Cull Back/Cull Front/Cull Off
ZTest深度测试类型ZTest Greater/ZTest Less/ZTest Equal/ZTest GEqual/ZTest LEqual/ZTest NotEqual/ZTest Always
ZWrite深度写入ZWrite Off/ ZWrite On
Blend透明度混合因子Blend SrcAlpha OneMinusSrcAlpha
BlendOp透明度混合操作模式BlendOp Add

5. Pass

一个Pass对应着一个完整的渲染流程,当一个SubShader中配置了N个Pass时,就代表在这种渲染方案中,需要进行N遍渲染才能得到最终的渲染效果

Pass的基本结构

Pass
{Name ""Tags{}[Render Setup][CGCode]
}

Name

可以为Pass指定名字,方便在其他shader中使用之前已经写好的pass
在跨shader使用Pass的时候,需要通过shader名 + “/” + pass名的方式指定要使用的Pass
Pass的名字会被Unity转化为大写,因此在使用的时候,指定的Pass名字也要用大写,如“PathA/PathB/ShaderA/PASS_1”

Tags

当前Pass的渲染标签,Pass可以使用的Tag与SubShader使用的Tag不同,不会覆盖SubShader的标签,只是补充

Tag说明示例
LightMode指定渲染路径以及在渲染路径中的角色“LightMode” = “ForwardBase”
RequireOptions指定满足条件时才使用Pass,值为空格或分开的字符串“RequireOptions” = “SoftVegetation”

Render Setup

状态设置,可选项,对当前Pass的渲染流水线配置做单独针对性设置,会覆盖SubShader中的同类设置。可设置的内容也与上文SubShader中一样。

CG代码段

XXPROGRAM
#pragma vertex vertFunc
#pragma fragment fragFunc
#pragma ...
...fixed4 _ColorPro;
...struct a2v 
{...
};
struct v2f 
{...
};
...v2f vertFunc(a2v _input) 
{v2f _output;...return _output;
}...fixed4 fragFunc(v2f _input)
{...return (1, 1, 1, 1)
}ENDXX
  • 通过 XXPROGRAM 开启CG代码段,其中XX代表使用的语言,如CGPROGRAM,HLSLPROGRAM
  • 通过ENDXX关闭CG代码段,其中XX代表使用的语言,如ENDCG
  • 通过#pragma … 指定编译指令,如 #pragma vertext vertFunc 指定顶点着色器为verFunc,#pragma fragment fragFunc指定片元着色器为fragFunc
  • 通过类型和变量名声明变量,如果要声明的变量是使用Properties中定义的属性的值,则声明的变量名需要与Properties中定义的属性名一样,变量类型也需要跟属性的类型对应, 如 fixed4 _ColorPro; 就是声明了 _ColorPro 变量,且使用了上文Properties中定义的_ColorPro属性值
  • 通过struct定义自定义结构 实现定义的顶点着色器和片元着色器,如果要加入可选着色器
  • 也可以在CG代码段中加入可选着色器,与顶点/片元着色器方式一样

后面章节中会对CG代码段内的内容做更详细的介绍

6. 表面着色器

与普通的顶点/片元着色器不同,表面着色器直接在SubShader中定义(而非Pass中),也就是直接在SubShader中添加CG代码段
表面着色器除了指定着色器类型和名字外,还需要指定使用的光照模型,如 #pragma surface surfaceFunc Lambert 就是制定了表面着色器名字为surfaceFunc,且使用的光照模型为Lambert

表面着色器会被unity自动编译成普通的顶点/片元着色器,因此不需要返回值

SubSader
{Tags{"Queue" = "Transparent"}CGPROGRAM#pragma surface surfaceFunc Lambert;struct Input{float4 color : COLOR;}void surfaceFunc(Input _input, inout SurfaceOutput o){o.Albedo = 1;}ENDCG
}

http://www.ppmy.cn/ops/30333.html

相关文章

Mac好用又好看的终端iTerm2 + oh-my-zsh

Mac好用又好看的终端iTerm2 1. iTerm2的下载安装2. oh-my-zsh的安装2.1 官网安装方式2.2 国内镜像源安装方式 3. oh-my-zsh配置3.1 存放主题的路径3.2 存放插件的路径3.3 配置文件路径 1. iTerm2的下载安装 官网下载: iTerm2 2. oh-my-zsh的安装 oh-my-zsh是一…

[方法] Unity 实现仿《原神》第三人称跟随相机 v1.0

参考网址:【Unity中文课堂】RPG战斗系统Plus 在Unity游戏引擎中,实现类似《原神》的第三人称跟随相机并非易事,但幸运的是,Unity为我们提供了强大的工具集,其中Cinemachine插件便是实现这一目标的重要工具。Cinemachi…

【C++】适配器模式

文章目录 前言 1. 适配器的介绍2. 仿函数2.1 sort函数的模板参数2.2 priority_queue类的模板参数 3. priority_queue模拟实现3. stack & queue 模拟实现3.1 deque的介绍3.2 deque的优点与缺陷3.3 STL标准库中对于stack和queue的模拟实现 前言 C中的适配器是一种设计模式&am…

OpenResty 操作 Redis 和 MySQL

OpenResty 是一个基于 Nginx 的 Web 开发平台,它通过内置的方式集成了 LuaJIT,并内置了很多常用的第三方 Nginx 模块,使得开发人员可以使用 Lua 脚本来扩展 Nginx 的功能,这样就使得 OpenResty 可以非常方便地操作 Redis 和 MySQL…

在vue3项目中设置错误路径的统一跳转

在我们前端开发过程中,如果,访问到了错误的或者不存在的路径,那么会直接出现空白。在一个完整的项目中,应该给用户一些友好的提示,显示他访问到了错误的页面。 我们可以专门的创建一个错误界面的.vue文件,…

暴雨服务器引领信创算力新潮流

去年大模型的空前发展,人工智能也终于迎来了属于自己的“文艺复兴”,众多的模型相继发布,继而催生了整个行业对于智能算力需求的激增。 市场需求与技术驱动仿佛现实世界的左右脚,催动着世界文明的齿轮向前滚动。在全球经济角逐日…

Java_从入门到JavaEE_07

一、数组的排序(冒泡排序) 原理: 从下标“0”开始,相邻两个元素依次进行比较,每次找出最大的往后移动。 规律:N个数字来排队,两两相比小靠前,外层循环N-1,内层循环N-1-i…

React 之 Suspense

Suspense Suspense 组件我们并不陌生,中文名可以理解为暂停or悬停 , 在 React16 中我们通常在路由懒加载中配合 Lazy 组件一起使用 ,当然这也是官方早起版本推荐的唯一用法。 那它暂停了什么? 进行异步网络请求,然后再拿到请求…