-
课时27 Vertex Shader - 顶点数据的输入与输出 1
1.一个函数有多个重复语义输出会报错,如果需要多输出的话,除了POSITION和COLOR,float2格式的TEXCOORD系列也可以。
2.POSITION语义的向量,第四个分量不能为0。
3.语义是为了方便函数间传递信息,函数内部可以对不同语义但相同类型的变量进行操作。
-
课时28 Vertex Shader - 顶点数据的输入与输出 2
Shader "Custom/Lesson28"
{
//课时28 Vertex Shader - 顶点数据的输入与输出 2
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//需要使用前定义
//可以使用c语言风格,一般用不到
typedef struct{
float4 pos:PoSITION;
float2 objPos:TEXCOORD0;
fixed4 col:COLOR;
}v2f;
//返回值为自定义结构体时,不需要语义
v2f vert (in float2 objPos:POSITION)
{
v2f o;
o.pos=float4(objPos,0,1);
o.objPos=float2(1,0);
o.col=float4(0,1,0,1);
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.col;
}
//片元程序可以不用v2f结构接收也可以(输入输出语义相同即可)
//接收一个顶点程序没有赋值的参数,比如COLOR,会收到默认值白色
fixed4 frag111 (in float2 opos:TEXCOORD0, in float4 col:COLOR):COLOR
{
// col=(0,0,0,1);
// return col;
return col;
return fixed4(opos,0,1);
}
ENDCG
}
}
}
效果:
-
课时29 Vertex Shader - 更好的数据组织方式struct
Shader "Custom/Lesson29"
{
//课时29 Vertex Shader - 更好的数据组织方式struct
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//需要使用前定义
//可以使用c语言风格,一般用不到
//一般不会定义在cginc中
typedef struct{
float4 pos:PoSITION;
float2 objPos:TEXCOORD0;
fixed4 col:COLOR;
}v2f;
//可以声明在自定义cginc文件中(UnityCG.cginc已包含appdata_base,appdata_tan,appdata_full)
struct appdata_base{
float2 pos:POSITION;
float4 col:COLOR;
};
//顶点函数的输入和输出都可以用结构体
v2f vert (appdata_base v)
{
v2f o;
o.pos=float4(v.pos,0,1);
o.objPos=float2(1,0);
o.col=v.col;//使用模型顶点颜色(默认白色)作为返回
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.col;
}
ENDCG
}
}
}
效果:
-
课时30 Vertex Shader - Uniform 与 properties属性
Shader "Custom/Lesson30"
{
//课时30 Vertex Shader - Uniform 与 properties属性
Properties{
_MainColor("Main Color",color)=(1,1,1,1)
// _MainTex("Texture",2D)="white"{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//需要在CG代码块中重新声明
//类型需要变化
float4 _MainColor;
//uniform需要在C#中赋值,默认黑色
//赋值语句:GetComponent<Renderer>().material.SetVector("_SecondColor",new Vector4(1,0,0,1));
uniform float4 _SecondColor;
//需要使用前定义
//可以使用c语言风格,一般用不到
//一般不会定义在cginc中
typedef struct{
float4 pos:PoSITION;
float2 objPos:TEXCOORD0;
fixed4 col:COLOR;
}v2f;
//可以声明在自定义cginc文件中(UnityCG.cginc已包含appdata_base,appdata_tan,appdata_full)
struct appdata_base{
float2 pos:POSITION;
float4 col:COLOR;
};
//顶点函数的输入和输出都可以用结构体
v2f vert (appdata_base v)
{
v2f o;
o.pos=float4(v.pos,0,1);
o.objPos=float2(1,0);
o.col=v.col;//使用模型顶点颜色(默认白色)作为返回
return o;
}
fixed4 frag (v2f IN):COLOR
{
// return _MainColor*_SecondColor;
// return _MainColor*0.5+0.5*_SecondColor;
return lerp(_MainColor,_SecondColor,0.7);
}
ENDCG
}
}
}
效果:
-
课时31 Vertex Shader - 几何变换 —MVP矩阵变换 1
Shader "Custom/Lesson31"
{
//课时31 Vertex Shader - 几何变换 —MVP矩阵变换 1
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float4x4 mvp;//uniform可有可无
struct v2f{
float4 pos:PoSITION;
};
//顶点函数的输入和输出都可以用结构体
v2f vert (appdata_base v)
{
v2f o;
//变换矩阵,见https://docs.unity3d.com/Manual/SL-BuiltinFunctions.html
// o.pos=UnityObjectToClipPos(v.vertex);
o.pos=mul(mvp,v.vertex);
return o;
}
fixed4 frag ():COLOR
{
return fixed4(1,1,1,1);
}
ENDCG
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//自己写MVP变换
public class MVPTransform : MonoBehaviour {
// Update is called once per frame
void Update () {
// Matrix4x4 mvp=transform.localToWorldMatrix*Camera.main.worldToCameraMatrix*Camera.main.projectionMatrix;
//正确顺序:与uniform中相反
Matrix4x4 mvp=Camera.main.projectionMatrix*Camera.main.worldToCameraMatrix*transform.localToWorldMatrix;
GetComponent<Renderer>().material.SetMatrix("mvp",mvp);
}
}
效果:场景视图的效果不正确,不用管,因为代码中用的是游戏摄像机进行变换。
-
课时32 Vertex Shader - 几何变换 —MVP矩阵变换 2
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/Lesson32"
{
//课时32 Vertex Shader - 几何变换 —MVP矩阵变换 2
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float4x4 mvp;//uniform可有可无
float4x4 rm;//旋转矩阵
float4x4 sm;//缩放矩阵
struct v2f{
float4 pos:PoSITION;
};
//顶点函数的输入和输出都可以用结构体
v2f vert (appdata_base v)
{
v2f o;
o.pos=mul(rm,v.vertex);//绕y轴旋转
o.pos=mul(sm,o.pos);//缩放
// o.pos=mul(mvp,o.pos);
o.pos=UnityObjectToClipPos(o.pos);
return o;
}
fixed4 frag ():COLOR
{
return fixed4(1,1,1,1);
}
ENDCG
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//自己写MVP变换
//使模型渲染过程中自旋转
public class MVPTransform_Lesson32 : MonoBehaviour {
// Update is called once per frame
void Update () {
//旋转矩阵,绕y轴旋转。注:shader中不能用四元数
Matrix4x4 RM=new Matrix4x4();
RM[0,0]=Mathf.Cos(Time.realtimeSinceStartup);
RM[0,2]=Mathf.Sin(Time.realtimeSinceStartup);
RM[1,1]=1;
RM[2,0]=-Mathf.Sin(Time.realtimeSinceStartup);
RM[2,2]=Mathf.Cos(Time.realtimeSinceStartup);
RM[3,3]=1;
//缩放矩阵
Matrix4x4 SM=new Matrix4x4();
SM[0,0]=Mathf.Sin(Time.realtimeSinceStartup)/4+0.5f;
SM[1,1]=Mathf.Cos(Time.realtimeSinceStartup)/8+0.5f;
SM[2,2]=Mathf.Sin(Time.realtimeSinceStartup)/6+0.5f;
SM[3,3]=1;
//MVP矩阵
Matrix4x4 mvp=Camera.main.projectionMatrix*Camera.main.worldToCameraMatrix*transform.localToWorldMatrix;
GetComponent<Renderer>().material.SetMatrix("rm",RM);//设置自定义旋转矩阵
GetComponent<Renderer>().material.SetMatrix("sm",SM);//设置自定义缩放矩阵
// GetComponent<Renderer>().material.SetMatrix("mvp",mvp);//设置自定义mvp
}
}
效果:
-
课时33 Vertex Shader - 几何变换 —顶点颜色变换 1
Shader "Custom/Lesson33"
{
//课时33 Vertex Shader - 几何变换 —顶点颜色变换 1
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float4x4 mvp;//uniform可有可无
float4x4 rm;//旋转矩阵
float4x4 sm;//缩放矩阵
struct v2f{
float4 pos:PoSITION;
fixed4 color:COLOR;
};
v2f vert (appdata_base v)
{
v2f o;
// o.pos=mul(rm,v.vertex);//绕y轴旋转
// o.pos=mul(sm,o.pos);//缩放
// o.pos=mul(mvp,o.pos);
o.pos=UnityObjectToClipPos(v.vertex);
//-------指定模型空间位于模型坐标中心两侧的颜色--------
// if(v.vertex.x>0)
// {
// o.color=fixed4(1,0,0,1);
// }else
// {
// o.color=fixed4(0,0,1,1);
// }
//-------end--------
//-------指定模型空间某个顶点的颜色--------
if(v.vertex.x==0.5 && v.vertex.y==0.5 && v.vertex.z==0.5)
{
o.color=fixed4(_SinTime.w/2+0.5,_CosTime.w/2+0.5,_SinTime.y/2+0.5,1);//_SinTime.w范围-1~1
}else
{
o.color=fixed4(0,0,1,1);
}
//-------end--------
//-------指定世界空间位于原点两侧的颜色--------
// float3 wpos=mul(unity_ObjectToWorld,v.vertex);//新版unity中, _Object2World 替换为 unity_ObjectToWorld
// if(wpos.x>0)
// {
// o.color=fixed4(1,0,0,1);
// }else
// {
// o.color=fixed4(0,0,1,1);
// }
//-------end--------
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.color;
}
ENDCG
}
}
}
效果:
-
课时34 Vertex Shader - 几何变换 —顶点颜色变换 2
Shader "Custom/Lesson34"
{
//课时34 Vertex Shader - 几何变换 —顶点颜色变换 2
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float dis;//uniform可有可无
float r;
struct v2f{
float4 pos:PoSITION;
fixed4 color:COLOR;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//齐次空间坐标
//--------根据屏幕空间坐标,设置从左到右的顶点颜色变换--------
float x=o.pos.x/o.pos.w;
if(x>dis && x<dis+r)
o.color=fixed4(1,0,0,1);
else if(x>=1)
o.color=fixed4(0,0,1,1);
else
o.color=fixed4(x/2+0.5,x/2+0.5,x/2+0.5,1);
//--------end--------
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.color;
}
ENDCG
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SetFloat : MonoBehaviour {
private float dis=-1;
private float r=0.1f;
// Update is called once per frame
void Update () {
dis+=Time.deltaTime*0.1f;
GetComponent<Renderer>().material.SetFloat("dis",dis);
GetComponent<Renderer>().material.SetFloat("r",r);
}
}
效果:
-
课时35 Vertex Shader - 几何变换 —顶点位移
Shader "Custom/Lesson35"
{
//课时35 Vertex Shader - 几何变换 —顶点位移
Properties{
_R ("R" , range(0,5))=1
_OX("OX",range(-5,5))=0
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float dis;
float r;
float _R;
float _OX;
struct v2f{
float4 pos:PoSITION;
fixed4 color:COLOR;
};
v2f vert (appdata_base v)//参数传递用的值拷贝
{
//顶点变换要在齐次变换之前进行
float4 wpos=mul(unity_ObjectToWorld,v.vertex);//求得世界空间坐标值
float2 xy=wpos.xz;//xy是世界空间二维向量
float d=_R-length(xy-float2(_OX,0));//求得与世界坐标系原点的距离的反比
d=d<0?0:d;
float height=1*d;
float4 uppos=float4(v.vertex.x,height,v.vertex.z,v.vertex.w);//求得模型坐标系下改变y轴的值
v2f o;
o.pos=UnityObjectToClipPos(uppos);//齐次空间坐标
o.color=fixed4(uppos.y,uppos.y,uppos.y,1);
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.color;
}
ENDCG
}
}
}
效果:几个拼接的模型做顶点位移
-
课时36 Vertex Shader - 几何变换 —扭曲
Shader "Custom/Lesson36"
{
//课时36 Vertex Shader - 几何变换 —扭曲
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
struct v2f{
float4 pos:PoSITION;
fixed4 color:COLOR;
};
v2f vert (appdata_base v)
{
v2f o;
float angle=length(v.vertex)*_SinTime.w;
//---------------常规旋转计算---------------------
// float4x4 m ={
// float4(cos(angle),0,sin(angle),0),
// float4(0,1,0,0),
// float4(-sin(angle),0,cos(angle),0),
// float4(0,0,0,1)
// };
// v.vertex=mul(m,v.vertex);
//----------------end--------------------
//----------------简化后的旋转计算--------------------
// float x=cos(angle)*v.vertex.x+sin(angle)*v.vertex.z;
// float z=cos(angle)*v.vertex.z-sin(angle)*v.vertex.x;
// v.vertex.x=x;
// v.vertex.z=z;
//----------------end--------------------
//---------------常规缩放计算---------------------
// angle=v.vertex.z+_Time.y;
// float4x4 m ={
// float4(sin(angle)/8+0.5,0,0,0),
// float4(0,1,0,0),
// float4(0,0,1,0),
// float4(0,0,0,1)
// };
// v.vertex=mul(m,v.vertex);
//----------------end--------------------
//---------------简化后的缩放计算---------------------
angle=v.vertex.z+_Time.y;
v.vertex.x=(sin(angle)/8+0.5)*v.vertex.x;
//----------------end--------------------
o.pos=UnityObjectToClipPos(v.vertex);//齐次空间坐标
o.color=fixed4(0,1,1,1);
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.color;
}
ENDCG
}
}
}
效果:
-
课时37 Vertex Shader - 几何变换 —波
课前知识准备:正弦曲线可表示为y=Asin(ωx+φ)+k,定义为函数y=Asin(ωx+φ)+k在直角坐标系上的图象,其中sin为正弦符号,x是直角坐标系x轴上的数值,y是在同一直角坐标系上函数对应的y值,k、ω和φ是常数(k、ω、φ∈R且ω≠0)
A——振幅,当物体作轨迹符合正弦曲线的直线往复运动时,其值为行程的1/2。
(ωx+φ)——相位,反映变量y所处的状态。
φ——初相,x=0时的相位;反映在坐标系上则为图像的左右移动。
k——偏距,反映在坐标系上则为图像的上移或下移。
ω——角速度, 控制正弦周期(单位弧度内震动的次数)。
Shader "Custom/Lesson37"
{
//课时37 Vertex Shader - 几何变换 —波
SubShader
{
Pass
{
CGPROGRAM
#include "unitycg.cginc"
#pragma vertex vert
#pragma fragment frag
struct v2f{
float4 pos:PoSITION;
fixed4 color:COLOR;
};
v2f vert (appdata_base v)
{
//=============常规缩放方式(y轴为0,无效)====================
// float up=sin(v.vertex.x)+_Time.y;
// float4x4 m={
// float4(1,0,0,0),
// float4(0,sin(up)/8+0.5,0,0),
// float4(0,0,1,0),
// float4(0,0,0,1)
// };
// v.vertex=mul(m,v.vertex);
//============end=====================
//=============正弦波横波方式====================
// v.vertex.y+=0.2*sin(v.vertex.z*2+_Time.y);
//============end=====================
//=============正弦波中心点向外扩散方式====================
// v.vertex.y+=0.2*sin(-length(v.vertex.xz)+_Time.y);
//============end=====================
//=============正弦波xz方向分布式方式====================
v.vertex.y+=0.2*sin(-length(v.vertex.x+v.vertex.z)+_Time.y);
v.vertex.y+=0.3*sin(-length(v.vertex.x-v.vertex.z)+_Time.w);
//============end=====================
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);//齐次空间坐标
o.color=fixed4(v.vertex.y,v.vertex.y,v.vertex.y,1);
return o;
}
fixed4 frag (v2f IN):COLOR
{
return IN.color;
}
ENDCG
}
}
}
效果: