UnityShader学习之旅 二

  1. 什么是Shader

    即着色器, 仅仅是渲染流水线中的一个环节
    1.GPU流水线上一些可高度编程的阶段,而由着色器编译的代码可以在GPU上运行
    2.有一些特定类型的着色器。eg:顶点、片元着色器
    3.依靠着色器我们可以控制流水线中的渲染细节

  2. 什么是渲染流水线

    定义: 是显示芯片内部处理图形信号相互独立的的并行处理单元
    工作任务: 计算机需要从一系列的顶点数据、纹理等信息出发,把这些信息转换成一张人脸可以看到的图像。由CPU、GPU共同完成。
    三个阶段: 应用阶段、几何阶段、光栅化阶段

阶段实现任务输出
应用阶段CPU负责实现1.把数据加载到显存中1
2设置渲染状态2
3.调用DrawCall3
渲染所需的几何信息
渲染图元
几何阶段GPU
处理所有与绘制的几何相关的事情
1.把顶点坐标变换到屏幕空间
2.交给光栅化器进行处理
进行逐顶点、逐多边形操作
屏幕空间的二维顶点坐标、每个顶点对应的深度值、着色等信息
光栅化阶段GPU决定每个渲染图元的哪些像素应该被绘制在屏幕上渲染最终的图像

3.GPU流水线:GPU渲染的过程在这里插入图片描述

流水线阶段定义输入输出特点任务
顶点数据由应用阶段加载到显存中,由Draw Call指定传递给Vertex shader
顶点着色器实现顶点的空间变换、顶点着色CPU后续阶段所需的数据顶点之间相互独立坐标变换、逐顶点光照
曲面细分着色器 4用于细分图元pach的顶点数量曲面更加平滑细密改变顶点与三角网格的数量–>插入新的顶点
几何着色器5逐图元的着色、产生更多图元一系列顶点组成的图元顶点–数量发生变换能够在GPU上创建数据根据运行环境产生合适分辨率的图形
裁剪图元图元将不在摄像机视野内的顶点裁剪,并剔除某些三角图元的面片
屏幕映射三维坐标转换到二维坐标(x,y)坐标:三维坐标:二维决定了顶点对应屏幕上哪个像素、距离把每个图元的x,y坐标转换到屏幕坐标系下
三角形设置计算三角网格表示数据的过程三角网格每条边的两端点边界像素的坐标信息计算光栅化一个三角网格所需的信息
三角形遍历找到哪些像素被三角网格覆盖的过程上个阶段的计算结果得到一个片元序列6对覆盖区域的像素进行插值检查每个像素是否被一个三角网格所覆盖
片元着色器顶点信息插值的结果一个或多个颜色值仅影响单个片元完成渲染技术7、效果
逐片元操作片元颜色缓冲区对像素产生影响经过测试8,决定每个片元的可见性问题
屏幕图像

4.什么是Shader Lab?

Unity Shader 是Unity为开发者提供的高层级的渲染抽象层。ShaderLab 是Unity提供的编写Unity Shader的一种说明性语言。用语义来描述文件的结构,包含了渲染所需的数据。在这里插入图片描述

5.Unity Shader的结构
Properties语义块的作用仅仅是为了让这些属性可以出现在材质面板中。
Unity Shader文件可以包含多个SubShader,但至少要有一个。

Unity会自动选择第一个能够在目标平台上运行的subshader,如果不支持则会使用Fallback指定的UnityShader

Shader "Name"    //UnityShader的名字 也是索引的路径 可在Name中添加(‘/’)控制面板中出现的位置
{
	Properties	//包含了一系列的属性 名字
	{
		//声明一个Color类型的属性
 	 	_Color("Color Tint", Color) = (1.0,1.0,1.0,1.0) //白色
 	 	/*属性名字:下划线开始. 某些有特殊要求。 eg:_Color
 	 	 显示的名称:在材质面板上可以看到名字--随便取:eg:Color Tint
 	 	 类型:属性指定的类型。eg:Color
 	 	 默认值:属性对应的默认值,第一次把shader赋给某个材质时,在材质面板上显示的默认值。eg:(1.0,1.0,1.0,1.0) 
 	 	*/
	}
	SubShader
	{
		Tags{} //标签 可选 -- 也可在pass中设定
		[RenderSetup] //状态可选
		//至少要有一个pass
		UsePass "ShaderLearn/Chapter12/GuassianShader/GAUSSIAN_BLUR_VERTICAL" //复用其他Pass
    		GrabPass {//抓取屏幕并将结果存储到一张纹理中,用于后续Pass处理
		"_RefractionTex"
		}
		Pass{ //渲染通道必须要有一个,一个Pass占一个CG,过多会造成渲染性能下降
		  [Name] //Pass名称 大写。通过名称其他的Shader可以调用该Pass
		  Tags{}
		  [RenderSetup]	
		}
	}
	Fallback "name" / Fallback Off //若以上SubShader在该显卡上不能运行执行name /关闭Fallback	
}
属性类型默认值的定义语法属性例子CG变量类型9
Intnumber数字_Int(“Int”, Int) = 2
Float10number数字_Float(“Float”, Float) = 2float,half,fixed
Range(min,max)number数字_Range(“Range”, Range(0,1)) = 0.5float,half,fixed
Color(number,number,number,number)四维向量_Color(“Color Tint”, Color) = (1.0,1.0,1.0,1.0)float4,half4,fixed4
Vector(number,number,number,number)四维向量_Vector(“Vector”, Vector) = (1.0,1.0,1.0,1.0)float4,half4,fixed4
2D“defauttexture”{}纹理类型11_2D(“2D”, 2D) = “white”{}sampler2D
Cube“defauttexture”{}纹理类型_Cube(“Cube”, Cube) = “white”{}samplerCube
3D“defauttexture”{}纹理类型_3D(“3D”, 3D) = “black”{}sampler3D
bump内置的法线纹理对应了模型自带的法线信息

【Tags】SubShader标签
subshader的标签是一个键值对(Key - Value)

标签类型说明例子
Queue控制渲染顺序,指定该物体属于哪一个渲染队列。
可以保证所有透明物体后渲染
Tags{“Queue” = “Transparent”}
RenderType对着色器分类Tags{“RenderType” = “Opaque”}
DisableBatching是否对该SubShader使用批处理Tags{“DisableBatching” = “True”}
ForceNoShadowCasting控制使用该SubShader的物体是否会投射阴影Tags{“ForceNoShadowCasting” = “True”}
IgnoreProjector为True是,该SubShader不会受Projector的影响,用于半透明物体Tags{“IgnoreProjector” = “True”}
CanUseSpriteAtlas该SubShader用于Sprite时,设置为FalseTags{“CanUseSpriteAtlas” = “False”}
PreviewType材质面板预览材质,可设置为plane、skybox等Tags{“PreviewType” = “Plane”}

—>以上标签只适用与SubShader

  • 渲染队列
渲染队列队列索引号描述适用例子
Background1000第一个被渲染的优先于其他队列渲染那些需要绘制在背景上的物体
天空盒子
Tags{“Queue” = “Background”}
Geometry2000默认的渲染队列不透明物体Tags{“Queue” = “Geometry”}
AlphaTest2450所有不透明物体渲染之后再渲染它们会更加高效需要透明度测试的物体Tags{“Queue” = “AlphaTest”}
Transparent3000在Geometry与AlphaTest之后,再按从后往前的顺序进行渲染使用了透明度混合的物体、关闭深度写入的ShaderTags{“Queue” = “Transparent”} Pass{ZWrite Off}
Overlay4000实现叠加效果任何需要在最后渲染的物体Tags{“Queue” = “Overlay”}

【Tags】Pass标签

标签类型说明例子
LightMode定义该Pass渲染路径Tags{"LightMode " = “ForwardBase”}
RequireOptions满足某些条件才渲染该Pass。SoftVegetationTags{“RequireOptions” = “SoftVegetation”}

SoftVegetation: Render this pass only if Soft Vegetation is on in the Quality window.

【LightMode 支持的渲染路径】

标签描述限制
Always无论哪种渲染路径,该Pass总会被渲染,但不计算任何光照
ForwardBase计算环境光、最重要的平行光、逐顶点/SH光源、Lightmaps前向渲染
ForwardAdd计算额外的逐像素光源,每个Pass对应一个光源前向渲染
Deferred渲染G缓冲延迟渲染
ShadowCaster把物体的深度信息渲染到阴影映射纹理或一张深度纹理中
PrepassBase渲染法线和高光反射的指数部分遗留的延迟渲染
PrepassFinal合并纹理、光照和自发光来渲染得到最后的颜色遗留的延迟渲染
Vertex、VertexLMRGBM、VertexLM遗留的顶点照模渲染

【渲染状态】

状态名称设置指令解释
CullCull Back/Front/Off设置剔除模式;剔除背面/正面/关闭
只渲染前面/后面/全都渲染
ZTestZTest Less Greater/LEqual/GEqual/Equal/NotEqual/Always设置深度测试时使用的函数
ZWriteZWrite On/Off开启/关闭深度写入
BlendBlend SrcFactor DstFactor开启并设置混合模式
OffsetOffset OffsetFactor, OffsetUnits设置Z缓冲区深度偏移
ColorMaskColorMask RGB /A / 0/ any combination of R, G, B, A设置颜色通道蒙版,0关闭颜色通道的渲染

6.Unity Shader的形式

Create特点劣势例子
表面着色器Surface Shader 包含标准光照代码量少渲染代价大#pragma surface surf lambert
顶点/片元着色器Unit Shader 无光照灵活性高,可控制渲染的实现细节复杂#pragma vertex vert
#pragma fragment frag
标准着色器Standard Shader表面的升级版,PBR技术
后期屏幕渲染特效Image Effect Shader屏幕后处理效果Graphics.Blit(scr,RT1,mat) ZWrite Off ZTest Always
计算着色器12Compute Shader大量数学计算传输速率慢
CPU->GPU->CPU->GPU
#pragma kernel CSMain
固定函数已被抛弃

7.坐标空间–顶点变换

定义原点坐标顶点变换维数
模型空间与某个模型或者对象有关模型的重心顶点着色器访问到的顶点坐标三维空间
世界空间最大最外层的坐标系游戏空间的中心模型的位置若无父节点,则为世界坐标模型变换
摄像机/观察空间渲染游戏所使用的视角摄像机位于原点观察变换
齐次裁剪空间能够方便地对渲染图元进行裁剪13裁剪/投影矩阵14四维空间
屏幕空间显示的屏幕屏幕左下角归一化的设备坐标NDC屏幕映射二维空间
切线空间二维空间

7.法线变换

8.Unity Shader的内置变量
1.变换矩阵

变量名描述矩阵曾用名用法
UnityObjectToClipPos将顶点从模型空间->裁剪空间模型 . 观察 . 投影矩阵mul(UNITY_MATRIX_MVP,*)UnityObjectToClipPos(*)
UNITY_MAXTRIX_MV将顶点从模型空间->观察空间模型 . 观察UNITY_MAXTRIX_MV
UNITY_MAXTRIX_V将顶点从世界空间->观察空间观察矩阵UNITY_MAXTRIX_V
UNITY_MAXTRIX_P将顶点从观察空间->裁剪空间投影矩阵UNITY_MAXTRIX_P
UNITY_MAXTRIX_VP将顶点从观察空间->裁剪空间观察 . 投影矩阵UNITY_MAXTRIX_VP
UNITY_MAXTRIX_T_MVUNITY_MAXTRIX_MV的转置UNITY_MAXTRIX_T_MV
UNITY_MAXTRIX_T_MV法线从模型空间->观察空间UNITY_MAXTRIX_MV的逆转置UNITY_MAXTRIX_T_MV
unity_ObjectToWorld顶点从模型空间->世界空间模型矩阵_Object2World
unityWorldToObject顶点从世界空间->模型空间_Object2World 的逆矩阵_World2Object

2.Unity内置的摄像机和屏幕参数

变量名类型描述曾用名解析用法
_WorldSpaceCameraPosfloat3该摄像机在世界空间中的位置
_ProjectionParamsfloat4x=1.0/-1,y=Near,z=Far,w=1+1/FarNear:近裁剪平面
Far:远裁剪平面
_ScreenParamsfloat4x=width,y=height,z=1+1/width,w=1+1/heightwidth:摄像机的渲染目标的像素宽度
Height:摄像机的渲染目标的像素高度
_ZBufferParamsfloat4x=1-Far/Near,y=Far/Near,z=x/Far,w=y/Far用于线性化Z缓存中的深度值
unity_OrthoParamsfloat4x=width,y=heght,z无定义,w=1(正交)/0(透视)width:正交投影摄像机的宽度
height::正交投影摄像机的高度
unity_CameraProjectionfloat4x4摄像机的投影矩阵
unity_CameraInvProjectionfloat4x4摄像机的投影矩阵的逆矩阵
unity_CameraWorldClipPlanes[6]float4摄像机的6个裁剪平面在世界空间下的等式顺序:左右下上近远裁剪平面

3.Unity 内置包含文件unity的安装路径下CGIncludes

文件名描述
UnityCG.cginc包含了最常使用的帮助函数、宏和结构体等
UnityShaderVariables.cginc在编译UnityShader时自动包含。内置的全局变量ps:UNITY_MAXTIX_MVP(UnityObjectToClipPos) 访问事件、光照、雾化和环境光
Lighting.cginc包含了各种内置的光照模型,surface shader 会自动包含
HLSLSupport.cginc在编译UnityShader时自动包含。声明了很多跨平台编译的宏和定义
UnityStandardBRDF.cginc实现基于物理的渲染
UnityStandardCore.cginc

4.UnityCG.cgin中一些常用的结构体

名称描述包含的变量结构体
appdata_base用于顶点着色器的输入顶点位置、顶点法线、第一组纹理坐标struct appdata_base {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID};
appdata_tan用于顶点着色器的输入顶点位置、顶点切线、顶点法线、第一组纹理坐标struct appdata_tan {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID};
appdata_full用于顶点着色器的输入顶点位置、顶点切线、顶点法线、多组纹理坐标、顶点颜色struct appdata_full {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
fixed4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID};
appdata_img用于顶点着色器的输入顶点位置、第一组纹理坐标struct appdata_img{
float4 vertex : POSITION;
half2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID};
v2f_img用于顶点着色器的输出裁剪空间中的位置、纹理坐标struct v2f_img{
float4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO};

5.UnityCG.cginc中一些常用的帮助函数

函数名描述限制实现
float3 UnityWorldSpaceViewDir(float3 worldPos)输入一个模型空间中的顶点位置,返回世界空间中从该点到摄像机的观察方向return _WorldSpaceCameraPos.xyz - worldPos;
float3 ObjSpaceViewDir(float4 v)输入一个模型空间中的顶点位置,返回模型空间中从该点到摄像机的观察方向float3 objSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz;
return objSpaceCameraPos - v.xyz;
float3 UnityWorldSpaceLightDir(float3 worldPos)
WorldSpaceLightDir(float4 vertex)
输入一个模型空间中的顶点位置,返回世界空间中从该点到光源的光照方向前向渲染return _WorldSpaceLightPos0.xyz - worldPos * _WorldSpaceLightPos0.w;
float3 ObjSpaceLightDir(float4 v)输入一个模型空间中的顶点位置,返回模型空间中从该点到光源的光照方向前向渲染float3 objSpaceLightPos = mul(unity_WorldToObject, _WorldSpaceLightPos0).xyz;
return objSpaceLightPos.xyz - v.xyz * _WorldSpaceLightPos0.w;
float3 UnityObjectToWorldNormal(float3 normal)把法线方向从模型空间转换到世界空间中return normalize(mul(norm, (float3x3)unity_WorldToObject));
float3 UnityObjectToWorldDir(float3 dir)把方向矢量从模型空间转换到世界空间中return normalize(mul((float3x3)unity_ObjectToWorld, dir));
float3 UnityWorldToObjectDir(float3 dir)把方向矢量从世界空间转换到模型空间中return normalize(mul((float3x3)unity_WorldToObject, dir));
float3 Shade4PointLights(…)计算4个点光源的光照。前向使用这个函数计算逐顶点光照前向渲染

9.渲染路径

决定了光照是如何应用到UnityShader中。一般一个项目只使用一种渲染路径,如果使用多条渲染路径,需要在摄像机下设置以覆盖Project Setting中的设置。

渲染路径原理处理光照方式15判断规则Pass缺陷
前向渲染路径1.渲染该对象的渲染图元
2.计算两个缓冲区的信息:颜色缓冲区,深度缓冲区
逐顶点
逐像素
球谐函数SH
1.最亮的平行光–逐像素处理
2.渲染模式为Not Important–逐顶点/SH处理
3.渲染模式为Important–逐像素
4.以上小于设定的值更多光源按逐像素方式
1.Base Pass
2.Additional Pass
有大量实时光源时,渲染性能降低
延迟渲染路径1.仅计算哪些片元是可见的–信息存储到G缓冲区
2.利用G缓冲中片元信息–计算真正的光照
逐像素与光源的数目无关,与屏幕空间的大小有关1.渲染G缓冲
2.计算真正的光照模型
1.不支持真正的抗锯齿
2.不能处理半透明
3.对显卡有要求
顶点照模渲染路径已废弃

1.前向渲染的两种Pass

实现光照效果渲染设置光照计算执行次数
Base Pass光照纹理、自发光、环境光、阴影Tags{“LightMode”=“ForwardBase”}
#pragma multi_compile_fwdbase}
一个逐像素的平行光以及所有逐顶点和SH光源一次
Additional Pass默认不支持阴影可用命令开启
#pragma multi_compile_fwdadd_fulls_shadows
Tags{“LightMode”=“ForwardAdd”}
Blend One One
#pragma multi_compile_fwdadd
其他影响该物体的逐像素每个光源执行一次Pass多次

2.内置光照变量

名称类型描述渲染路径使用Pass限制
_LightColor0float4该Pass处理的逐像素光源的颜色前向
_WorldSpaceLightPos0float4xyz分量是处理的逐像素光源的位置
平行光 w==0,其他光源w == 1
前向、延迟
_LightMatrix0float4x4从世界空间到光源空间的变换矩阵,可用于采样cookie和光强衰减纹理前向
unity_4LightPosX0、unity_4LightPosY0、unity_4LightPosZ0float4前4个非重要的点光源在世界空间中的位置前向Base Pass
unity_4LightAtten0float4前4个非重要的点光源的衰减因子前向Base Pass
unity_LightColorhalf4[4]前4个非重要的点光源的颜色前向Base Pass
_LightColorfloat4光源颜色延迟

3.渲染纹理
UnityShader 入门精要 作者github
彩图

4.Unity内置的时间变量

名称类型描述分量
_Timefloat4t是自该场景加载开始所经过的时间(t/20,t,2t,3t)
_SinTimefloat4t是时间的正弦值(t/8,t/4,t/2,t)
_CosTimefloat4t是时间的余弦值(t/8,t/4,t/2,t)
unity_DeltaTimefloat4dt是时间增量(dt,1/dt,smoothDt,1/smoothDt)

  1. 1.所有渲染需要的数据都要从硬盘中加载到系统内存中。
    2.网格和纹理等数据又被加载到显卡的存储空间–显存中 <== 显卡对于显存的访问速度更快。
    3.某些不需要的数据可以从RAM中移除 <==硬盘加载到RAM的过程耗时。 ↩︎

  2. 定义了场景中的网格是怎么被渲染的。eg:使用哪个顶点着色器/片元着色器、光源属性、材质等
    如果没有更改渲染状态,所有的网格都将使用同一种渲染状态。
    在这里插入图片描述 ↩︎

  3. DrawCall 就是一个命令。它的发起方:CPU,接收方:GPU。这个命令仅仅会指向一个需要被渲染的图元列表,而不会包含任何材质信息。 ↩︎

  4. 细分着色器介绍 ↩︎

  5. 几何着色器介绍 ↩︎

  6. 片元并不是真正意义上的像素,而是包含了许多状态的集合。状态包括:它的屏幕坐标、深度信息,以及其他从几何阶段输出的顶点信息,法线、纹理坐标等。 ↩︎

  7. 纹理采样:
    1.在顶点着色器阶段输出每个顶点对应的纹理坐标
    2.经过光栅化阶段对三角网格的3个顶点对应的纹理坐标进行插值
    3.得到其覆盖的片元纹理坐标。 ↩︎

  8. 主要任务:1.决定每个片元的可见性
    2.若一个片元通过了所有的测试,就需要把这个片元的颜色值与已经在缓冲区的颜色进行合并。
    在这里插入图片描述
    模板测试:在这里插入图片描述
    在这里插入图片描述 ↩︎

  9. CG代码块中访问属性 。uniform关键字:CG中修饰变量和参数的一种修饰,仅仅用于提供关于该变量的初始值是如何指定和存储相关信息。 ↩︎

  10. ↩︎
  11. 内置的纹理名称:white、black、gray、bump等。花括号 原本是用于指定一些纹理属性。后来被移除了。 ↩︎

  12. Compute Shader ↩︎

  13. 视锥体决定了哪些部分剔除,裁剪。
    视锥体是空间中的一块区域六面体组成的裁剪平面,决定了摄像机能看到的空间。两种类型:
    正交投影 :所有网格大小都一样,保持了物体的距离和角度 |视锥体为长方体型
    透视投影:模拟人眼看世界的方式 |视锥体为金字塔型 ↩︎

  14. 投影矩阵的目的:1.为投影做准备。2.对x、y、z分量进行缩放 ↩︎

  15. 决定一个光源使用哪种处理模式取决于它的类型和渲染模型。
    光源类型:该光源是平行光还是其他类型的光源
    光源的渲染模式:该光源是否是重要的(Important or Not Important) ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值