• 本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载。
  • 本篇博客会补充一些扩展内容(例如其他博客链接)。
  • 本篇博客还会提供一些边读边做的效果截图。文章内所有数学公式都由Latex在线编辑器生成。
  • 本篇博客主要提供一个“glance”,知识点的总结。如有需要请到书店购买正版。
  • 博客提及所有官方文档基于2022.2版本,博客会更新一些书中的旧的知识点到2022.2版本。
  • 个人博客网址:《Unity Shader入门精要》笔记:高级篇(3)以及扩展 - Sugar的博客,如文章转载中出现例如传送门失效等纰漏,建议直接访问原博客网址。

  • 如有不对之处欢迎指正。
  • 我创建了一个游戏制作交流群:637959304 进群密码:(CSGO的拆包密码)欢迎各位大佬一起学习交流,不限于任何平台(U3D、UE、COCO2dx、GamesMaker等),以及欢迎编程,美术,音乐等游戏相关的任何人员一起进群学习交流。
  • 完结撒花~

目录

噪声

消融效果

水波效果

Unity中的渲染优化技术

影响性能的因素

Unity中的渲染分析工具

减少draw call数目

减少需要处理的顶点数目

减少需要处理的片元数目

减少带宽

减少计算复杂度

扩展


噪声

消融效果

  • 原理:噪声纹理+透明度测试
//核心代码在于:
//第一个Pass
float4 frag (VertexOutput i) : SV_Target
{fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
//burn为噪声贴图,_BurnAmount为时间clip(burn.r - _BurnAmount);fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);burnColor = pow(burnColor, 5);//书里面写的是3D的,然后这里我改了改放在了2D上面fixed4 finalColor = lerp(这里填入你原本的颜色, fixed4(burnColor,1.0), t * step(0.0001, _BurnAmount));return finalColor;
}
//第二个用于裁剪的Pass
fixed4 frag(v2f i) : SV_Target {
{fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;clip(burn.r - _BurnAmount);SHADOW_CASTER_FRAGMENT(i)
}

  • 当你试图把你的砖块贴图当成噪声放上去的时候


水波效果

  • 把噪声图当做高度图使用,不断修改水面的法线方向。
    把立方纹理作为环境纹理贴图模拟折射效果。
  • 使用菲涅尔系数动态混合反射和折射颜色,v和n代表视角方向和法线方向。夹角越小,数值越小,反射越弱。

Shader "Example/Water Wave" {Properties {_Color ("Main Color", Color) = (0, 0.15, 0.115, 1)_MainTex ("Base (RGB)", 2D) = "white" {}_WaveMap ("Wave Map", 2D) = "bump" {}_Cubemap ("Environment Cubemap", Cube) = "_Skybox" {}_WaveXSpeed ("Wave Horizontal Speed", Range(-0.1, 0.1)) = 0.01_WaveYSpeed ("Wave Vertical Speed", Range(-0.1, 0.1)) = 0.01_Distortion ("Distortion", Range(0, 100)) = 10}SubShader {Tags { "Queue"="Transparent" "RenderType"="Opaque" }
//抓取屏幕图像,并自定义名字传入到下方的Pass并采样GrabPass { "_RefractionTex" }Pass {Tags { "LightMode"="ForwardBase" }CGPROGRAM#include "UnityCG.cginc"#include "Lighting.cginc"#pragma multi_compile_fwdbase#pragma vertex vert#pragma fragment fragfixed4 _Color;sampler2D _MainTex;float4 _MainTex_ST;
//水的关于波纹的法线噪声贴图sampler2D _WaveMap;float4 _WaveMap_ST;
//环境贴图samplerCUBE _Cubemap;fixed _WaveXSpeed;fixed _WaveYSpeed;
//控制扭曲程度float _Distortion;  sampler2D _RefractionTex;float4 _RefractionTex_TexelSize;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT; float4 texcoord : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float4 scrPos : TEXCOORD0;float4 uv : TEXCOORD1;float4 TtoW0 : TEXCOORD2;  float4 TtoW1 : TEXCOORD3;  float4 TtoW2 : TEXCOORD4; };v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.scrPos = ComputeGrabScreenPos(o.pos);o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);o.uv.zw = TRANSFORM_TEX(v.texcoord, _WaveMap);float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
//得到切线空间下的3个坐标轴(切线、附切线和法线的方向)在世界空间下的表示o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);  o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);  o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);  return o;}fixed4 frag(v2f i) : SV_Target {float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
//计算法线纹理当前偏移量float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);
//两次采样对应了模拟两层交叉的睡眠波动效果。fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;fixed3 bump = normalize(bump1 + bump2);
//选用切线空间下的法线进行便宜float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
//使用透视除法并采样得到折射颜色fixed3 refrCol = tex2D( _RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));fixed4 texColor = tex2D(_MainTex, i.uv.xy + speed);fixed3 reflDir = reflect(-viewDir, bump);
//使用反射方向对CUBE采样,把结果和主纹理颜色相乘得到反射颜色。fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb * _Color.rgb;
//计算菲涅尔系数并混合折射和反射。fixed fresnel = pow(1 - saturate(dot(viewDir, bump)), 4);fixed3 finalColor = reflCol * fresnel + refrCol * (1 - fresnel);return fixed4(finalColor, 1);}ENDCG}}// Do not cast shadowFallBack Off
}

Unity中的渲染优化技术

  • 不同平台不同手机型号所用架构都各有差异,这就要求在移动平台上需要花更大的功夫去做优化。例如:PowerVR芯片(用于IOS和部分安卓)使用基于瓦片的延迟渲染架构(TBDR)。Adreno(高通)和Mali(ARM的芯片)使用Early-z或相似技术进行一个低精度的深度检测,来剔除那些不需要渲染的片元。Tegra(英伟达芯片)使用传统架构设计,overdraw(一个像素被绘制多次)可能会造成性能瓶颈。

影响性能的因素

  • CPU:负责保证帧率。有可能的性能影响:1、过多的draw call 2、复杂的脚本或物理模拟
  • GPU:负责分辨率相关的处理。有可能的性能影响
    顶点处理:1、过多的顶点 2、过多的逐顶点计算
    片元处理:1、过多的片元(有可能是分辨率,也有可能是overdraw)2、过多逐片元计算
  • Draw Call:CPU在每次通知GPU进行渲染之前,都要提前准备好顶点数据(位置、颜色、法线、纹理坐标等),然后调用一系列API把他们放到GPU可以访问到的指定位置,最后调用绘制指令。而调用绘制命令会产生一个draw call,过多的draw call会造成CPU性能瓶颈。这是因为CPU往往需要盖面很多渲染状态的设置,这很好费时间。
  • 优化技术:
    CPU:使用批处理技术减少draw call数目。
    GPU:1、减少需要处理的顶点数目:优化几何体,使用模型的LOD(level of detail)技术,使用遮挡剔除(Occlusion Culling)技术 2、减少需要处理的片元数目:控制绘制程序,警惕透明物体,减少实时光照 3、减少计算复杂度:使用Shader的LOD技术,代码方面的优化
    节省内存带宽:1、减少纹理大小 2、利用分辨率缩放

Unity中的渲染分析工具

  • 渲染统计窗口:他会统计音频、图像、网络三个方面信息。
  • FPS:帧率以及处理一帧所需的时间(括号内)
  • Batches:一帧需要进行的批处理数目
  • Saved by batching:合并的批处理数目(表明批处理为我们节省了多少draw call)
  • Tris,Verts:需要绘制的三角面片和顶点数目
  • Screen:屏幕大小以及占用内存大小
  • SetPass calls:渲染使用的pass数目(每个pass都需要Unity的runtime绑定新的Shader,这可能造成CPU性能瓶颈)
  • shadow casters:阴影映射数目
  • Visible skinned meshes:渲染的蒙皮网格数目
  • Animation/Animator components playing:播放动画数目

  • 性能分析器(Profiler):通过Window->Analysis->Profiler打开。

  • 帧调试器(Frame Debugger):Window->Analysis->Frame Debugger打开。在窗口中可以查看每个draw call的工作和结果。
  • Drawing为10代表绘制工作需要10个draw call完成,剩余的4个draw call是准备处理工作。

  • 其他平台性能分析工具:
    安卓:高通分析工具可以对不同测试机进行详细的性能分析。英伟达提供了NVPerfHUD工具。
    IOS平台:Unity内置工具可以得到整个场景花费GPU的时间。PoweVRAM的PVRUniSCo shader也可以给出一些宏观上的性能信息。

减少draw call数目

  • Unity渲染优化的4种批处理:传送门
  • 动态批处理:如果场景中有一些模型共享了同一个材质并满足一些条件,Unity就可以自动把他们进行批处理,合并为一个draw call完成。
    原理:每一帧把可以进行批处理的模型网络进行合并,再把合并后模型数据传递给GPU,然后使用同一个材质对其渲染。
    条件限制:1、能够进行动态批处理的网格的顶点属性规模要小于900。(该规模大小为Unity5时所设定)2、所有对象最好使用同一个缩放尺度。 3、使用光照纹理的物体需要小心处理。 4、多Pass的Shader会被批处理中断。
  • 静态批处理:适用于任何大小的几何模型。在Unity中只需要勾选模型的Static可选框即可变为静态批处理。
    原理:在运行开始阶段,把需要进行静态批处理的模型合并到一个新的网格结构中。但只需要进行一次合并操作,因此要比动态批处理更加高效。缺点有:模型不可以在运行时刻被移动,占用更多的内存空间来存储合并后的集合结构。
    对于不同材质的物体,静态批处理可以减少draw call之间的切换,同样也可以优化性能。

  • 共享材质:如果两个材质之间只有使用的纹理不同,我们可以把这些文理合并到一张更大的纹理中,这张更大的纹理被称为一张图集(atlas),再次使用时采用不同的采样坐标即可。

减少需要处理的顶点数目

  • 优化几何体:Unity和三维建模软件中都有相应优化选项。Unity中显示的顶点数目一般会多于三维建模软件中的,因为Unity要进行GPU计算,会进行顶点拆分。
  • 模型的LOD技术:当一个物体离摄像机很远时,模型上的细节无法被察觉到。因此LOD允许当对象原理摄像机时,减少模型上的面片数量。
  • 遮挡剔除技术:消除其他物件后面看不到的物件,因此就不会计算看不到的顶点。

减少需要处理的片元数目

  • 这部分的重点在于减少overdraw
  • 控制绘制顺序:深度测试可以保证物体都是从前往后绘制的,可以很大程度上减少overdraw。
    人为控制绘制顺序的经验:优先绘制主人公,敌人绘制顺序可以往后放,天空盒子放在渲染队列最后。
  • 透明物体:移动设备尽量避免半透明物体的绘制,或者考虑开启深度写入的透明方法。
  • 减少实时光照和阴影:使用逐像素点光源以及逐像素的Shader可能造成draw call数目成倍增加,同时也会增加overdraw的数量。同时同态批处理和静态批处理都无法优化逐像素点光源。
    解决方法:1、提前进行光照烘焙得到光照纹理,进行光源模拟。 2、使用God Ray进行光源模拟,通过透明纹理的模拟来得到。 3、使用查找纹理,提前存储好内容,使用时根据光源方向,视角方向,法线方向等参数直接采样得到光照结果。这种方法可以得到更出色的光照模型。

减少带宽

  • 减少纹理大小
    1、纹理长宽比最好是正方形,且最少是2的整数幂。
    2、尽可能使用多级渐远纹理技术(mipmapping)和纹理压缩。(书中所述的Advanced的Texture Type已经没有了,在Default类型中也可以直接设置是否生成Mip Maps,如下图所示)纹理压缩如下图最下方的Format选项所示,Unity会自动根据平台不同采用不同纹理压缩技术。

  • 利用分辨率缩放:过高屏幕分别率也会造成性能下降。Unity设置屏幕分辨率可以直接调用Screen.SetResolution

减少计算复杂度

  • Shader的LOD技术:和模型的LOD技术类似。只有Shader的LOD值小于某个设定的值,这个Shader才会被使用,而超过了的物体将不会被渲染。(difffuse的LOD为200,Bumped Specular为400)
  • 代码方面的优化:1、尽可能使用低精度的浮点值进行运算,高精度,float适用于存储顶点坐标等变量。half适用于一些标量、纹理坐标等变量,计算速度大约是float的两倍。fixed适用于绝大多数颜色变量和归一化后的方向矢量,计算速度大约是float的4倍。2、尽可能使用全屏的屏幕后处理效果。 3、尽可能不要使用分支语句和循环语句,避免三角函数、pow、log等复杂的数学运算(可以用查找表进行代替),尽可能不要使用discard操作会影响硬件某些优化。

扩展

  • 书中的最后一个部分主要是一些扩展内容的讲解,这里不作过多赘述,推荐去原书中阅览一番。(另外原作者在Github中更新了最后一个章节的新内容,部分与原版书籍不同)根据书中扩展内容加之本人的理解,提到如下可以扩展的方向,也是值得有时间找专门教程仔细研究一番:
  • 表面着色器
  • PBS基于物理的渲染
  • 光线追踪技术
  • 伽马校正、HDR
  • SRP、URP、HDRP
  • ShaderGraph

完结撒花~

《Unity Shader入门精要》笔记:高级篇(3)以及扩展相关推荐

  1. Unity shader入门精要学习笔记-代码篇6(序列帧动画/滚动背景/流动河流/广告牌/顶点动画的阴影)

    一.序列帧动画 建立一个四边形对着摄像机. 我们需要一张序列帧图像,这里用到8x8的爆炸图. 给四边形上材质和shader,代码如下: Shader "Custom/NewSurfaceSh ...

  2. Unity Shader入门精要学习笔记 - 第14章 非真实感渲染

    Unity Shader入门精要学习笔记 - 第14章 非真实感渲染 本系列为UnityShader入门精要读书笔记总结, 原作者博客链接:http://blog.csdn.net/candycat1 ...

  3. Unity Shader入门精要学习笔记 - 第7章 基础纹理

    转自 冯乐乐的 <Unity Shader 入门精要> 纹理最初的目的就是使用一张图片来控制模型的外观.使用纹理映射技术,我们可以把一张图"黏"在模型表面,逐纹素地控制 ...

  4. Unity Shader入门精要学习笔记 - 第14章非真实感渲染

    转载自 冯乐乐的 <Unity Shader 入门精要> 尽管游戏渲染一般都是以照相写实主义作为主要目标,但也有许多游戏使用了非真实感渲染(NPR)的方法来渲染游戏画面.非真实感渲染的一个 ...

  5. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

  6. Games101结合Unity Shader入门精要学习笔记(个人向)

    第四章 3D旋转 绕X轴旋转: 绕Y轴旋转: 绕Z轴旋转: 旋转变换(一)旋转矩阵_csxiaoshui的博客-CSDN博客_旋转矩阵 重点:MVP变换!!! model transformation ...

  7. Unity Shader入门精要笔记(五):其他数学相关介绍

    本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢. http://blog.csdn.net/lzhq1982/article/details/73747162 前两篇介绍了U ...

  8. Unity Shader入门精要笔记(四):矩阵与空间变换

    本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢. http://blog.csdn.net/lzhq1982/article/details/73612170 上一篇我们学习 ...

  9. 《Unity Shader入门精要》笔记:初级篇(2)

    本篇博客主要为个人学习所编写读书笔记,不用于任何商业用途,以及不允许任何人以任何形式进行转载. 本篇博客会补充一些扩展内容(例如其他博客链接). 本篇博客还会提供一些边读边做的效果截图.文章内所有数学 ...

最新文章

  1. 理解并演示:Root Guard(根保护)
  2. “HTTP 500 - 内部服务器错误”解决办法
  3. 音视频技术开发周刊 | 138
  4. Java中Lambda表达式与方法引用和构造器引用
  5. AI领域都在用Python即将被淘汰?网友预测未来的编程语言不会是TA
  6. golang - strings
  7. LeetCode--5.最长回文子串(滑动窗口)
  8. dlink虚拟服务器端口转发,D-Link路由器端口转发怎么设置【图文教程】
  9. JavaScript内置对象→对象、系统函数、Date日期对象、String字符串对象、Math对象、Number数字对象、Object对象、Boolean对象、Error对象
  10. [NLP]OpenNLP词形还原器(Lemmatizer)的使用
  11. NYOJ题目289/456/49-01背包问题汇总
  12. 扣丁三国 - 技术支持
  13. 计算机不识别加密狗,用友加密狗识别不到_电脑无法识别用友软件加密狗
  14. 东北大学oj平台python答案_你觉得东北大学的Python考试怎么样?
  15. 油相CdSe/ZnS量子点溶液 硒化镉/硫化锌量子点介绍及阐述
  16. 树莓派如何接硬盘_树莓派添加USB外接硬盘
  17. An error has occured.See the log file
  18. android有什么作用,Android 7.0有什么功能 Android N完整功能参数介绍
  19. 酒店项目 酒店管理系统酒店在线预订系统
  20. 求函数:x的n次方(函数递归)

热门文章

  1. Unity做360°全景图
  2. 工业物联网竟如此简单?
  3. MATLAB在力学上应用,Matlab在力学中的应用
  4. 微信公众平台天气查询,火车票查询,快递查询,小黄鸡,翻译,公交查询的实现
  5. 树莓派简易聊天机器人
  6. Oracle 11G OCP 1Z0-053 570
  7. 企业SaaS模式的优缺点
  8. 批量修改文件名部分字段
  9. 损失函数之NLLLoss和CrossEntropyLoss
  10. 2019寒假集训新生考试 【持续更新中】