Unity Shader 知识点总结(一)
在学习了一段时间的Unity Shader后,打算写一些知识总结,便于今后的查找。如有错误,希望大家指出更改。
本文参照的unity入门精要一书,做一个知识归纳,如有兴趣可以看看其开源的部分,是一本比较好的入门shader书。
一、渲染流水线
学习shader的知识,最重要的是要理解渲染流水线,基于渲染流水线,才能进一步的理解和学习下面的各个部分的shader。基于 Real-time rendering一书,渲染流水线可以分为三个部分:
1、应用阶段
在unity shader中,应用阶段主要完成三个基本的事:
1)准备渲染的场景和模型;
2)设置渲染的状态,主要是渲染所用到的材质、shader、贴图等;
3)对渲染对象做一个粗粒度的剔除操作。
这一阶段都是在CPU阶段执行的,特别是渲染状态的设置,对于后期的渲染有较大的影响,常见的批处理等操作都是在这阶段完成的。对于CPU阶段的优化,我也翻译了一篇外文如何优化CPU造成的渲染性能问题,可以查看这儿:Unity渲染优化中文翻译(二)——CPU的优化策略
2、几何阶段
基于应用阶段的渲染图元(primitives)以及渲染状态的设置,在几何阶段,主要完成的任务是对模型的顶点进行坐标转换,转换到屏幕空间投影坐标系中。此外一些其他的转换操作也可以在这个阶段执行,比如描边涉及的顶点位置偏移,模型空间到切线空间的转换矩阵计算等等。
3、光栅化阶段
基于几何阶段得到的顶点坐标数据,这一阶段的主要任务是基于顶点确定三角形,再对三角形进行插值操作,得到片元像素,最后进行逐像素的操作得到像素颜色。通过一些模板测试,深度测试,透明度测试等等最后将可以显示的像素更新到颜色缓存区中,通过双重缓存的机制更新屏幕颜色。
二、GPU的渲染流水线
我们通常接触的更多的是GPU的渲染流水线,CPU主要工作是将数据发送的显存中,然后设置渲染状态(SetPass的操作),然后调用Draw Call。在CPU和GPU的中间有一个指令缓冲队列,CPU插入指令,GPU取出指令进行渲染,所以整体的渲染的工作主要还是在GPU上执行。现阶段的Unity Shader的GPU渲染流水线主要为:

细分整个流水线,可以参考上面的流程图以及参考书中的过程,可以细分为:
顶点数据—>顶点着色器—>曲面细分着色器—>几何着色器—>裁剪—>投影—>三角形设置—>三角形遍历—>片元着色器—>逐片元操作—>基本测试—>颜色缓存区
Unity提供的主要是Surface shader,但是其本质还是顶点/片元着色器的构成,所以很多的时候在实际项目中,应用顶点/片元着色器的居多。我们在编写自己的shader的时候,更多的是在vertex/fragment这两个部分的shader中编写,当然涉及到其他的一些操作比如剔除、透明度、阴影等可以通过一些Unity shader中的语义指令来设置。
三、基本的光照知识
1、渲染路径
在unity中,主要的渲染路径分为三种:顶点光照渲染路径、延迟渲染路径、前向渲染路径。顶点光照渲染路径现在应用较少,逐渐走出应用的主流,现在应用较多的是前向渲染路径和延迟渲染路径。
在前向渲染路径中,其基本的操作分为两个部分:forwardBase和forwardAdd,在forwardBase中主要计算逐像素光源的渲染,在forwardAdd中计算其他光源的光照计算。在前向渲染路径中,光照的渲染过程分为两个部分,先进行深度的测试,如果通过深度测试,则执行对应的渲染操作。在前向渲染路径中,每个逐像素光源都会对物体执行一次渲染,所以如果场景中有N个物体,M个光源,就会执行N*M次渲染,显然这对于大场景和多像素光源的应用场景有一定的性能限制。
在延迟渲染路径中,只会执行2个Pass的渲染操作,第一个pass主要执行基本的深度测试,并进行G-缓冲;在第二个pass中,基于G-缓冲的结果进行具体的光照计算等渲染操作。所以延迟渲染的意思是指渲染操作被延迟到第二个pass中执行了。这样只用2个pass就实现渲染,可以提高渲染的性能。
2、基本光照模型
在shader中,应用的最为广泛的光照模型是Phong光照模型:光照 = 环境光 + 自发光+ 漫反射光 + 高光反射光
1)环境光,通常可以直接利用UNITY_LIGHTMODEL_AMBIENT.xyz获取到,自发光通常没有采用,但是如果模型的顶点中带有颜色,可以在模型将模型的顶点数据导出用作自发光,可以参考这儿:访问顶点颜色
2)漫反射光
漫反射是shader中操作最多的一种光照,大部分的光照都是对其进行操作,其基本的计算公式为:
Ccolor=Cdiffuse * Clight * max(a,dot(Vnormal,Vlight))
这里解释一下为什么需要max操作,因为光源方向和法线方向夹角未必是锐角,在为钝角的时候得到的点乘结果为负数,这样得到的光照是指模型背面部分的顶点光照计算,这部分计算其实是不需要的,所以都设置为0,max操作就是用来确保最终的计算结果大于等于0。
对于漫反射,在某些部分可能得到的光照颜色接近于灰暗,在某些情况下需要对光照结果做一个整体亮度的提高,所以V社提出了半Lambert的光照模型:
Ccolor= 0.5 * Cdiffuse + 0.5;
其实质就是将整体的计算结果做了一个缩放和偏移后,得到的变化曲线。
除了半Lambert的操作外,在某些时候,如果我们需要对模型进行一种渐变的处理,可以用一张渐变纹理来改变模型的漫反射计算,我会在后面的渐变纹理中提到这部分的操作。
3)高光反射
高光反射是另外一种应用较多的光照,其基本的计算公式为:
Ccolor = Cspecular * Clight * pow(max(Vreflect,Vview),mgloss)
Blinn-Phong的光照模型中,高光反射计算公式可以改为:
Ccolor = Cspecular * Clight * pow(max(Vnormal,Vhalf),mgloss)
其中Vhalf =normalize( normalize(Vview) + normalize(Vlight))
高光反射,主要的是实现对光照的高亮,但是某些时候需要对高亮的结果进行一定的平滑处理,所以可以采用遮罩纹理来处理这样的操作,主要是通过遮罩纹理的某个通道来实现对高光的计算结果进行平滑处理。
3、基本的阴影和衰减
Unity中,对于衰减,主要是通过一张光照衰减纹理(_LightTexture0)的采样得到,其采样操作主要是在光照空间中进行。对于阴影,一般不会采用实时阴影的方式(性能耗费太高),但是现在随着技术的发展,越来越多的游戏采用的实时光照,当然这是对整体的光照的优化有一个极其高的情况下。一般情况下都是将场景烘培,对模型自身添加相应的光照设置。
在unity中,主要是通过一个shadowCaster的shader来实现对阴影的计算,对于物体是否投射阴影可以在其自身的组件上设置。而unity将阴影和衰减的计算合并在一起,主要通过三个基本的内部操作来实现:在a2v的结构体中设置SHADOW_COORDS(n),在vert shader中进行TRANSFER_SHADOW(o),最后在frag shader中进行 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos),此时得到的atten就是综合了衰减和阴影的结果,可以用其来作为衰减和阴影的因子与最终的光照颜色相乘。
Unity Shader 知识点总结(一)的更多相关文章
- Unity Shader 知识点总结(二)
紧接着上一篇文章的shader入门知识的总结,本文主要总结shader中的纹理贴图.透明度混合.顶点动画.后期特效处理等操作.如果有什么地方有错,请指出更正,谢谢.本文的代码主要来自开源书:unity ...
- Unity Shader入门教程(一)
参考文献:http://www.360doc.com/content/13/0923/15/12282510_316492286.shtml Unity Shader是着色器,将纹理.网格信息输入,得 ...
- 【Unity Shader】---常用帮助函数、结构体和全局变量
[Unity Shader]---常用帮助函数.结构体和全局变量 一.内置包含文件 Unity中有类似于C++的包含文件.cginc,在编写Shader时我们可以使用#include指令把这些文件包含 ...
- Unity Shader入门精要之 screen post-processing effect
本篇记录了学习Unity Shader入门精要的屏幕后处理的一些知识点. OnRenderImage(RenderTexture src, RenderTexture dest) 以上函数是Unity ...
- 【Unity Shader】(三) ------ 光照模型原理及漫反射和高光反射的实现
[Unity Shader](三) ---------------- 光照模型原理及漫反射和高光反射的实现 [Unity Shader](四) ------ 纹理之法线纹理.单张纹理及遮罩纹理的实现 ...
- 【Unity Shader】(十) ------ UV动画原理及简易实现
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...
- 【Unity Shader】(九) ------ 高级纹理之渲染纹理及镜子与玻璃效果的实现
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...
- 【Unity Shader】(六) ------ 复杂的光照(上)
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Sha ...
- 【Unity Shader编程】之十六 基于MatCap实现适于移动平台的“次时代”车漆Shader
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/55803629 渲染本文配图使用的 ...
随机推荐
- php中cookie实现二级域名可访问操作的方法
本文实例讲述了php中cookie实现二级域名可访问操作的方法.分享给大家供大家参考.具体方法如下: cookie在一些应用中很常用,假设我有一个多级域名要求可以同时访问主域名绑定的cookie,下面 ...
- QT第六天学习
基本事件: 鼠标事件 键盘事件 绘制事件 1.QT中的事件: 事件是对各应用程序需要知道的由应用程序内部或外部产生的事情或动作的通称. QT中事件的处理: 在QT中使用一个对象来表示一个事件,继承自Q ...
- HDU-1430-素数回文
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1431 这题之前做过,又不会做了, 思路先直接暴力,输入a=5 b=500000000得到最大的值为9 ...
- STL内存管理
1. 概述 STL Allocator是STL的内存管理器,也是最低调的部分之一,你可能使用了3年stl,但却不知其为何物. STL标准如下介绍Allocator the STL includes s ...
- 关于aop:pointcut的expression配制说明及JoinPoint
http://blog.csdn.net/wubai250/article/details/8102194 网上其它示例1:<aop:pointcut id="serviceMetho ...
- 如何开发基于Dubbo RPC的分布式服务?
什么是Dubbo? Dubbo能做什么? 在Crystal框架下,如何开发基于Dubbo RPC的服务? 在Crystal框架下,如何调用Dubbo RPC服务? 相关的文章 什么是Dubbo? Du ...
- HDU1494(dp)
跑跑卡丁车 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- php扩展SeasLog应用于 yii2 组件
一.seaslog 简单介绍及使用原因 它是C 写的PHP扩展,性能很高,使用简单,能满足大部分简单的日志需求.(个人感觉) 其他优势请看-->https://github.com/Neeke/ ...
- ubuntu/deepin制作快捷启动图标
默认情况下系统所有的快捷方式放在/usr/share/applications,打开该目录会看到大量的.desktop文件,每个文件便是一个快捷方式. 有时我们需要自己安装软件,然后添加快捷方式.文件 ...
- 使用fullPage.js遇到的问题以及翻译
使用fullPage.js做一简单页面,遇一古怪问题:.section中的h1标签始终被一插件生成的标签包裹,导致样式调整好不困难!花费数小时排查为何会生成这样一个标签,最终在fullPage.js的 ...