一、基础属性认识和知识掌握
Shader "Custom/1-first"//指定shader的名字,不必跟脚本名一样
{
Properties
{
// 属性 结尾不带分号
//属性名 显示属性名 属性 默认值
_Color ("Color", Color) = (1,1,1,1)
_Vector("Vector",Vector)=(1,1,1,1)
_Int("Int",Int)=1
_Float("Float",Float)=2.2
_Range("Range",Range(0,6))=6
_2D("Texture",2D)="white"{}//若不指定图片则取纯白色
_Cube("Cube",Cube)="white"{}//常用做天空盒
_3D("Texture",3D)="white"{}
}
//SubShader可以有很多个,第一个开始执行,如果可以使用就用第一个,不能用就尝试第二个SubShader
SubShader
{
//至少有一个pass快
pass
{
//在这里写shader代码 HLSLPROGRAM
CGPROGRAM
//使用CG语言编写Shader 结尾带分号
//属性用之前需要重新定义 float是一个值,float2是两个值,……一直到float4
//float 可用half fixed 代替 Float范围32位存储,half范围是16位存储,-6w到6w,fixed是11位存储-2到2
fixed _Color;//颜色值
float4 _Vector;
float _Int;
float _Float;
float _Range;
sampler2D _2D;
samplerCube _Cube;
sampler3D -3D;
ENDCG
}
}
//兜底渲染方案
FallBack "Diffuse"
}
二、顶点函数和片元函数基础
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/2 second"
{
//Properties可以没有
SubShader
{
pass
{
CGPROGRAM
//顶点函数固定格式#pragma vertex,vert是自定义函数名
//顶点坐标是相对于自身坐标来说的(不一定是中心) 将顶点坐标从模型空间转换到剪裁空间(可以认为转到屏幕)
#pragma vertex vert
//返回型 参数型 参数语义说明 POSITION 把顶点坐标传给 v
float4 vert(float4 v : POSITION): SV_POSITION //SV_POSITION解释说明返回值是剪裁空间下的顶点坐标
{
//矩阵和坐标相乘,UNTIY_MATRIX_MVP是矩阵宏4*4
float4 pos = UnityObjectToClipPos(v);
return pos;
}
//片元函数固定格式#pragma fragment,frag是自定义函数名
//返回模型对应屏幕上每个像素颜色值
#pragma fragment frag
//返回值就是像素颜色
fixed4 frag() : SV_Target
{
return fixed4(1,1,0.5,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
三、函数结构体
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/2 second"
{
//Properties可以没有
SubShader
{
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
///顶点参数结构体 application to vertex
struct a2v{
float4 vertex:POSITION;//把模型空间下顶点坐标填充给vertex
float3 normal:NORMAL;//把模型空间法线方向填充给normal
float4 texcoord:TEXCOORD0;//第一套纹理坐标填充给textcoord
};
///顶点函数返回值结构体
struct v2f{
float4 position:SV_POSITION;
};
v2f vert(a2v v)
{
v2f f;
///UnityObjectToClipPos(v.vertex) = mul(UNITY_MATRIX_MVP,vertex) unity封装的方法
f.position = UnityObjectToClipPos(v.vertex);
return f;
}
fixed4 frag() : SV_Target
{
return fixed4(1,1,0.5,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
四、顶点函数和片元函数传递参数
Shader "Custom/2 second"
{
SubShader
{
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 position:SV_POSITION;
//
float3 temp:COLOR0;
//
};
v2f vert(a2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vertex);
///
f.temp = v.normal;
return f;
}
fixed4 frag(v2f f) : SV_Target
{
//将顶点法线赋给颜色
return fixed4(f.temp,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
五、unity中封装好的shader函数
//摄像机方向(视角方向)
根据模型空间中的顶点坐标得到(世界空间)从这个点到摄像机的观察方向
float3 WorldSpaceViewDir(float4 v)
世界空间中的顶点坐标-=》世界空间从这个点到摄像机的观察方向
float3 UnityWorldSpaceviewDir(float4 v)
世界模型空间中的顶点坐标==》模型空间从这个点到摄像机的观察方向
float3 ObjSpaceViewDir(float4 v)
//光源方向
模型空间中的顶点坐标==》世界空间中从这个点到光源的方向,
float3 WorldSpaceLightDir(float4 v)
世界空间中的顶点坐标-=》世界空间中从这个点到光源的方向
float3 UnityWorldSpaceLightDir(float4 v)
模型空间中的顶点坐标==》模型空间中从这个点到光源的方向
float3 ObjSpaceLightDir(float4 v)
//方向转换
float3 UnityObjectToWorldNormal(float3 norm)把法线方向_模型空间==》世界空间
float3 UnityObjectToWorldDir(float3 dir)把方向 模型空间=》世界空间
float3 UnityWorldToObjectDir(float3 dir)把方向 世界空间-》模型空间
六、语义所应用函数范围
1.应用程序到顶点函数使用的语义(a2v)
POSITION (模型空间)顶点坐标
NORMAL (模型空间)法线
TANGENT (模型空间)切线
TEXCOORD0~n 纹理坐标
COLOR 顶点颜色
2.顶点函数到片元函数可以使用的语义(v2f)
SV_POSITION 剪裁空间中的顶点坐标(一般系统直接使用)
COLOR0/COLOR1 传递一组值 4个
TEXCOORD0~7 传递纹理坐标
3.片元函数传递给系统
SV_Target 颜色值,显示到屏幕的颜色
光照模型是一个公式,用来计算某个点的光照效果
七、常用方法:
max() 取得函数中最大的一个
dot() 取得两个向量的点积
_worldSpaceLightPos0 取平行光的位置(方向)
_LightColor0 取平行光的颜色
UNITY_MATRIX_MVP 这个4*4矩阵用来把坐标从模型空间换到剪裁空间
_World2Object 这个4*4矩阵用来把一个方向从世界空间换到模型空间
UNITY_LIGHTMODEL_AMBIENT 直接获取环境光
八、标准光照模型:
自发光
高光反射: Spcular = 直射光 * pow(max(cosθ,0),高光的参数)
θ是反射光方向和视野方向的夹角。pow是次方函数cosθ的高光次方
漫反射:
半兰伯特模型:
Diffuse = 直射光颜色 *(cos θ* 0.5 + 0.5)
兰伯特模型:
Diffuse = 直射光颜色 * max( 0,cos夹角(光和法线的夹角)) cosθ = 光方向*法线方向
环境光: UNITY_LIGHTMODEL_AMBIENT