Unity Shader简介

2023-10-27

Shader,中文名为着色器,对很多开发者来说它是一个神秘的存在,想学但是又不知道如何去学,或者学了一段时间发现Get不到它的点,始终感觉游离在外,无法开窍。

本文来讲下如何从零基础入门Shader,目的在于让初学Shader的程序或者美术可以快速进入这个丰富多彩的世界。

这里有unity学习交流小组点击可以直接加入,一起学习交流吧

一、 什么是Shader

Shader其实就是专门用来渲染图形的一种技术,通过shader,我们可以自定义显卡渲染画面的算法,使画面达到我们想要的效果。小到每一个像素点,大到整个屏幕,比如下面这两个游戏内比较常见的效果。

二、 Shader分类

顶点Shader(3D图形都是由一个个三角面片组成的,顶点Shader就是计算每个三角面片上的顶点,并为最终像素渲染做准备)。

像素Shader,顾名思义,就是以像素为单位,计算光照、颜色的一系列算法。

几个不同的图形API都有各自的Shader语言,在DirectX中,顶点shader叫做 Vertex Shader ,像素Shader叫做 Pixel Shader; 在OpenGL中,顶点Shader也叫做 Vertex Shader ,但像素Shader叫做 Fragment Shader,也就是我们常说的片断Shader或者片元Shader。

说白了,Shader其实就是一段代码,这段代码的作用是告诉GPU具体怎样去绘制模型的每一个顶点的颜色以及最终每一个像素点的颜色。

三、 Shader编程语言

既然Shader是一段代码,那必然要用一种语言来书写它,目前主流的有三种语言:

基于OpenGL的OpenGL Shading Language,简称GLSL

基于DirectX的High Level Shading Language,简称HLSL

还有NVIDIA公司的C for Graphic,简称Cg语言

GLSL与HLSL分别是基于OpenGL和Direct3D的接口,两者不能混用。而Cg语言是用于图形的C语言,这其实说明了当时设计人员的一个初衷,就是让基于图形硬件的编程变得和C语言编程一样方便,自由。正如C++和 Java的语法是基于C的,Cg语言本身也是基于C语言的。如果您使用过C、C++、Java其中任意一个,那么Cg的语法也是比较容易掌握的。Cg语言极力保留了C语言的大部分语义,力图让开发人员从硬件细节中解脱出来,Cg同时拥有高级语言的好处,如代码的易重用性,可读性高等。

Cg语言是Microsoft和NVIDIA相互协作在标准硬件光照语言的语法和语义上达成了一致,所以,HLSL和Cg其实是同一种语言。

一般来说为了跨游戏平台方便,一般学CG语言。

四、 什么是Unity Shader

显卡有NVIDIA、ATI、Intel等等。

图形API有OpenGL、DirectX、OpenglES、Vulkan、Metal等等。

Shader编程语言有GLSL、HLSL、Cg等等。

是不是有点头晕,该怎么去选择呢?在Unity中我们又应该如何做呢?

其实在Unity中反而一切变的简单起来了,我们只需关心如何去这实现我们想要的效果就好了,其余的事情全部交给Unity来自动处理。因为我们在Unity中编写的Shader最终会根据不同的平台来编绎成不同的着色器语言,那么我们在Unity中应该用什么语言来书写Shader呢?

官方的建议是用Cg/HLSL来编写,当然你也可以使用GLSL,主要是因为Cg/HLSL有更好的跨平台性,更倾向于使用Cg/HLSL来编写Shader程序。

Unity Shader严格来说并不是传统上的Shader,而是Unity自身封装后的一种便于书写的Shader,又称为ShaderLab

在Unity中有3种Shader(其实就是三种不同的写法):

Surface Shaders 表面着色器;

Vertex/Fragment Shaders 顶点/片断着色器;

Fixed Function Shaders 固定管线着色器;

其中Fixed Function Shaders已经被淘汰,完全没有学习的必要了。

Surface Shader其实就是Unity对Vertex/Fragment Shader的又一层包装,以使Shader的制作方式更符合人类的思维模式,同时可以以极少的代码来完成不同的光照模型与不同平台下需要考虑的事情。

但是Surface Shader也有它的局限性,就是Vertex/Fragment Shader能实现的效果,Surface Shader不一定能实现,反过来则成立,Surface Shader能实现的Vertex/Fragment Shader则一定可以实现。

并且在Unity2018后的版本中推出了Unity官方自己的可视化Shader工具(Shader Graph)。从生成的代码上来看,也全部是用的Vertex/Fragment Shader,那是不是可以理解为在今后的可编程渲染管线中,Unity自己也抛弃了Surface Shader,而全部采用了Vertex/Fragment Shader?

总之,在今后的学习过程中,也会涉及一些Surface Shader的内容,但主要还是会以Vertex/Fragment为主。

另外,学会Shader也会给我们带来很多的好处:

游戏中模型显示粉色的情况你一定碰到过吧,是Shader丢失呢,还是Shader不符合当前平台呢,又或者是Shader上有语法的错误呢?如果我们有了解并学会Shader的话,这些问题就不会再是一脸懵逼啦。

內建Unity Shader仅仅只是“通用”用例,不足以满足我们所有的画面表现需求。

一旦掌握Shader,可以为游戏/应用创造独一无二的视觉享受。根据实际需求,为游戏和应用实现特定功能的Shader。

能极大的帮助我们做渲染上的性能优化,因为通过Shader可以控制渲染什么以及如何渲染。

撰写Shader的能力对于游戏团队非常重要,掌握Shader技能的开发一直是炙手可热的职位。现在一个不争的事实就是,技术美术永远是各大厂商的稀缺资源。

五、 Shader核心知识

1. 渲染管线

又叫渲染流水线,是显示芯片内部处理图形信号相互独立的并行处理单元。一个流水线是一序列可以并行和按照固定顺序进行的阶段,遵循着前入后出的流程。类比来说,就像是一个工厂,同时生产宝马和宾利两种汽车,这两款汽车的每个零件又是同时制作的,就可以说这个车间内有两个不同的渲染管线。

根据上图进行说明。3D软件或是游戏在运行的时候,会调用图形API,OpenGL或者是DirectX。而顶点着色器和片段着色器就在图中GPU运算框选部产生作用。

上图就是针对到unity引擎中。Geometry部分可以理解为建模,这个过程就是把Mesh数据导入到unity之中,unity引擎再调用图形API,而调用图形API的过程就是在驱动GPU进行处理运算。

进入到GPU后,首先进行的是顶点处理程序(Vertex Processor)对应顶点shader,顶点运算的结果会传递给像素处理器(Pixel Processor相当于片段处理器),其对应的便是像素shader(也就是片段shader),最后输出可以在屏幕上显示的像素信息,即Frame Buffer(帧缓冲),Frame Buffer不仅可以储存颜色信息还可以储存深度值。

2. shader 材质 贴图

着色器实际就是一小段程序,他负责将输入的顶点数据以指定的方式和输入的贴图或者颜色等组合起来,然后进行输出。绘图单元可以以及这个输出来将图像绘制到屏幕上。

输入的贴图或者颜色等,加上对应的shader,以及对shader的特定的参数设置,将这些内容(shader及输入参数)打包储存在一起,得到的就是一个Material(材质),这些包里其实还有其他东西比如向量、矩阵。之后,我们便将材质赋予到三维模型上进行渲染(输出)了。

材质,就像是游戏引擎最终使用的商品,shader就好比是生产这种商品的加工方法,而贴图则是这商品的原材料。如果我们不用Unity或是其他引擎的话,实现材质就需要利用OpenGL或是DirectX的API的调用,手动组织出个shader,这样就很麻烦,所以引擎提供了便捷。

六、 unity中shader的编写形式

有三种:surface shader vertex and Fragment shader fixed function shader。我们知道,硬件只识别顶点着色和片段着色,那么unity引擎中为何还会多出来一个surface shader(以下简称SS)和Fixed Function shader(以下简称FFS)呢。

对于FFS,主要是对于固定管线的硬件的操作,是特别保守的shader能得到绝大部分硬件的支持;而SS呢,是unity推荐用的,创建一个shader在unity中的时候,默认的代码就是SS。实际上SS是对顶点和片段着色器的一种“包装”,在SS编程后unity会将SS代码编译成硬件可识别的顶点和片段着色器代码

书写shader的主要结构:

七、 ShaderLab

ShaderLab是为unity定制的专门用于编写Shader的语法,可以容纳其他三种shader。

shaderLab的主要结构:

花括号内的三个部分:Properties,Subshaders,Fallback。

什么是Properties呢,属性。我们在unity中新建一个材质球和一个shader,打开编译器将shader命名为“111”,再将111shader拖拽给材质球,再点击材质球观察其显示与代码中Properties的内容。我们发现,shader编程中的Properties(属性)会让拥有该shader的材质球的属性以列表的形式显示出来,进行参数调节。

subshader是啥呢,算法,就是写给GPU渲染的shader片段了,这里记住,一个shader当中至少有一个subshader。每一次显卡进行处理的时候呢,只能选择其中一个subshader去执行。那为什么会有多个subshader呢?这和硬件有关。

在读取shader的时候,会先从第一个subshader读取,如果第一个能适配当前硬件,就不会往下读了;如果硬件太老跟不上,第一个读取不了,就会读取第二个看能不能与我适配。也就是说,subshader的所有方案会向下简化。如果这些列举的subshader都用不了怎么办?那就是第三个Fallback了。

FallBack就是在subshader都用不了的时候可以回滚到指定的unity中一个都能适配的shader。unity常用的内建shader的如下:

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

Unity Shader简介 的相关文章

  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 将 Excel 导入到 Datagridview

    我使用此代码打开 Excel 文件并将其保存在 DataGridView 中 string name Items string constr Provider Microsoft Jet OLEDB 4 0 Data Source Dial
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 如何将整数转换为 void 指针?

    在 C 中使用线程时 我面临警告 警告 从不同大小的整数转换为指针 代码如下 include
  • Java字符串查找和替换的最佳方法?

    我正在寻找 Java 中字符串查找和替换的最佳方法 这是一句话 我的名字叫米兰 人们都知道我叫米兰瓦西奇 我想用 Milan Vasic 替换 Milan 弦 但在我已经有 Milan Vasic 的地方 情况不应该是这样 搜索 替换后的结
  • Java LRU 缓存使用 LinkedList

    堆栈溢出的新手 所以请不要介意我以菜鸟的方式问这个问题 我正在尝试使用链表实现 LRU 缓存 我在这里看到了使用 linkedHashMap 和其他数据结构的其他实现 但对于这种情况 我正在尝试使用链表创建最佳优化版本 正如我在技术期间被问
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • 如何在 Blackberry Cascades 中显示具有特定号码的电话板

    我正在使用带有 C QT 和 QML 的 Blackberry Cascades 10 Beta 3 SDK 以及 Blackberry 10 Dev Alpha Simulator 和 QNX Momentics IDE 并且我正在尝试实
  • 使用 Moq 使用内部构造函数模拟类型

    我正在尝试模拟 Microsoft Sync Framework 中的一个类 它只有一个内部构造函数 当我尝试以下操作时 var fullEnumerationContextMock new Mock
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • .NET中的LinkedList是循环链表吗?

    我需要一个循环链表 所以我想知道是否LinkedList是循环链表吗 每当您想要移动列表中的 下一个 块时 以循环方式使用它的快速解决方案 current current Next current List First 电流在哪里Linke
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当
  • 使用正则表达式匹配阿拉伯文文本

    我试图使用正则表达式仅匹配阿拉伯语文本 但出现异常 这是我的代码 txt matches P Arabic 这是例外情况 线程 main 中的异常 java util regex PatternSyntaxException 索引 9 附近
  • 如何创建具有同等时间元素的 JavaFX 转换?

    我正在尝试 JavaFX 和动画 尤其是PathTransition 我正在创建一个简单的程序 使球 弹跳 而不使用QuadCurveTo班级 到目前为止 这是我的代码 Ellipse ball new Ellipse 375 250 10
  • Retrofit 2.0:预期为 BEGIN_OBJECT,但在第 1 行第 1 列路径 $ [重复] 处为 STRING

    这个问题在这里已经有答案了 我在邮递员上传递了更新用户请求并获得了成功的响应 参见图片 现在当我尝试使用 Retrofit 2 在我的应用程序中执行相同操作时 出现错误 com google gson JsonSyntaxException
  • 使用 PDFBox 在 Android 中创建 PDF

    我正在尝试通过我的 Android 应用程序创建 PDFPDFBoxapi 但出现以下错误 java lang NoClassDefFoundError org apache pdfbox pdmodel PDDocument 我已经将以下
  • Java 可变 BigInteger 类

    我正在使用 BigIntegers 进行计算 该计算使用一个调用 multiply 大约 1000 亿次的循环 并且从 BigInteger 创建新对象使其非常慢 我希望有人编写或找到了 MutableBigInteger 类 我在 jav

随机推荐

  • electron-builder打包白屏,报错:Not allowed to load local resource: file:///index.html解决方法

    报错如下 还有的是控制台弹窗报错 先看看项目目录结构 dist index html 打包好的主入口文件 main bundle js 打包好的main js文件 src main main js文件在里面 main js electron
  • hdf5文件读取

    深度学习中 数据集的特征文件通常以hdf5文件形式存储 读取方式如下 import h5py 读取文件 路径需要自己修改下 f h5py File home xdu yys MIGCN main data raw data charades
  • 【事件驱动】【数码管识别】 封装成DLL的函数的梳理

    要封装成动态链接库 首先要知道哪些函数需要封装起来 所以今天主要是把程序的结构梳理了一下 看看用到了哪些函数 因为后来识别的方法修改了 所以之前采用的很多函数没有再用到 所以就没有必要把所有的函数都封装起来了 程序主干部分的结构如下 这个流
  • 【regression】分位数回归 quantile regression

    quantile regression python实现 前言 分位数回归可调用的库 1 scikit learn 2 statsmodels quantile loss function python实现 1 在neural networ
  • 区块链在医疗行业能做些什么?

    千金难买一个健康的身体 健康是每个人成长和实现幸福生活的基础 也是促进人的全面发展的必然条件 当今时代 社会压力巨大 很多人处于亚健康的状态 这是一个亟需重视的问题 众所周知 很多疾病早发现就能实现早治疗 实现及时治疗 才能最大程度上挽回生
  • 腾讯云2核4G服务器5M带宽轻量CPU性能、流量和系统盘测试

    腾讯云轻量应用服务器2核4G5M配置 自带5M公网带宽 5M带宽下载速度峰值可达640KB 秒 系统盘为60GB SSD盘 每月500GB流量包 折合每天16GB流量 腾讯云百科来详细说下腾讯云轻量应用服务器2核4G5M配置 CPU型号处理
  • 「速通Shell」建楼先搬砖,Shell变量四大分类

    目录 Shell变量 什么是变量 shell变量定义 shell变量分类 环境变量 常见变量 变量引用 变量赋值 本地变量 变量定义 变量引用 变量赋值 变量删除 位置参数变量 变量定义 变量引用 特殊变量 变量定义 变量引用 总结 上一篇
  • POJ--1328:Radar Installation (贪心)

    1 题目源地址 http poj org problem id 1328 2 解题思路 该题题意是为了求出能够覆盖所有岛屿的最小雷达数目 每个小岛对应x轴上的一个区间 在这个区间内的任何一个点放置雷达 则可以覆盖该小岛 区间范围的计算用 x
  • MySQL数据库命令行详解

    MySQL数据库命令行详解 基础操作 进入数据库 mysql u root p databaseName root是只用管理员账户 后面括号是自己想连接的数据库名称 可不写 进入mysql后在通过use databaseName来连接对应数
  • 小样本学习--学习记录

    之前在做课题的时候 把数据不均衡和小样本的概念混淆了 昨天看了一篇论文 面向小样本数据的机器学习方法研究综述 陈良臣 傅德印 这篇论文写的非常清晰 推荐阅读 网上的一些综述整理都是根据 小样本学习研究综述 赵凯琳 这篇论文 知乎上的一篇笔记
  • 哪些应用适合服务器虚拟化,哪些服务器和应用适合虚拟化?

    虚拟化如今很流行 你可能也想把你所有的物理机进行虚拟化 考虑到可移植性 部署和硬件利用等方面的好处 虚拟化的确是非常诱人的 不过 这并不意味着虚拟化是任何服务器或应用的最好解决方案 至少现在还不是 其挑战是如何判断到底哪些服务器和应用适合于
  • 优秀英语教材

    优秀英语教材的选择 本人是个学生 依照自己学习英语的经历发表一些浅见 请各位不要将以下内容做商业用途 误区 1 在我看来 简单地评判一本英语教材是否优秀 可以观察以下几点 1 有无CEFR欧洲标准评级 2 是否是近10年出版 3 是否是英美
  • 【磕盐随记】C++ CUDA编程的环境配置

    一 前言 最近写了个又臭又长的代码来验证idea 效果还行但速度太慢 原因是代码中包含了一个很耗时的模块 这个模块需要连续执行百次以上才能得到最终结果 经过实测模块每次执行消耗约20ms 而且两次执行之间没有先后关系 为了保证系统的实时性
  • VUE3 + TS + 父子组件传值

    VUE3 TS 父子组件传值 父组件 传入几个变量 并且有接受子组件函数 changeaddress
  • 【主席树启发式合并】【P3302】[SDOI2013]森林

    Description 给定一个 n 个节点的森林 有 Q 次操作 每次要么将森林中某两点联通 保证操作后还是个森林 要么查询两点间权值第 k 小 保证两点联通 强制在线 Limitation 1 leq n Q leq 80000 Sol
  • SpringBoot核心配置全面总结

    Spring Boot的核心配置文件用于配置Spring Boot程序 文件名字必须以application开始 这个既是底层源码的强制要求 也是SpringBoot的一种代码规约 有助于在开发层面利于代码规范管理 说明 以下内容接着i前面
  • Java中的Calendar日历API用法完全解析

    第一部分 Calendar介绍 Calendar 定义 public abstract class Calendar implements Serializable Cloneable Comparable
  • centos mysql jar 驱动包_JDBC连接Mysql数据库详解

    JDBC Java DataBase Connectivity 即Java数据库连接 简而言之 就是通过Java语言来操作数据库 我们可以把JDBC理解成是官方定义的一套操作所有关系型数据库的规则 规则即接口 也就是说 官方定义了一套操作所
  • java实现单点登陆(SSO)

    java实现单点登陆 SSO 网络域名必须完全一致 才代表同一站点 域名映射 访问后面的 会跳转到前面 单点登陆概念 多系统 单一位置登录 实现多系统同时登陆 常出现在互联网和企业级平台中 单点登陆一般是用于互相授信的系统 实现单一位置登录
  • Unity Shader简介

    Shader 中文名为着色器 对很多开发者来说它是一个神秘的存在 想学但是又不知道如何去学 或者学了一段时间发现Get不到它的点 始终感觉游离在外 无法开窍 本文来讲下如何从零基础入门Shader 目的在于让初学Shader的程序或者美术可