3.顶点和片段着色器:
实现颜色过渡,
添加边框
//顶点片段着色器的工作流程:
//1.首先:vertexProgram收到系统传递给他的模型数据
//3.然后,把这些数据处理成我们后续需要的数据(至少包含定点的位置信息),其他的数据还包含一些文理的UV坐标以及他们的要传递的fragmentPraogram的数据
//3.然后,系统对vertexProgram输入的顶点数据进行插值计算,并将差值结果传递给frgmentProgram,最后fragemntProgram根据这些插值计算屏幕上的显示的像素颜色
Shader "CustomLearn/VertexAndFragShader" {
Properties{
//颜色设置
_myColor("Color",color) = (1,1,1,1)
//边框距离
_outLine("OutLine",Range(0,1)) = 0.1
}
SubShader{
//渲染不透明物体,IgnoreProjector指不受投影的影响
Tags{
"Queue" = "Geometry" "RenderType" = "Opaque" "IgnoreProjector" = "True"
}
//第一个通道。用来渲染物体表面的颜色
PASS{
CGPROGRAM
//告诉程序定义一个顶点着色器
#pragma vertex vert
//定义一个片段着色器
#pragma fragment frag
//使用顶点和片段的CG时,需要引入头文件UnityCG.cginc
#include "UnityCG.cginc"
//定义vertex to fragment结构体
//v2f:顶点程序到片段程序的信息传递
//本结构体传递的是位置和颜色参数
fixed4 _myColor;
struct v2f{
//该结构体中还可以包含其他的一些成员变量
//1.float4 vertex:POSTION 顶点位置
//2.float3 normal:POSTION 顶点法线
//3.float4 texcoord:TEXCOORD0 第一UV坐标
//4.float4 texcoord:TEXCOORD1 第二UV坐标
//5.float4 tangent:TANGENT切线向量(一般是用在法线贴图中)
//6.float4 color:COLOR 每个顶点的颜色
//SV_POSITON:SV前缀的变量代表SystemValue
float4 pos:SV_POSITION;
float3 color:COLOR;
};
//顶点函数,参数十一结构体,返回值也是一个结构体
//appdata_full是“UnityCG.cginc”的结构体类型
//顶点函数的参数类型可以有:
//appdata_base:包含顶点位置,法线和一个纹理坐标
//appdata_full:包含顶点的位置,法线和两个纹理坐标
//appdata_tan:包含顶点位置,法线,切线和一个的纹理坐标
//appdata_img:包含位置和一个纹理坐标
v2f vert(appdata_full v) {
v2f o;
//UNITY_MATRIX_MVP表示当前模型视图投影的矩阵
//UNITY_MATRIX_MV表示当前模型的视图矩阵
//UNITY_MATRIX_V表示当前视图矩阵
//UNITY_MATRIX_P表示当前视图投影矩阵
//UNITY_MATRIX_T_MV:转置模型视图矩阵
//UNITY_MATRIX_IT_MV:表示逆转置视图矩阵
//mul:表示矩阵相除函数
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
//彩虹色
o.color = v.vertex*0.8+0.5;
//纯色
// o.color = v.normal*0.4+0.5;
return o;
}
//片段函数,参数是v2f的结构体类型
fixed4 frag(v2f i):COLOR{
return fixed4(i.color*_myColor,1);
}
ENDCG
}
//第二个通道,用来渲染模型的边框
pass{
Name "Bordor"
Tags{
"LightModel" = "ForwardBase"}
//前方剔除
CULL Front
Lighting On
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//编译指令:编译正向渲染的基础通道
//用于正向渲染中,应用环境关照,主方向光照和顶点所需要的变体
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
//float相当于一个Range类型
float _outLine;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f{
float4 pos:POSITION;
};
v2f vert(a2v v){
v2f o;
float4 pos = mul(UNITY_MATRIX_MV,v.vertex);
float3 normal = mul(UNITY_MATRIX_IT_MV,v.normal);
pos = pos+float4(normalize(normal),0)*_outLine;
o.pos = mul(UNITY_MATRIX_P,pos);
return o;
}
fixed4 frag(v2f i):COLOR{
return fixed4(0,0,0,1);
}
ENDCG
}
}
}
例子:
1.Earth的纹理和云层:
Shader "CustomPractice/Earth" {
Properties {
//地球纹理
_EarthTex("EarthTex",2D) = "white"{}
//云的纹理
_CloudTex("CloudTex",2D) = "white"{}
}
SubShader {
Tags{"RenderType" = "Transparent"}
LOD 200
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _EarthTex;
sampler2D _CloudTex;
struct v2f{
//顶点的位置
float4 vertex:POSITION;
//纹理的坐标
fixed4 texcoord:TEXCOORD0;
};
void vert(inout v2f v){
v.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
}
fixed4 frag(v2f v):COLOR{
//渲染出地球
fixed u = v.texcoord.x+_Time*0.3;
float2 uv = float2(u,v.texcoord.y);
fixed4 earthColor = tex2D(_EarthTex,uv);
//渲染出云层
fixed uc = v.texcoord.x+_Time*0.5;
float2 uvc = float2(uc,v.texcoord.y);
fixed4 cloudColor = tex2D(_CloudTex,uvc);
cloudColor = cloudColor.r*fixed4(1,1,1,1);
//取地球和云颜色的插值
return lerp(earthColor,cloudColor,0.5);
}
ENDCG
}
}
FallBack "Diffuse"
}
2.流水的效果
Shader "CustomPractice/River" {
Properties {
//设置颜色值
_Color("Color",color) = (1,1,1,1)
//设置纹理
_MainTex("Albeo(RGB)",2D) = "white"{}
//水流速度X
_RiverSpeedX("X_Speed",Range(2,10)) = 5
//水流速度
_RiverSpeedY("Y_Speed",Range(2,10))= 5
}
SubShader {
Tags{"RenderType" = "Opaque"}
CGPROGRAM
//使用漫反射的光照模型
#pragma surface surf Lambert
//CG程序中要使用外部输入的值,定义变量是,一定要与属性里面的变量名一致
sampler2D _MainTex;
fixed4 _Color;
fixed _RiverSpeedX;
fixed _RiverSpeedY;
//输入结构体
struct Input{
float2 uv_MainTex;
};
void surf(Input IN,inout SurfaceOutput o){
fixed xSpeed = _RiverSpeedX*_Time;
fixed ySpeed = _RiverSpeedY*_Time;
//使用内置的_Time变量来根据运行时间滚动Texture
fixed2 uv = IN.uv_MainTex+fixed2(xSpeed,ySpeed);
fixed4 c = tex2D(_MainTex,uv)*_Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
3.三种任务模型不同效果的对比
(1):法线贴图
Shader "CustomPractice/David01" {
Properties {
_MainTex("MainTexture",2D) = "white"{}
}
SubShader {
Tags{"RenderType" = "Opaque"}
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
struct v2f{
float4 vertex:POSITION;
fixed4 texcoord:TEXCOORD0;
};
void vert(inout v2f v){
//将模型中的点转到屏幕中的位置
v.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
}
fixed4 frag(v2f v):COLOR{
//片段方法:负责每个顶点在屏幕中的颜色
//通过纹理坐标在纹理图片上进行采样,进行输出
return tex2D(_MainTex,v.texcoord);
}
ENDCG
}
}
FallBack "Diffuse"
}
(2)透明
Shader "CustomPractice/David02" {
Properties {
_MainTex("Albedo(RGB)",2D) = "white"{}
_LogoTex("LogoTexture",2D) = "white"{}
}
SubShader {
Tags{"RenderType" = "Transparent"}
//透明设置
Blend SrcAlpha OneMinusSrcAlpha
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.CGINC"
sampler2D _MainTex;
sampler2D _LogoTex;
void vert(inout appdata_base v){
v.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
}
fixed4 frag(appdata_base v):COLOR{
fixed4 col = tex2D(_MainTex,v.texcoord);
fixed4 logo = tex2D(_LogoTex,v.texcoord);
return col*logo;
}
ENDCG
}
}
FallBack "Diffuse"
}
(3)卡通
Shader "CustomPractice/David03" {
Properties {
_MainTex("MainTexture",2D) = "white"{}
_BumpTex("BumpTexture",2D) = "white"{}
_EmssionColor("EmssionColor",Color) = (1,1,1,1)
isEnter("IsEnter",int) = 0
//卡通度
Cartoon("Cartoon",Range(-0.05,0.05)) = 0.00
}
SubShader {
Tags{"RenderType" = "Opaque"}
CGPROGRAM
//自定义光照,模型
#pragma surface surf CustomLighting vertex:vert
//主纹理
sampler2D _MainTex;
//法线纹理
sampler2D _BumpTex;
//高光颜色
fixed4 _EmssionColor;
//判断条件
fixed isEnter;
//缩放系统
float Cartoon;
struct Input{
fixed2 uv_MainTex;
fixed2 uv_BumpTex;
//视觉方向
float3 viewDir;
};
//注意:自定义光照模型名字前一定要加Lighting
half4 LightingCustomLighting(SurfaceOutput o,half3 lightDir,half atten){
half4 result;
half4 nDot = dot(lightDir,o.Normal);
nDot = nDot*0.5+0.5;
//_LightColor0:表示当前光照颜色,由系统填充
result.rgb = o.Albedo * _LightColor0.rgb * nDot*atten;
return result;
}
//顶点方法:所有纹处理完之后才会执行这个方法来移动顶点
void vert(inout appdata_full v){
v.vertex.xyz+= v.normal.xyz*Cartoon;
}
void surf(Input IN,inout SurfaceOutput o){
fixed4 albedo = tex2D(_MainTex,IN.uv_MainTex);
o.Albedo = albedo;
//采样法线纹理
fixed4 bump = tex2D(_BumpTex,IN.uv_BumpTex);
if(isEnter>0){
//求视觉方向上的单位向量
float3 view = normalize(IN.viewDir);
//计算法线和视觉方向上的点积
float value = dot(view,o.Normal);
//限制一下范围
value = 1-saturate(value);
//边缘视觉高光现象
o.Emission=_EmssionColor*value*isEnter;
}
}
ENDCG
}
FallBack "Diffuse"
}
第一个是系统提供的Shader。
====================================================================================================================
下面是对上次一个用表面着色器写的云图的修正
Shader "CustomLearn/Five 1" {
Properties{
_MainTex("Albedo RGB", 2D) = "white"{}
_Color("Color", color) = (0,0,0,1)
_Alpha("Alpha", Range(0.5,1)) = 0.6
_SpeedX("X_Speed",Range(0.5,10)) = 0.6
_SpeedY("Y_Speed",Range(0.5,10)) = 0.6
}
SubShader{
Tags {"RenderType" = "Transparent"}
LOD 200
CGPROGRAM
//alpha 便是透明度
#pragma surface surf Lambert alpha
sampler2D _MainTex;
fixed4 _Color;
half _Alpha;
half _SpeedX;
half _SpeedY;
struct Input{
float2 uv_MainTex;
};
void surf(Input IN, inout SurfaceOutput o){
fixed xSpeed = _SpeedX * _Time;
fixed ySpeed = _SpeedY * _Time;
fixed2 uv = IN.uv_MainTex - fixed2(xSpeed,ySpeed);
fixed4 c = tex2D(_MainTex, uv);
o.Albedo = _Color * c.rgb;
// o.Alpha = _Color.a * c.a * _Alpha;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
效果图太大了没传上来……