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

2023-11-03

Unity系列文章目录

前言

通过前面的学习内容我们已经知道,Shader 并不是什么神秘的东西,它们其实就是渲染流水
线中的某些特定阶段,如顶点着色器阶段、片元着色器阶段等。
在没有Unity 这类编辑器的情况下,如果我们想要对某个模型设置渲染状态,可能需要类似
下面的代码:

// 初始化渲染设置
void Initialization() {
// 从硬盘上加载顶点着色器的代码
string vertexShaderCode = LoadShaderFromFile(VertexShader.shader);
// 从硬盘上加载片元着色器的代码
string fragmentShaderCode = LoadShaderFromFile(FragmentShader.shader);
// 把顶点着色器加载到GPU 中
LoadVertexShaderFromString(vertexShaderCode);
// 把片元着色器加载到GPU 中
LoadFragmentShaderFromString(fragmentShaderCode);
// 设置名为"vertexPosition"的属性的输入,即模型顶点坐标
SetVertexShaderProperty("vertexPosition", vertices);
// 设置名为"MainTex"的属性的输入,someTexture 是某张已加载的纹理
SetVertexShaderProperty("MainTex", someTexture);
// 设置名为"MVP"的属性的输入,MVP 是之前由开发者计算好的变换矩阵
SetVertexShaderProperty("MVP", MVP);
// 关闭混合
Disable(Blend);
// 设置深度测试
Enable(ZTest);
SetZTestFunction(LessOrEqual);
// 其他设置}
// 每一帧进行渲染
void OnRendering() {
// 调用渲染命令
DrawCall();
// 当涉及多种渲染设置时,我们可能还需要在这里改变各种渲染设置
...
}

VertexShader.shader:

// 输入:顶点位置、纹理、MVP 变换矩阵
in float3 vertexPosition;
in sampler2D MainTex;
in Matrix4x4 MVP;
// 输出:顶点经过MVP 变换后的位置
out float4 position;
void main() {
// 使用MVP 对模型顶点坐标进行变换
position = MVP * vertexPosition;
}

FragmentShader.shader:

// 输入:VertexShader 输出的position、经过光栅化程序插值后的该片元对应的position
in float4 position;
// 输出:该片元的颜色值
out float4 fragColor;
void main() {
// 将片元颜色设为白色
fragColor = float4(1.0, 1.0, 1.0, 1.0);
}

上述伪代码仅仅是简化后的版本,当渲染的模型数目、需要调整的着色器属性不断增多时,
上述过程将变得更加复杂和冗长。而且,当涉及透明物体等多物体的渲染时,如果没有编辑器的
帮助,我们要非常小心如渲染顺序等问题。
Unity 的出现改善了上面的状况。它提供了一个地方能够让开发者更加轻松地管理着色器代
码以及渲染设置(如开启/关闭混合、深度测试、设置渲染顺序等),而不需要像上面的伪代码一
样,管理多个文件和函数等。Unity 提供的这个“方便的地方”,就是Unity Shader。

一、Unity Shader 概述

那么如何充分利用Unity Shader 来为我们的游戏增光添彩呢?
3.1.1 一对好兄弟:材质和Unity Shader
总体来说,在Unity 中我们需要配合使用材质(Material)和Unity Shader 才能达到需要的效
果。一个最常见的流程是:
(1)创建一个材质;
(2)创建一个Unity Shader,并把它赋给上一步中创建的材质;
(3)把材质赋给要渲染的对象;
(4)在材质面板中调整Unity Shader 的属性,以得到满意的效果。
图3.1 显示了Unity Shader 和材质是如何一起工作来控制物体的渲染的。
在这里插入图片描述
可以发现,Unity Shader 定义了渲染所需的各种代码(如顶点着色器和片元着色器)、属性(如
使用哪些纹理等)和指令(渲染和标签设置等),而材质则允许我们调节这些属性,并将其最终赋
给相应的模型。

二、使用步骤

1.3.1.2 Unity 中的材质

Unity 中的材质需要结合一个GameObject 的Mesh 或者Particle Systems 组件来工作。它决定
了我们的游戏对象看起来是什么样子的(这当然也需要Unity Shader 的配合)。
为了创建一个新的材质,我们可以在Unity 的菜单栏中选择Assets -> Create -> Material 来创
建,也可以直接在Project 视图中右击 -> Create -> Material 来创建。当创建了一个材质后,就可
以把它赋给一个对象。这可以通过把材质直接拖曳到Scene 视图中的对象上来实现,或者在该对
象的Mesh Renderer 组件中直接赋值,如图3.2 所示。
在Unity 5.x 版本中,默认情况下,一个新建的材质将使用Unity 内置的Standard Shader,这
是一种基于物理渲染的着色器,我们将在第18 章中讲到。
对于美术人员来说,材质是他们十分熟悉的一种事物。Unity 的材质和许多建模软件(如Cinema
4D、Maya 等)中提供的材质功能类似,它们都提供了一个面板来调整材质的各个参数。这种可视化
的方法使得开发者不再需要自行在代码中设置和改变渲染所需的各种参数,如图3.3 所示。
在这里插入图片描述

2.Unity 中的Shader

为了和前面通用的Shader 语义进行区分,我们把Unity 中的Shader 文件统称为Unity Shader。
这是因为,Unity Shader 和我们之前提及的渲染管线的Shader 有很大不同,我们会在3.6.2 节中进
行更加详细的解释。
为了创建一个新的Unity Shader,我们可以在Unity 的菜单栏中选择Assets -> Create -> Shader 来
创建,也可以直接在Project 视图中右击 -> Create -> Shader 来创建。在Unity 5.2 及以上版本中,Unity
一共提供了4 种Unity Shader 模板供我们选择—Standard Surface Shader,Unlit Shader,Image Effect
Shader 以及Compute Shader。其中,Standard Surface Shader 会产生一个包含了标准光照模型(使用了Unity 5 中新添加的基于物理的渲染方法,详见第18 章)的表面着色器模板,Unlit Shader 则会产生一
个不包含光照(但包含雾效)的基本的顶点/片元着色器,Image Effect Shader 则为我们实现各种屏幕
后处理效果(详见第12 章)提供了一个基本模板。最后,Compute Shader 会产生一种特殊的Shader
文件,这类Shader 旨在利用GPU 的并行性来进行一些与常规渲染流水线无关的计算,而这不在本书
的讨论范围内,读者可以在Unity 手册的Compute Shader 一文(http://docs.unity3d.com/Manual/
ComputeShaders.html)中找到更多的介绍。总体来说,Standard Surface Shader 为我们提供了典型的表
面着色器的实现方法,但本书的重点在于如何在Unity 中编写顶点/片元着色器,因此在后续的学习中,
我们通常会使用Unlit Shader 来生成一个基本的顶点/片元着色器模板。
一个单独的Unity Shader 是无法发挥任何作用的,它必须和材质结合起来,才能发生神奇的
“化学反应”!为此,我们可以在材质面板最上方的下拉菜单中选择需要使用的Unity Shader。当
选择完毕后,材质面板中就会出现该Unity Shader 可用的各种属性。这些属性可以是颜色、纹理、
浮点数、滑动条(限制了范围的浮点数)、向量等。当我们把材质赋给场景中的一个对象时,就可
以看到调整属性所发生的视觉变化。
Unity Shader 本质上就是一个文本文件。和Unity 中的很多外部文件类似,Unity Shader 也有
导入设置(Import Settings)面板,在Project 视图中选中某个Unity Shader 即可看到。在Unity 5.2
版本中,Unity Shader 的导入设置面板如图3.4 所示。
在该面板上,我们可以在Default Maps 中指定该Unity Shader 使用的默认纹理。当任何材质
第一次使用该Unity Shader 时,这些纹理就会自动被赋予到相应的属性上。在下方的面板中,Unity
会显示出和该Unity Shader 相关的信息,例如它是否是一个表面着色器(Surface Shader)、是否是
一个固定函数着色器(Fixed Function Shader)等,还有一些信息是和我们在Unity Shader 中的标
签设置(详见3.3.3 节)有关,例如是否会投射阴影、使用的渲染队列、LOD 值等。
对于表面着色器(详见3.4.1 节)来说,我们可以通过单击Show generated code 按钮来打开
一个新的文件,在该文件里将显示Unity 在背后为该表面着色器生成的顶点/片元着色器。这可以
方便我们对这些生成的代码进行修改(需要复制到一个新的Unity Shader 中才可保存)和研究。
同样地,如果该Unity Shader 是一个固定函数着色器,在Fixed function 的后面也会出现一个Show
generated code 按钮,来让我们查看该固定函数着色器生成的顶点/片元着色器。Compile and show
code 下拉列表可以让开发者检查该Unity Shader 针对不同图像编程接口(例如OpenGL、D3D9、
D3D11 等)最终编译成的Shader 代码,如图3.5 所示。直接单击该按钮可以查看生成的底层的汇
编指令。我们可以利用这些代码来分析和优化着色器。
在这里插入图片描述
除此之外,Unity Shader 的导入面板还可以方便地查看其使用的渲染队列(Render queue)、
是否关闭批处理(Disable batching)、属性列表(Properties)等信息。

3.Unity Shader 的基础:ShaderLab

“计算机科学中的任何问题都可以通过增加一层抽象来解决。”— 大卫·惠勒

学习和编写着色器的过程一直是一个学习曲线很陡峭的过程。通常情况下,为了自定义渲染
效果往往需要和很多文件和设置打交道,这些过程很容易消磨掉初学者的耐心。而且,一些细节
问题也往往需要开发者花费较多的时间去解决。
Unity 为了解决上述问题,为我们提供了一层抽象—Unity Shader。而我们和这层抽象打交
道的途径就是使用Unity 提供的一种专门为Unity Shader 服务的语言—ShaderLab。
什么是ShaderLab?
“ShaderLab is a friend you can afford.”—尼古拉斯·弗朗西斯(Nicholas Francis),Unity 前首
席运营官(COO)和联合创始人之一。
Unity Shader 是Unity 为开发者提供的高层级的渲染抽象层。图3.6 显示了这样的抽象。Unity
希望通过这种方式来让开发者更加轻松地控制渲染。
在这里插入图片描述
在Unity 中,所有的Unity Shader 都是使用ShaderLab 来编写的。ShaderLab 是Unity 提供的
编写Unity Shader 的一种说明性语言。它使用了一些嵌套在花括号内部的语义(syntax)来描述
一个Unity Shader 文件的结构。这些结构包含了许多渲染所需的数据,例如Properties 语句块中定
义了着色器所需的各种属性,这些属性将会出现在材质面板中。从设计上来说,ShaderLab 类似
于CgFX 和Direct3D Effects(.FX)语言,它们都定义了要显示一个材质所需的所有东西,而不仅
仅是着色器代码。
一个Unity Shader 的基础结构如下所示:

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

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

4.Unity Shader 的结构

在上一节的伪代码中我们见到了一些ShaderLab 的语义,如Properties、SubShader、Fallback
等。这些语义定义了Unity Shader 的结构,从而帮助Unity 分析该Unity Shader 文件,以便进行正
确的编译。在下面,我们会解释这些基础的语义含义和用法。
3.3.1 给我们的Shader 起个名字
每个Unity Shader 文件的第一行都需要通过Shader
语义来指定该Unity Shader 的名字。这个名字由一个字
符串来定义,例如“MyShader”。当为材质选择使用的
Unity Shader 时,这些名称就会出现在材质面板的下拉列
表里。通过在字符串中添加斜杠(“/”),可以控制Unity
Shader 在材质面板中出现的位置。例如:
Shader “Custom/MyShader” { }
那么这个Unity Shader 在材质面板中的位置就是:
Shader -> Custom -> MyShader,如图3.7 所示。
3.3.2 材质和Unity Shader 的桥梁:Properties
Properties 语义块中包含了一系列属性(property),
这些属性将会出现在材质面板中。
Properties 语义块的定义通常如下:

Properties {
Name ("display name", PropertyType) = DefaultValue
Name ("display name", PropertyType) = DefaultValue
// 更多属性
}

开发者们声明这些属性是为了在材质面板中能够方便地调整各种材质属性。如果我们需要在
Shader 中访问它们,就需要使用每个属性的名字(Name)。在Unity 中,这些属性的名字通常由
一个下划线开始。显示的名称(display name)则是出现在材质面板上的名字。我们需要为每个
属性指定它的类型(PropertyType),常见的属性类型如表3.1 所示。除此之外,我们还需要为每
个属性指定一个默认值,在我们第一次把该Unity Shader 赋给某个材质时,材质面板上显示的就
是这些默认值。

参考

Unity Shader入门精要
作者:冯乐乐

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity Shader入门精要第3 章 Unity Shader 基础 的相关文章

  • unity粒子特效附上贴图后播放动画

    转自 http jingyan baidu com article f96699bbb1a0d6894f3c1b77 html 参考 http www unitymanual com thread 2993 1 1 html dsign a
  • Unity WebGL错误集锦

    ips 0 Unity的PlayerSettings的otherSettings或者Publish Settings里面的Enable Exceptions里面选择Full StackTrace 可以在打出的包中的浏览器的webgl打印出错
  • Unity中loading页加载的实现

    首先创建一个Global cs 使用单例用于存储场景的名字 便于后续脚本的调用 此脚本不必挂载在游戏物体上 using UnityEngine using System Collections public class Global Mon
  • unity网络资源导入

    1 找到需要导入的文件 这里导入fbx格式 2 打开unity界面 在Asset目录下创建文件夹FBX 将需要导入的fbx预制体或整个文件夹拖入创建的FBX文件夹下 3 选中需要的fbx预制体并拖至场景中 4 双击定位到当前物体 5 找到需
  • c#获取cpu序列号

  • Unity-AR 简介

    Unity AR 简介 现有Unity AR Sdk ARKit 苹果推出的AR开发平台 ARCore Google 推出的增强现实 SDK ARFoundation ARFoundation是ARKit XR插件和ARCore XR插件
  • Unity中按钮检测鼠标状态

    改方法主要是用于按钮检测鼠标的进入 滑出 点击 抬起 长按 长按停止 1 先将下面这个脚本挂载到需要检测鼠标状态的按钮上 using System Collections using System Collections Generic u
  • Unity3d 插件 系列——DoTweenPro介绍(图文详细+案例)

    Unity3d 插件 系列 DoTweenPro介绍 图文详细 案例 前言 一 DoTweenPro简介 二 DoTweenPro安装 三 DoTweenPro主要组件 1 DoTweenAnimation 2 DoTweenPath 3
  • Unity中UI框架的使用1-添加面板、显示Loading页面

    其中BasePanel和Canvas都是挂在面板的预制物上的 1 导入我们的UI框架 本篇文章中有用的是两个UIPanelType NUIManager和NBasePanel 会放在文章最后供大家使用 2 先将我们做好的Panel设置成预制
  • unity后台加密时间锁

    前言 在做一些项目的时候 有些不良甲方在给完项目后会有不给尾款的情况 之前都是加一些水印啥的 感觉不是很方便 第一不美观 第二如果甲方给完尾款后还得重新打包去水印 然后又做过一个本地的时间锁 等到时间 程序直接退出 但是感觉还是不方便 有时
  • 【IMGUI】 各种辅助类 EditorGUIUtility、EditorUtility、GUIUtility、GUILayoutUtility

    EditorGUIUtility class in Editor 继承自 GUIUtility EditorGUI 的各种辅助程序 EditorGUIUtility currentViewWidth 我尝试打印了下这个值和position
  • Unity 键盘控制人物移动——之输入方式代码的编写

    键盘输入 控制人物移动 在我们制作游戏中最常见的需求之一就是使用键盘移动游戏角色 那么我们首先需要获取键盘输入 以下提供两种方法获取键盘 这里尽量通过截图解释让大家理解代码的含义 GetInput void FixedUpdate Move
  • unity: C#的Action Event Delegate的异同

    目录 一 Action 二 Event 三 Action和Event区别 四 Delegate 总结 Action Event Delegate的异同 前言 Action Event和Delegate都是C 语言中的重要概念 分别用于管理函
  • Unity打包WebGL的优化常用操作?

    1 贴图部分优化 如果贴图格式时2048 在不影响画面效果的情况下 改成1024或者5 12 还可以缩小包体 2 压缩和解压缩问题 WebGL打包的时候分三种压缩情况 gzip 比Brotli文件打 但打包快 http和https都支持 B
  • unity3d image组件不显示

    需要将UI组件放到画布下面
  • 【原神游戏开发日志1】缘起

    原神游戏开发日志1 缘起 版权声明 本文为 优梦创客 原创文章 您可以自由转载 但必须加入完整的版权声明 文章内容不得删减 修改 演绎 相关学习资源见文末 大家好 最近看到原神在TGA上频频获奖 作为一个14年经验的游戏开发行业的老兵 我就
  • Unity学习笔记

    一 旋转欧拉角 四元数 Vector3 rotate new Vector3 0 30 0 Quaternion quaternion Quaternion identity quaternion Quaternion Euler rota
  • Unity中URP下的指数雾

    文章目录 前言 一 指数雾 雾效因子 1 FOG EXP 2 FOG EXP2 二 MixFog 1 ComputeFogIntensity 雾效强度计算 2 lerp fogColor fragColor fogIntensity 雾效颜
  • U3D游戏开发中摇杆的制作(NGUI版)

    在PC端模拟摇杆 实现控制摇杆让玩家或者物体移动 以下是完整代码 using System Collections using System Collections Generic using UnityEngine public clas
  • 游戏开发中常见系统梳理之背包系统的实现一

    游戏中几乎都存在大大小小的背包系统 接下来我将讲述背包系统具体是如何实现的 完整源码 以下是使用unity NGUI实现 使用txt配置的方法 后续更新UGUI Json实现的背包系统敬请期待 背包中的物品我们常常将其制作成预设体 通过改变

随机推荐

  • 浅谈Python解释器的组成

    Python解释器是一个复杂的软件 它可以解释和执行Python代码 以下是Python解释器的主要组成部分 源代码词法分析器 Lexical Analyzer 这部分的任务是将输入的Python源代码分解成称为 tokens 的基础元素
  • Diffusion笔记

    一 Diffusion是什么 Diffusion 是一种去噪扩散模型 工作原理是对图像逐步施加噪点 直至图像被破坏变成完全的噪点 然后再逆向学习从全噪点还原为原始图像的过程 而 AI 所看到的是全是噪点的画面如何一点点变清晰直到变成一幅画
  • C++-Cmake指令:cmake_minimum_required

    命令格式 cmake minimum required VERSION
  • nginx禁用3DES和DES弱加密算法

    nginx禁用3DES和DES弱加密算法 项目背景 最近护网行动 收到漏洞报告 如下 漏洞名称 SSL TLS协议信息泄露漏洞 CVE 2016 2183 原理扫描 详细描述 TLS是安全传输层协议 用于在两个通信应用程序之间提供保密性和数
  • 创建第一个phpstorm项目(phpstorm+Apache)

    创建第一个phpstorm项目 1 点击新建项目 2 选择新建空项目 3 选择新建项目位置 由于要使用apache 所以项目一定要建在apache下的htdocs下 4 给项目命完名 5 再次确认文件位置是否正确 点击创建 6 为新创建的项
  • matplotlib刻度值使用科学记数法

    原本 plot 出的图 y 轴刻度值太多 0 想用科学记数法 去掉后面那些 0 效果 要设置 ax ticklabel format style sci scilimits 1 2 axis y 其中 style sci 指明用科学记数法
  • GoFrame 代码生成工具【gf】SQLite ORM映射报错: unknown driver “sqlite3“ (forgotten import?)

    1 环境 Windows10 golang1 7 GoFrame1 16 SQLite3 2 异常 执行 gf gen dao 生成代码时报错 unknown driver sqlite3 forgotten import 3 排查 官方文
  • EduCoder_web实训作业--播放视频

    第一关 B A C B AC 第二关
  • 【C++学习第七讲】简单变量(一)

    目录 简单变量 一 简单变量 1 变量名 2 整型 3 整型short int long和long long 面向对象编程 OOP 的本质是设计并扩展自己的数据类型 设计自己的数据类型就是让类型与数据匹配 如果正确做到了这一点 将会发现以后
  • 博客志第一天——判断一个整数N是否是完全平方数?

    关注博客园很久 今天是第一次写博客 先附上一个C题目 写一个函数判断一个整数是否为完全平方数 同时是否该数的各位数至少两个相同的数字 1 include
  • 期货开户要注意轻仓止损

    保持同一比例的仓位 比如说 每次做一手 赚了5次 然后有一次做了10手 亏了一次 那么 可能把前面赚的钱全亏回去 排除任何的主观预测 根据实际行情走势来操作 而不是根据自己的预测或是期望或是恐惧来操作 不能因为预测行情涨而买入 也不能因为预
  • 动态修改el-input样式;动态修改elmentUI元素样式;css变量

    场景 正常我们动态修改div元素的样式 使用 style和 class即可 但是我们想要动态修改element的组件样式时候 例如el input字体颜色 由于el input的样式嵌套很深 我们需要修改的实际是 el input inne
  • arxiv文章下载速度慢解决方法

    arxiv文章下载速度慢解决方法 一 arxiv网站作用 参考知乎链接 Arxiv是一个免费张贴和下载预印本的网站 最初用于高能物理和粒子物理学家之间的交流 如今已经发展到了物理学的各个领域 且延伸到了物理 数学 非线性科学 计算机科学 数
  • autoscan、aclocal、automake和autoconf区别【转】

    转自 https blog csdn net renhui1112 article details 96480535 autoscan 扫描源代码以搜寻普通的可移植性问题 比如检查编译器 库 头文件等 生成文件configure scan
  • Git-2-网络仓库使用

    本文内容介绍 需要连接到远程网络 并实现远程网络的同步 远程网络库最常见的是GitHub 是国外的服务器 用户最多 网络库中的资源最多 网络可能会不稳定 这里采用国内的网络仓库Gitee码云 使用中文界面 比较适合初学者使用 0 首先介绍下
  • 2023华数杯A题 隔热材料的结构优化控制研究(论文+代码)

    目录 问题一 问题2 问题3 离子群算法代码 Matlab 离子群算法代码 python
  • CTF学习-eric靶机练习:使用git tools获取敏感目录,提权

    Kali渗透测试 靶场练习eric 实验 Kali的IP 192 168 1 11 不同的机器配置不同 靶机IP 192 168 1 6 动态ip 操作步骤 靶机下载 https www vulnhub com entry sp eric
  • 【Windows10+wsl2+Ubuntu20.04】安装nvidia驱动问题

    使用windows命令行工具可以顺利查看nvidia smi 但在Ubuntu中执行命令行nvidia rmi后显示 Failed to initialize NVML GPU access blocked by the operating
  • [4G+5G专题-141]: 终端 - 测试仪表详解

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 123070605 目录 第1章 本章在
  • Unity Shader入门精要第3 章 Unity Shader 基础

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一 Unity Shader 概述 二 使用步骤 1 3 1 2 Unity 中的材质 2 Unity 中的Shader 3 Unity Shader 的基础 ShaderLa