前一篇介绍了若是编写最基本的shader,接下来本文将会简单的深刻一下,咱们先来看下效果吧
呃,gif效果很差,实际效果是很平滑的动态过渡
1.首先咱们要实现一个彩色方块
2.让色彩动起来
overhtml
先看代码吧:算法
Shader "LT/Lesson2" { Properties { _OffsetX ("Offset X", Range (-1.5, 1.5) ) = 0 _OffsetY ("Offset Y", Range (-1.5, 1.5) ) = 0 _OffsetZ ("Offset Z", Range (-1.5, 1.5) ) = 0 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct VertextOutput { float4 pos : SV_POSITION ; fixed4 col : COLOR ; }; uniform float _OffsetX; uniform float _OffsetY; uniform float _OffsetZ; VertextOutput vert ( appdata_base input ) { VertextOutput result; result.pos = mul(UNITY_MATRIX_MVP , input.vertex ) ; result.col = input.vertex + float4( _OffsetX, _OffsetY, _OffsetZ, 0); return result; } fixed4 frag ( VertextOutput input ) : COLOR { return input.col; } ENDCG } } }
恩~~,首先呢,咱们此次输出的颜色不一样的位置颜色不一样,因此咱们须要一个同时能存位置和颜色的结构体:c#
struct VertextOutput { float4 pos : SV_POSITION ; // 位置信息, 后面的: SV_POSITION是必须的,固然你也能够换成: POSITION fixed4 col : COLOR ; // 颜色信息, 后面的: COLOR不是必须的,你能够随便取名字好比 : FUCK // 可是嘛,为了代码方便阅读,仍是写成COLOR吧 };
而后呢咱们只有这样一个模型:
24个顶点(每一个面顶点单算的),12个三角形,两个空的UV(这个是unity自带的cube模型)
这个模型是没有任何颜色信息,因此咱们须要本身在shader中生成他的颜色
出于方便考虑,咱们将这个模型的顶点(XYZ)变成RGB的颜色,由于恰好三个值都有变化嘛
因而有了这样的代码
result.col = input.vertex + float4( _OffsetX, _OffsetY, _OffsetZ, 0);
前面顶点位置就不做处理了,直接换算成Unity坐标就完了
result.pos = mul(UNITY_MATRIX_MVP , input.vertex ) ;app
而后咱们来讲说传入参数中的appdata_base
对于VertextOutput vert ( appdata_base input )这个函数命名
学过C语言的应该知道前面是返回值类型 括号里面是传入值类型和名字吧
而后这个appdata_base呢是定义在#include "UnityCG.cginc"的一个结构体
(强行带节奏引入了UnityCG.cginc,其实也能够像前面一篇同样使用float4 position : POSITION,只是这里为了早点引入UnityCG.cginc而已)
咱们能够看一下UnityCG.cginc的部分代码:ide
// Dynamic & Static lightmaps contain indirect diffuse ligthing, thus ignore SH #define UNITY_SHOULD_SAMPLE_SH ( defined (LIGHTMAP_OFF) && defined(DYNAMICLIGHTMAP_OFF) ) struct appdata_base { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; struct appdata_tan { float4 vertex : POSITION; float4 tangent : TANGENT; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; struct appdata_full { float4 vertex : POSITION; float4 tangent : TANGENT; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; float4 texcoord1 : TEXCOORD1; float4 texcoord2 : TEXCOORD2; float4 texcoord3 : TEXCOORD3; #if defined(SHADER_API_XBOX360) half4 texcoord4 : TEXCOORD4; half4 texcoord5 : TEXCOORD5; #endif fixed4 color : COLOR; };
整个有点小长,我只粘贴一部分,其实就是一大堆Unity的定义而已,
咱们再来看看函数
struct appdata_base { float4 vertex : POSITION; //位置 float3 normal : NORMAL; //法线 float4 texcoord : TEXCOORD0; // 纹理 };
其实这是一个简化的模型数据,包含了一些经常使用的参数,若是咱们写的shader主要是给手机使用的话,这些数据基本也就够了,并且目前咱们也就用了他的位置的信息,固然你也能够传入一个appdata_full 类型,区别不大性能
至于_OffsetX,_OffsetY,_OffsetZ三个外接属性的定义就很少作赘述了
而后咱们就经过动画
VertextOutput vert ( appdata_base input ) { VertextOutput result; result.pos = mul(UNITY_MATRIX_MVP , input.vertex ) ; result.col = input.vertex + float4( _OffsetX, _OffsetY, _OffsetZ, 0); return result; }
计算出了相应顶点的颜色
而后直接在面片渲染函数中把对应点的颜色赋值给他就好了
return input.col;
注意这里咱们的传入参数变成了vert 的返回值
fixed4 frag ( VertextOutput input ) : COLORui
好来看下初步的效果:
这里咱们就完成了一个RBG CUBE了。
下面对一些原理性的东西简单解释一下spa
前面我解释过vert函数是一个顶点调用一次,这里咱们的模型一共才24个顶点,可是为啥出来这么多个颜色呢,这里就跟渲染流程的光栅化有关。默认状况下,光栅化会保持平滑过渡,若是两边不匹配就会在中间插值,而后对于咱们的模型而言,一个面上每一个顶点的颜色都不一样,因此他就会自动插入不少个顶点,而且自动渐变颜色来知足平滑过渡(也就是说若是你颜色都同样,就不会插点了,固然你也能够手动不让它插点,概念比较多,这里就不展开了,咱们要快速上手嘛)
这里是我强行要加的一个功能,否则感受这篇blog就太少内容咯,哈哈
有两种实现方法:
1.unity中经过C#代码去控制刚才开放出来的参数
2.shader中本身经过时间去更改颜色
咱们既然是学shader,固然是在shader中进行更改啦
直接上代码:
result.col = input.vertex + float4( _SinTime.w + 0.5, _SinTime.w + 0.5, _SinTime.w + 0.5, 0);
呃,对,就改这一行。效果就是实现啦,你们能够本身行试一下
下面解释一小下下:
_SinTime是unity为shader内置的一个时间的sin值得变量(看名字也看的出来吧)
须要引入#include "UnityCG.cginc" (这也是为啥我前面强行带节奏的缘由)
而后来普及下Unity为咱们内置了哪些东西吧:
Transformations 变换 float4x4 UNITY_MATRIX_MVP Current model*view*projection matrix 当前物体*视*投影矩阵。(注:物体矩阵为 本地->世界) float4x4 UNITY_MATRIX_MV Current model*view matrix 当前物体*视矩阵 float4x4 UNITY_MATRIX_P Current projection matrix 当前物体*投影矩阵 float4x4 UNITY_MATRIX_T_MV Transpose of model*view matrix 转置物体*视矩阵 float4x4 UNITY_MATRIX_IT_MV Inverse transpose of model*view matrix 逆转置物体*视矩阵 float4x4 UNITY_MATRIX_TEXTURE0 to UNITY_MATRIX_TEXTURE3 Texture transformation matrices 贴图变换矩阵 float4x4 _Object2World Current model matrix 当前物体矩阵 float4x4 _World2Object Inverse of current world matrix 物体矩阵的逆矩阵 float3 _WorldSpaceCameraPos World space position of the camera 世界坐标空间中的摄像机位置 float4 unity_Scale xyz components unused; .w contains scale for uniformly scaled objects. 不适用xyz份量,而是经过w份量包含的缩放值等比缩放物体。 _ModelLightColor float4 Material's Main * Light color 材质的主颜色*灯光颜色 _SpecularLightColor float4 Material's Specular * Light color 材质的镜面反射(高光)*灯光颜色。 _ObjectSpaceLightPos float4 Light's position in object space. w component is 0 for directional lights, 1 for other lights 物体空间中的灯光为,平行光w份量为零其灯光为1; _Light2World float4x4 Light to World space matrix 灯光转世界空间矩阵 _World2Light float4x4 World to Light space matrix 世界转灯光空间矩阵 _Object2Light float4x4 Object to Light space matrix 物体转灯光空间矩阵 float4 _Time : Time (t/20, t, t*2, t*3), use to animate things inside the shaders 时间: 用于Shasder中可动画的地方。 float4 _SinTime : Sine of time: (t/8, t/4, t/2, t) 时间的正弦值。 float4 _CosTime : Cosine of time: (t/8, t/4, t/2, t) 时间的余弦值 float4 _ProjectionParams : 投影参数 x is 1.0 or -1.0, negative if currently rendering with a flipped projection matrix x为1.0 或者-1.0若是当前渲染使用的是一个反转的投影矩阵那么为负。 y is camera's near plane y是摄像机的近剪裁平面 z is camera's far plane z是摄像机远剪裁平面 w is 1/FarPlane. w是1/远剪裁平面 float4 _ScreenParams : 屏幕参数 x is current render target width in pixels x是当前渲染目标在像素值中宽度 y is current render target height in pixels y是当前渲染目标在像素值中的高度 z is 1.0 + 1.0/width z是1.0+1.0/宽度 w is 1.0 + 1.0/height w是1.0+1.0/高度
呃,格式不是很好看的样子,这里有连接,本身去看吧http://www.ceeger.com/Components/SL-BuiltinValues.html
有了这些东西以后呢,咱们就能够简单的根据时间变化作一些动态shader了,好比什么UV流动啊,颜色动态变化啊,动态模型(是动态模型不是模型动画哈)啥的,瞬间就高大上了有不有,性能嘛取决于你写的代码(一样的代码级别下,shader速度秒杀你在c#中写)
这一篇感受写的比较乱,主要是知识点比较杂(这理由不是很好找啊....原谅我语文老师是数学老师教大的) 主要知识点是介绍一下光栅化那个插值,这个很重要https://en.wikibooks.org/wiki/Cg_Programming/Rasterization(虽然我讲的一笔带过,你们去看看官方解释吧) 而后介绍一下UnityCG.cginc,咱们既然是写的unityshader,固然仍是要常用这个库的啦,后面还有光照,空间矩阵啥的,基本咱们要想作高级特效离不开这个库的,你们能够去看看这个库源码 了解了这些以后,就是单纯的算法了(好比怎么经过时间更改模型顶点位置实现好看的动画啥的) 恩~~~再次坦白下写的比较乱,若有疑问欢迎联系QQ:821580467一块儿探讨