UnityShader入门精要笔记(十二)——屏幕后处理效果
屏幕后处理效果是游戏中实现屏幕特效的常见方法。在本章中我们将学习如何在Unity中利用渲染纹理来实现各种常见的屏幕后处理效果。我们首先要建立一个基本的屏幕后处理脚本系统,随后我们会使用这个系统实现一个简单的调整画面亮度、饱和度和对比度的屏幕特效。然后我们会接触到图像滤波的概念,并利用Sobel算子在屏幕空间中对图像进行边缘检测,实现描边效果。在此基础上,我们会实现一个高斯模糊的屏幕特效、Bloom和运动模糊的效果。
建立一个基本的屏幕后处理脚本系统
在Unity5之后,书里面提到的这个后处理脚本系统的基类中使用的那些接口都已经废弃了,所以这个后处理脚本启动其实也没有什么存在的必要了。另外,本书使用OnRenderImage的方法实现后处理效果的方式也逐渐被CommandBuffer给取代了,所以笔者会尝试用CommandBuffer的方式重新实现这章的所有后处理效果。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051using UnityEngin ...
UnityShader入门精要笔记(十一)——让画面动起来
没有动画的画面往往会让人觉得很无趣,在本章中,我们将会学习如何向UnityShader中引入时间变量,以实现各种动画效果。
Unity Shader中的内置变量(时间篇)动画效果往往是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化。UnityShader提供了一些列关于时间的内置变量来允许我们方便地在Shader中访问运行时间,实现各种动画效果。下表是Unity中内置地时间变量。
名称
类型
描述
_Time
float4
t是自该场景加载开始所经过地时间,4个分量分别是(t/20, t, 2t, 3t)
_SinTime
float4
t是时间的正弦值,4个分量的值分别是(t/8, t/4, t/2, t)
_CosTime
float4
t是时间的余弦值 ,4个分量分别是(t/8,t/4, t/2, t)
unity_DeltaTime
float4
dt是时间增量,4个分量的值分别是(dt, 1/dt, smoothDt, 1/smoothDt)
在后面的章节中,我们会使用上述的时间变量来实现纹理动画和顶点动画。
纹理动画纹理 ...
UnityShader入门精要笔记(十)——高级纹理
立方体纹理在图形学中,立方体纹理(Cubemap)是环境映射(Environment Mapping)的一种实现方法。环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像是镀了一层金属一样反射处周围的环境。
和之前见到的纹理不同,立方体纹理总共包含六张图片,这些图像对应了一个立方体的六个面,立方体纹理的名称也由此而来。立方体的每个面表示沿着世界空间下的轴向(上、下、左、右、前、后)观察所得的图像。那么我们如何对这样的一种纹理进行采样呢?和之前使用的二维纹理坐标不同,对立方体纹理采样我们需要提供一个三维的纹理坐标,这个三维纹理坐标表示了我们在世界空间下的一个3D方向。这个方向矢量从立方体的中心出发,当它向外部延伸时就会和立方体的6个纹理之一发生相交,而采样得到的结果就是由该交点计算而来的。
使用立方体纹理的好处在于,它的实现简单快速,而且得到的效果也是比较好的。但是它也有一些缺点,例如,当场景中引入了新的物体、光源,或者物体发生移动时,我们就需要重新生成立方体纹理。除此之外,立方体纹理也仅可以反射环境,但不能反射使用了该立方体纹理的物体本身。这是因为,立方体纹理不能模拟多次 ...
UnityShader入门精要笔记(九)——更复杂的光照
Unity 的渲染路径在Unity中, 渲染路径(Render Path)决定了光照是如何被应用到Unity Shader中的。因此,如果要和光源打交道,我们需要为每个Pass指定它使用的渲染路径,只有这样才能让Unity知道,“哦,原来这个程序员想要这种渲染路径,那么好的,我把光源和处理后的光照信息都放在这些数据里,你可以访问啦!”也就是说,我们只有为Shader正确地选择和设置了需要地渲染路径,该Shader地光照计算才能被正确执行。
Unity支持多种类型的渲染路径。在Unity5.0之前,Unity主要有3种:前向渲染路径(Forward Rendering Path)、延迟渲染路径(Deferred Rendering Path)和顶点照明渲染路径(Vertex Lit Rendering Path)。unity5.0之后,Unity做了很多更改,主要有两个变化:首先顶点照明渲染路径已经被Unity抛弃。其次,新的延迟渲染路径已经代替了原来的延迟渲染路径。
大多数情况下,一个项目只会使用一种渲染路径,因此我们可以为整个项目设置渲染时的渲染路径。我们可以通过在Unity的Edi ...
UnityShader入门精要笔记(八)——透明效果
Unity中实现透明效果有两种方式,透明度测试(Alpha Test)和透明度混合(Alpha Blend)
渲染顺序很重要在使用透明度混合技术的时候需要关闭深度写入,为什么呢?如果不关闭深度写入的话,一个半透明的物体表面背后的表面本来是可以透过它被我们看到的,但是由于深度测试时判断结果时该半透明表面距离摄像机更近,导致后面的表面将会被剔除,我们也就无法通过半透明表面看到后面的物体了。但是,我们由此也破坏了深度缓冲的工作机制,这是一个很糟糕的事情,尽管我们不得不这样做。
渲染引擎一般都会先对物体进行排序,再渲染。常用的方法是:
先渲染所有不透明的物体,并且开启它们的深度测试和深度写入
把半透明物体按照它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染透明物体,并开启它们的深度测试,但关闭深度写入。
为了减少错误排序的情况,我们可以尽可能让模型是凸面体。并且考虑将复杂的模型拆成可以独立排序的子模型等。其实就算排序错误结果有时也不会非常糟糕,如果我们不想分割网格,可以试着让透明通道更加柔和,使穿插看起来并不是那么明显。我们也可以使用开启了深度写入的半透明效果来近似模拟物体的半透明 ...
UnityShader入门精要笔记(七)——基础纹理
纹理的作用像是盖在模型表面的衣服,纹理决定了模型表面看起来是什么样子的。
单张纹理我们通常会使用一张纹理来代替物体的漫反射颜色。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182Shader "unityShaderBook/Chapter 7/Single Texture"{ Properties { _MainTex ("MainTex", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) _Gloss ("Gloss", Range(8.0, 256)) = 20 ...
Unity性能优化
本文是笔者近期开展性能优化工作的知识点记录,性能优化涉及渲染、内存代码逻辑等方方面面,内容特别繁杂。以笔者目前的能力没有办法将这些知识系统梳理,因此本文每小节之间并无关联性,是一个个独立的知识点。
性能优化的原则本小结翻译自Unity官方的性能优化指导书
设置帧率预算内存分析内存对运行时的性能表现的影响微乎其微,
在Unity中有两种方法来分析游戏的内存占用:
Memory Profiler module: 这是Unity内置的模块,通过该模块我们可以分析我们的游戏基本的内存占用情况
Memory Profiler package: 这是一个Unity Package你可以将其安装到你的Unity项目中。这个模块为Unity Editor添加了额外的Memory Profiler窗口,让你能够更加详细地分析项目的内存使用情况。
Unity 性能分析工具Unity官方提供的性能分析工具有 ‘Profiler’ ‘Frame Debugger’ ‘Memory Profiler’ ‘Profile Analyzer’笔者体验下来觉得这几个工具的使用还是很容易上手体验很好的
判断是CP ...
发布自定义UnityPackage到代码托管平台
背景笔者正筹划搭建自己的游戏框架,并希望基于Github和Gitee这类代码托管平台维护和迭代,实现在开发新游戏时快速移植。本文记录笔者将代码发布到Gitee上的过程。
制定规范一个标准UnityPackage的内部结构大致如下:
123456.├── CHANGELOG.md├── README.md├── LICENSE.md├── Code└── package.json
README用来介绍Package的功能和用法;CHANGELOG用来记录Package所有历史版本功能修改、新增和维护日志;README和CHANGELOG不是必须的,但它们可以作为辅助文档帮助使用者更好的理解和使用该Package;而且维护README和CHANGELOG更新可以督促我们养成良好的开发习惯。
LICENSE是开源许可,如果你对你的代码版权不是很重视的话,这也是非必需的;你也可以使用最宽松的MIT开源许可。
Code是Package中实现功能的代码部分了,这一部分的细节会在实践章节中阐述。
package.json是Package中最重要的文件,它记录了Package的版本、url等各种能够 ...
UnityShader入门精要笔记(六)——Unity中的基础光照
我们如何看到这个世界当我们说一个物体的颜色是红色时,是因为这个物体更多地反射了红光波长,而吸收了其他波长。要在计算机上模拟真实的光照环境来生成一张图像,需要考虑三个过程:
首先, 光线从光源中被发射出来
然后,光线和场景中的一些物体相交;一些光线被物体吸收了,而另一些光线被散射到其他方向了
最后,摄像机吸收了一些光,产生了一张图像
光源在光学中,使用辐照度(irradiance)来量化光。我们用l来表示光线的从光源射出的方向,对于平行光来说,它的辐照度可以用过计算在垂直于l的单位面积上单位时间内穿过的能量来得到。注意这个值表示的是垂直于光线方向上的辐照度,而我们在计算光照模型中,需要知道的是物体表面的辐照度,物体的表面往往是不垂直于l的,所以为了得到物体表面的辐照度,我们需要用光线方向l和物体表面发现n之间夹角的余弦值来得到。
吸收和散射光线由光源发射出来之后,就会和一些物体相交。通常相交的结果有两个:散射(scattering)和吸收(absorption)。
散射只改变光线的方向,但是不改变光线的密度和颜色。而吸收只改变光线的密度和颜色,不改变光的方向。
我们重点看散射部 ...
基于CommandBuffer的Bloom效果的实现
背景最近在配合动效同事使用后处理技术实现Bloom辉光的效果。首先如果要实现Bloom效果是必须开启HDR的,开启HDR之后内存里会增加两个RenderTexture,并且随着屏幕分辨率的增加这两个Render Texture会越来越大,这是无法避免的一部分开销。一开始我们使用的是Unity官方提供的兼容Build-in渲染管线的Post Processing stack V2后处理插件,这个插件十分强大,除了Bloom效果还能实现很多其他的后处理效果。但同时这个插件的开销实在是太大了,在使用了这个插件之后我们只是为了实现一个Bloom效果而造成这么大的内存效是得不偿失的。比起我们要实现的Bloom效果,使用这个插件造成的开销是无法接受的。为了做优化打出包来做了性能对比分析,发现整个插件造成的主要开销在内存占用上。在网上找到了一个Bloom插件,但是插件已经比较老了,还是基于Graphics.Blit的方式实现的后处理效果,因此笔者在此插件的基础上实现了基于CommandBuffer的Bloom效果。
前置知识大概方案Post Processing后处理后处理值得是在渲染完整个场景得到 ...