您的位置:首页 > 理论基础

Shader 基础使用(三) ----- vertex & fragment

2017-08-10 13:58 417 查看
基本数据类型与surface一致,就不在此文章赘述了

顶点语义绑定

float4 POSITION 顶点坐标位置

float3 NORMAL 顶点法线向量坐标

float4 TEXCOORD0 第一个UV坐标

float4 TEXCOORD1..N 第二个到第N个UV坐标

float4 TENGENT 顶点切线向量坐标

float4 COLOR 顶点颜色值

常用函数库

HLSLSupport.cginc 辅助为跨平台的着色器编译宏和定义

UnityShaderVariables.cginc 常⽤用全局变量量

UnityCG.cginc 常⽤用辅助函数

AutoLight.cginc 光、影函数

Lighting.cginc 光照模型相关

TerrainEngine.cginc 地形植被辅助

首先我们应该知道顶点片段着色器的基本框架

Shader "MyVFShader/VFShader_001"
{
Properties
{
}
SubShader
{
Pass
{
CGPROGRAM
//预编译指令关键词  |  函数类型  |  函数名
#pragma vertex vert  //vertex 是顶点着色器
#pragma fragment frag // fragment 是片段着色器
void vert(){}
void frag(){}
ENDCG
}
}
}


接下来先来用顶点片段着色器写一个纯色的Shader

Shader "MyVFShader/VFShader_002"
{
Properties
{
_MainColor("颜色",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
//预编译指令关键词  |  函数类型  |  函数名
#pragma vertex vert  //vertex 是顶点着色器
#pragma fragment frag // fragment 是片段着色器
//输入一个顶点坐标 名称vertexPos 语义绑定POSITION
//输出一个像素坐标 语义绑定SV_POSITION
float4 vert(float4 vertexPos:POSITION):SV_POSITION
{
//老版本写法(Model View Project矩阵变幻,得到每个像素的坐标位置)
return UnityObjectToClipPos(vertexPos);
//新版本写法UnityObjectToClipPos(顶点坐标)
return UnityObjectToClipPos(vertexPos);
}
float4 _MainColor;
//无输入 输出内插值颜色
float4 frag():COLOR
{
return _MainColor;
}
ENDCG
}
}
}

/*
我们来说一下步骤和思路 做一个总结

首先看顶点函数
1.参数 --> 每个顶点的坐标位置 语义绑定是POSITION 类型是float4
2.返回值 --> 每个顶点的像素位置 语义绑定是SV_POSITION 类型是float4
3.顶点函数的作用:就是将三维空间坐标投影到二维窗口
然后看片段函数
1.参数 --> 片段函数没有参数
2.返回值 --> 片段的颜色值 语义绑定COLOR 类型是float4
3.片段函数的作用:就是给片段颜色赋值,也就是设置片段颜色
*/


如果感觉纯色的太局限了 我们来写一下彩色的看看效果

Shader "MyVFShader/VFShader_003"
{
Properties
{
//_ColorOffset("颜色偏移量",Range(0,1)) = 0.5
_ROffset("红色偏移量",Range(0,1)) = 0
_GOffset("绿色偏移量",Range(0,1)) = 0
_BOffset("蓝色偏移量",Range(0,1)) = 0
}
SubShader
{
Pass
{
CGPROGRAM
//预编译指令关键词  |  函数类型  |  函数名
#pragma vertex vert  //vertex 是顶点着色器
#pragma fragment frag // fragment 是片段着色器
//顶点输出的结构体
struct V2F
{
//像素坐标
float4 position:POSITION;
//0级纹理坐标(可以理解为像素的颜色)
float4 color:TEXCOORD0;
};

float _ROffset;
float _GOffset;
float _BOffset;
//顶点函数
//输入一个顶点坐标 名称vertexPos 语义绑定POSITION
V2F vert(float4 vertexPos:POSITION)
{
//声明结构体
V2F v2f;
//通过顶点坐标求像素坐标
v2f.position = UnityObjectToClipPos(vertexPos);
//顶点坐标当做颜色值设置成像素颜色
//通过红,绿,蓝三个颜色的偏移量来修改颜色的变化
v2f.color = vertexPos + float4(_ROffset,_GOffset,_BOffset,0);
//返回
return v2f;
}
//片段函数
float4 frag(V2F v2f):COLOR
{
return v2f.color;
}
ENDCG
}
}
}

/*
我们来说一下步骤和思路 做一个总结

顶点着⾊色器器输出结构体
1.float4 postion:SV_POSITION 空间位置
2.float4 color:TEXCOORD0 0级纹理理坐标
首先看顶点函数
1.参数 --> 每个顶点的坐标位置 语义绑定是POSITION 类型是float4
2.返回值 --> 输出结构体
3.顶点函数的作用:将三维空间坐标投影到⼆维口,颜⾊值设置为顶点坐标+偏移量(营造彩虹效果)
然后看片段函数
1.参数 --> 顶点着⾊器输出结构体
2.返回值 --> 片段的颜色值 语义绑定COLOR 类型是float4
3.片段函数的作用:直接将顶点输出的颜色设置到片段显示
*/


由浅至深的 接下来 我们看一下顶点片段着色器的漫反射应该怎样实现

Shader "MyVFShader/VFShader_004"
{
Properties
{
_Color("颜色",Color) = (1,0,0,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex ver
#pragma fragment frag
//引用库
#include "UnityCG.cginc"
//声明外部颜色变量
float4 _Color;
//声明内部光照颜色变量
float4 _LightColor0;
//顶点函数输入结构体
struct appData
{
//顶点坐标
float4 vertexPos:POSITION;
//顶点法线
float3 normal:NORMAL;
};

struct V2F
{
//像素坐标
float4 position:SV_POSITION;
//像素法线
float3 normal:NORMAL;
};
//顶点函数
V2F ver(appData data)
{
//定义输出结构体
V2F v2f;
//坐标系转换
v2f.position = UnityObjectToClipPos(data.vertexPos);
//从顶点法线 到 像素法线
v2f.normal = mul(float4(data.normal,0),unity_WorldToObject).xyz;
//返回
return v2f;
}
//片段函数
float4 frag(V2F v2f):COLOR
{
//求法线的单位向量
float3 v2fnormal = normalize(v2f.normal);
//求入射光的单位向量 _WorldSpaceLightPos0内部函数
float3 lnormal = normalize(_WorldSpaceLightPos0.xyz);
//逆向光公式:Diffuse=LightColor * MainColor * max(0,dot(N,L))
//正向光公式:Diffuse=LightColor * MainColor * -min(0,dot(N,L))
float3 diffuse = _LightColor0 * _Color * -min(0,dot(v2fnormal,lnormal));
//添加环境光
float4 newDiffuse = float4(diffuse,0) + UNITY_LIGHTMODEL_AMBIENT;
//返回颜色值
return newDiffuse;
}
ENDCG
}
}

FallBack "Diffuse"
}

/*
我们来说一下步骤和思路 做一个总结

第一步
1.引入库 #include “UnityCG.cginc”
顶点着色器输入结构体
1.顶点位置 语义绑定POSITION  类型float4
2.法线 语义绑定NORMAL 类型float3
顶点着⾊器输出结构体
1.像素位置 语义绑定SV_POSITION 类型float4
2.法线 语义绑定NORMAL 类型float3
全局变量声明
1.光照颜色 内部值 _LightColor0 类型float4
2.漫反射颜色 属性值  自己定义
首先看顶点函数
1.参数 --> 输入结构体
2.返回值 --> 输出结构体
3.步骤:
1.矩阵变幻
2.计算法线
1).输入法线扩充 : float4(input.normal, 0.0)
2).内部值 : unity_WorldToObject
3).法线计算 : mul(float4(input.normal, 0.0), unity_WorldToObject).xyz
然后看片段函数
1.参数 --> 顶点着⾊器输出结构体
2.返回值 --> 片段的颜色值 语义绑定COLOR 类型是float4
3.步骤:
1.获取输入法线方向(float3) normalize(input.normal)
2.获取入射光法线方向(float3)normalize(_WorldSpaceLightPos0.xyz)
3.计算漫反射值
1).逆向光公式:Diffuse=LightColor * MainColor * max(0,dot(N,L))
2).正向光公式:Diffuse=LightColor * MainColor * -min(0,dot(N,L))
i).LightColor 光照颜⾊色
ii).MainColor 漫反射颜⾊色
iii).N 输⼊入法线
iiii).L 光照法线
4.合并环境光
1).漫反射扩充 float4(diffuse, 1.0)
2).添加环境光 + UNITY_LIGHTMODEL_AMBIENT
5.返回结果 片段颜色
*/


Shader就先介绍这么多了,感谢大家的支持, 如果有人想要深入的研究,可以给我评论留言,我们一起讨论研究!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息