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 渲染本文配图使用的 ...
随机推荐
- 1.4.1. Core Data Helper 简介(Core Data 应用程序实践指南)
有些支持Core Data的内置模板是在应用程序委托里面设置Core Data的.但是为了模块化,我们通过应用程序委托惰性地创建CoreDataHelper类的实例: 初始化托管对象模型 根据托管对象 ...
- MYSQL外键的使用以及优缺点
主键和索引是不可少的,不仅可以优化数据检索速度,开发人员还省不其它的工作, 矛盾焦点:数据库设计是否需要外键.这里有两个问题:一个是如何保证数据库数据的完整性和一致性:二是第一条对性能的影响. 正方观 ...
- js原生设计模式——3简单工厂模式\简单工厂模式封装简单对象
1.Factory基本写法 <!DOCTYPE html><html lang="en"><head> <meta charset= ...
- 关于自己封装Web前端框架的思考和探索
一.引言 首先这些年关于前端技术层出不穷,从最早的只用js做简单验证,到现在发现好像大前端已经无所不能了的感觉.特别是为了降低前端开发复杂度,涌现了一大批 的MVC/MVVM模式的前端框架,不停了刷新 ...
- AJAX 跨域请求的解决办法:使用 JSONP获取JSON数据
由于受到浏览器的限制,ajax不允许跨域通信.如果尝试从不同的域请求数据,会出现安全错误.如果能控制数据驻留的远程服务器并且每个请求都前往同一域,就可以避免这些安全错误.但是,如果仅停留在自己的服务器 ...
- CentOS 7 部署、连接 数据库mariadb
1.安装mariadb yum -y install mariadb* 2.开启/停止 systemctl start mariadb #启动MariaDB systemctl stop maria ...
- 扩展BaseAdapter实现不存储列表项的ListView
下面的实例将会通过扩展BaseAdapter来实现Adapter,扩展BaseAdapter可以取得对Adapter最大的控制权:程序要创建多个列表项,每个列表项的组件都由开发者来决定. 下面的布局文 ...
- 细说WPF数据绑定
简单的事例: <Slider Name="mySlider" Height="28" HorizontalAlignment="Left&q ...
- 【java设计模式】之 模板方法(Template Method)模式
1. 模板方法的一个实例 这一节主要来学习一下设计模式中的模板方法模式.我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验 ...
- IOS控件布局之Masonry布局框架
前言: 回想起2013年做iOS开发的时候,那时候并没有采用手写布局代码的方式,而是采用xib文件来编写,如果使用纯代码方式是基于window的size(320,480)计算出一个相对位置进行布局,那 ...