UnityShader系列文章转载于 @浅墨_毛星云,为本人的学习笔记,转载请注明出处。
文章链接:https://blog.csdn.net/poem_qianmo/article/details/41175585
子着色器结构
Subshader{ [Tags] [CommonState] Passdef [Passdef ...] }
即通过可选标签,通用状态和一个Pass定义的列表构成了子着色器。
子着色器标签
子着色器使用标签来告诉渲染引擎期望何时和如何渲染对象。其语法结构如下
Tags { "TagName1" ="Value1" "TagName2" = "Value2" }
决定渲染次序——队列标签
使用Queue标签来决定对象被渲染的次序。
四种预定义的渲染队列
-
后台(Background)
-
这个渲染队列在所有队列之前被渲染,被用于渲染天空盒之类的对象
-
-
几何体(Geometry,默认值)
-
这个队列被用于大多数对象。不透明的几何体使用这个队列
-
-
透明(Transparent)
-
这个渲染队列在几何体队列之后被渲染,采用由后到前的次序。任何采用alpha混合的对象(也就是不对深度缓冲产生写操作的着色器)应该在这里渲染(如玻璃,粒子效果等)
-
-
覆盖(Overlay)
-
这个渲染队列被用于实现叠加效果。任何需要最后渲染的对象应该放置此处(如镜头光晕等)
-
一个Tags的示例
Shader "Transparent QueueExample"
{
SubShader
{
//写上Tags标签
Tags {"Queue" = "Transparent" }
//开始一个通道
Pass
{
// 写Shader实体内容
}
}
}
自定义中间队列
在Unity实现中每一个队列都被一个整数的索引值所代表。后台为1000,几何体为2000,透明度为3000,叠加层为4000.着色器可以自定义一个队列,如:
Tags { "Queue" ="Geometry+1" }
因为渲染队列是从小到大来数的,这就会使对象在所有不透明的对象之后但却在所有透明物体前被渲染,该渲染队列的索引值为2001
通道
Pass通道块控制被渲染的对象的几何体。其语法定义是这样的:
Pass { [Name and Tags] [RenderSetup][TextureSetup] }
基本通道命令包含一个可选的渲染设置命令的列表,和可选的被使用的纹理的列表
通道中的名称与标签
Tags { "TagName1" ="Value1" "TagName2" = "Value2" }
内部的Pass标签用来控制光照管道(环境光照,顶点光照和像素光照)中pass的任务和一些其他选项。
光照模式标签
-
Always
-
总是渲染。没有运用光照
-
-
ForwardBase
-
用于正向渲染,环境光、方向光和顶点光等
-
-
ForwardAdd
-
用于正向渲染,用于设定附加的像素光,每个光照对应一个pass
-
-
PrepassBass
-
用于延迟光照,渲染法线/镜面光
-
-
PrepassFinal
-
用于延迟光照,通过结合纹理,光照和自发光渲染最终颜色
-
-
Vertex
-
用于顶点光照渲染,当物体没有光照映射时,应用所有的顶点光照
-
-
VertexLMRGBM
-
用于顶点光照渲染,当物体有光照映射的时候使用顶点光照渲染。在平台上光照映射时RGBM编码
-
-
VertexLM
-
用于顶点光照渲染,当物体有光照映射的时候使用顶点光照渲染。在平台上光照映射是double-LDR编码(移动平台,及老式台式CPU)
-
-
ShadowCaster
-
使物体投射阴影
-
-
ShadowCollector
-
为正向渲染对象的路径,将对象的阴影收集到屏幕空间缓冲区中
-
渲染设置
通道设定显示硬件的各种状态,例如能打开alpha混合,能使用雾,等等。这些命令如下:
-
Material{Material Block}
-
定义一个使用顶点光照管线的材质
-
-
Lighting On|Off
-
开启或关闭顶点光照。开启灯光之后,顶点光照才会有作用。只有开启了顶点光照,顶点光照管线的材质才会起作用。
-
-
Cull Back|Front|Off
-
设置多边形剔除模式
-
-
ZTest(Less|Greater|LEqual|Equal|NotEqual|Always)
-
设置深度测试模式
-
-
ZWrite On|Off
-
设置深度写模式
-
-
Fog{Fog Block}
-
设置雾参数
-
-
AlphaTex(Less|Greater|LEqual|Equal|NotEqual|Always) CutoffValue
-
开启alpha测试
-
-
Blend SourceBlendMode | DestBlendMode
-
设置alpha混合模式
-
-
Color Colorvalue
-
设置当顶点光照关闭时使用的颜色
-
-
ColorMask RGB|A|0|any combination of R,G,B,A
-
设置颜色写遮罩。设置为0将关闭所有颜色通道的渲染
-
-
Offset OffsetFactor,OffsetUnits
-
设置深度偏移
-
-
SeparateSpecular On|Off
-
开启或关闭顶点光照相关的平行高光颜色
-
-
ColorMaterial AmbientAndDiffuse | Emission
-
当计算顶点光照时使用每顶点的颜色
-
纹理设置
在完成渲染设定后,我们可以指定一定数量的纹理和当使用SetTexture命令时所采用的混合模式:
SetTexture [texture property]{ [Combineoptions] }
纹理设置,用于配置固定函数多纹理管线,当自定义fragment shaders被使用时,这个设置会被忽略掉
一些细节
-
每像素光照(Per-pixel Lighting)
-
每像素光照管线通过多次通道渲染对象来完成。Unity渲染对象一次来获取阴影色和任何顶点光照。然后再在额外的并行通道中渲染出每像素光照的效果
-
-
每顶点光照(Per-vertex Lighting)
-
每顶点光照是标准的Direct3D/OpendGL光照模式,通过计算每个顶点的光照来完成。Lighting on命令开启光照。光照被材质块,颜色材质和平行高光等命令所影响。
-
纹理(Texturing)
纹理在基本的顶点光照计算完成之后被应用,这也就是SetTexture命令必须放置在通道的末尾的原因了。在着色器中通过SetTexture命令来完成。需要注意的是,SetTexture命令在使用了片段着色器时不会生效;因为片段着色器下像素操作被完全描述在着色器中。
材质贴图可以用来实现旧式风格的混合器效果。我们可以在一个通道中使用多个SetTexture命令,SetTexture所有纹理都是按代码顺序添加的。
SetTexture [TexturePropertyName] { TextureBlock }
纹理块中能执行3种命令:合并操作、矩阵操作、与常量颜色进行混合操作
纹理合并命令
-
combine src1*src2
-
将源1和源2的元素相乘。结果会比单独输出任何一个都要暗
-
-
combine src1 + src2
-
将源1和源2的元素相加。结果会比单独输出任何一个都要亮
-
-
combine src1 - src2
-
源1 减去 源2
-
-
combine src1 +- src2
-
先相加,然后减去0.5
-
-
combine src1 lerp(src2) src3
-
使用源2的透明度通道值在源3和源1中进行差值,注意差值是反向的:当透明度值是1使用源1,透明度为0时使用源3
-
-
combine src1*src2+src3
-
源1和源2的透明度相乘,然后加上源3
-
-
combine src1*src2+-src3
-
源1和源2的透明度相乘,然后和源3做符号加
-
-
combine src1*src2 -src3
-
源1和源2的透明度相乘,然后和源3相减
-
-
其中,所有的src属性都可以是previous、constant、primary or texture其中一个
-
Previous是上一次SetTexture的结果
-
Primary是来自光照计算的颜色或是当它绑定时的顶点颜色
-
Texture是在SetTexture中被定义的纹理颜色
-
Constant是被ConstantColor定义的颜色
-
一些小技巧:
1.上述的公式都均能通过关键字 Double 或是 Quad 将最终颜色调高亮度2倍或4倍。
2.所有的src属性,除了差值参数都能被标记一个“-”负号来使最终颜色反相。
3.所有src属性能通过跟随 alpha 标签来表示只取用alpha通道。
颜色常量命令
ConstantColor color
定义在combine命令中能被使用的常量颜色
纹理矩阵命令
matrix [MatrixPropertyName]
使用给定矩阵变换纹理坐标
一些细节命令
-
分离的透明度和颜色混合(Separate Alpha & Color computation)
在默认情况下,混合公式被同时用于计算纹理的RGB通道和透明度。同时,我们也能指定针对透明度来单独计算,比如,将RGB操作和Alpha操作隔开:
SetTexture [_MainTex] { combine previous *texture, previous + texture }
如上所述,我们对RGB的颜色做乘然后对Alpha透明度相加
-
反射高光(Specular highlights)
默认情况下primary颜色是漫反射,阴影色和高光颜色(在光线计算中定义)的加和。如果我们将通道设置中的SeparateSpecular On开启,高光色便会在混合计算后被加入,而不是之前。
综合应用
Shader "typedef/Volume2/顶点光照+自发光混合+纹理混合" {
Properties {
_IlluminCol("自发光颜色" ,Color) = (1,1,1,1)
_Color ("主颜色", Color) = (1,1,1,1)
_SpecCol("高光颜色",Color) = (1,1,1,1)
_EmissionCol("光泽颜色",Color) = (1,1,1,1)
_Shininess("光泽度",Range(0.01,1)) = 0.7
_MainTex ("基础纹理", 2D) = "white" {}
_BlendTex("混合纹理", 2D) = "white" {}
}
SubShader {
//通道
Pass{
//材质,需要开启光照,否则不起作用
Material{
//主颜色
Diffuse[_Color]
Ambient[_Color]
//高光颜色
Specular[_SpecCol]
//光泽颜色
Emission[_EmissionCol]
//光泽度
Shininess[_Shininess]
}
//开启光照
Lighting On
//开启独立镜面反射
SeparateSpecular On
//将自发光颜色与纹理混合
SetTexture[_MainTex]{
constantColor[_IlluminCol]
combine constant Lerp(texture) previous
}
//乘上基础纹理
SetTexture[_MainTex]{
combine previous * texture
}
//乘上混合纹理
SetTexture[_BlendTex]{
combine previous * texture
}
//乘上顶点纹理
SetTexture[_MainTex]{
combine previous * primary DOUBLE,previous * primary
}
}
}
FallBack "Diffuse"
}