如何使用属性
Shader"MyShader"{ //这里是 文件名
Properties{
//属性
_Color("_Color",Color) = (1,1,1,1)//四维向量 float4
_Vector("Vector",Vector) = (1,2,3,4) //四维向量 float4
_Int("Int",int) = 12 //int值 float
_Float("Float",Float) = 234.3 //float值 float
_Range("Range",Range(1,23)) = 3 // 滑动条 大小从1到23 默认为3 float
_2D("Texter",2D) = "white"{} //2D图片的texter 如果什么都不指定 默认为白色 sampler2D
_Cube("Cube",Cube) = "white" {} //立方体文理 一般用于天空空盒子 samplerCube
_3D("3D",3D) = "black"{} //2D 的纹理 sampler3D
}
///子的shader SubShader可以有很多个 显卡运行效果的时候,从第一个subShader开始 ,
//如果第一个SubShader里面的效果都可以实现 那么就是用第一个SUbShade,如果显卡发现SubShader里面的效果他实现不了,
//他会自动去运行下一个SubShader
SubShader{
//至少有一个Pass块
Pass{
//在这里编写SHader代码 或者HLSLPROGRAM
CGPROGRAM
//使用CG语言编写Shader
//CGPROGRAM
// 属性要从新定义一遍 里面对应的是float4 对应 Vector4
float4 _Color ;
float4 _Vector; //可以代替为 half3 或者 fixed
float3 t1;
float2 t;
float t2;
//float 用32位来存储
//half 16位来存储 -6万-6万
//fixed 11为 -2到2
float _Int;
float _Float;
float _Range;
//2D 的格式
sampler2D _2D;
samplerCube _Cube;
sampler3D _3D;
ENDCG
}
}
//如果上面的SubShader都不能用久使用Fallback指定的shader
Fallback "VertexLit"
}
010-创建vert和frag函数(顶点函数和片元函数)
Shader"MyShader02"{
SubShader{
Pass{
CGPROGRAM
//定点函数 这里只是声明了 顶点函数的函数名
// 基本作用是 完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex vert
//片元函数 这里只是声明了 顶点函数的函数名
//基本作用 返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag
//xxx返回值
float4 vert(float4 v:POSITION /* float4 v:POSITION 通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法 */
) :SV_POSITION //:SV_POSITION 对返回值做解释说明 // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统
{
//float4 pos = mul(UNITY_MATRIX_MVP,v); //完成一个矩阵到一个position的乘法运算
//return pos;
return mul(UNITY_MATRIX_MVP,v);
}
//片元函数 返回模型对应屏幕上的每一个像素的颜色值
fixed4 frag():SV_Target //SV_Target 返回值 对应的屏幕颜色
{
return fixed4(1,1,1,1);
}
ENDCG
}
}
Fallback "VertexLit"
}
013-学习NORMAL、TEXCOORD0语义; 014-如何在片元函数和顶点函数之间传递数据
Shader"MyShader03Usestruct"{
SubShader{
Pass{
CGPROGRAM
//定点函数 这里只是声明了 顶点函数的函数名
// 基本作用是 完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex vert
//片元函数 这里只是声明了 顶点函数的函数名
//基本作用 返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag
//a2v application to vertex 从应用传递到顶点 的数据
struct a2v //结构体 和CSharp的一样 不过也要返回 v:POSITION
{
/* float4 v:POSITION 通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法 */
float4 vertex:POSITION; //告诉unity 吧模型空间下的顶点坐标给到vertex
float3 normal:NORMAL;// 法线 告诉unity 把模型空间下的发现法相填充给normal
float4 texcoord:TEXCOORD0; //告诉unity 把第0套纹理坐标填充给texcoord
};
//顶点函数的返回值也使用结构体
struct v2f{
float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明 // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统
float3 temp:COLOR0;
};
// 顶点函数 引用一个结构体 调用结构体中的 vertex
v2f vert(a2v v)
{
v2f f;
f.position= mul(UNITY_MATRIX_MVP, v.vertex);
f.temp = v.normal; //法线 赋值
//float4 pos = mul(UNITY_MATRIX_MVP,v); //完成一个矩阵到一个position的乘法运算
//return pos;
return f;
}
//片元函数 返回模型对应屏幕上的每一个像素的颜色值
fixed4 frag(v2f f ):SV_Target //SV_Target 返回值 对应的屏幕颜色
{
return fixed4(f.temp,1); //使用 法线
}
ENDCG
}
}
//Fallback "VertexLit"
}
015-Unity中的语义有哪些
019-编写漫反射的shader代码
Shader"MyShader04Diffuse"{
SubShader{
Pass
{
Tags{"LightMode" = "ForwardBase" }
CGPROGRAM
#include "Lighting.cginc" ///取得第一个直射光的颜色 _LightColor0 _WorldSpaceLightPos0 第一个直射光的位置
//定点函数 这里只是声明了 顶点函数的函数名
// 基本作用是 完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex vert
//片元函数 这里只是声明了 顶点函数的函数名
//基本作用 返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag
//只有定义了LightMode 才能得到一些Unity的内置光照变量
//a2v application to vertex 从应用传递到顶点 的数据
struct a2v //结构体 和CSharp的一样 不过也要返回 v:POSITION
{
/* float4 v:POSITION 通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法 */
float4 vertex:POSITION; //告诉unity 吧模型空间下的顶点坐标给到vertex
float3 normal:NORMAL; //取 到法线 法线在模型空间下面
};
//顶点函数的返回值也使用结构体
struct v2f{
float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明 // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统
fixed3 color : COLOR;
};
// 顶点函数 引用一个结构体 调用结构体中的 vertex
v2f vert(a2v v)
{
v2f f;
f.position= mul(UNITY_MATRIX_MVP,v.vertex); //UNITY_MATRIX_MVP 这个矩阵用来吧一个坐标从模型空间转换到剪裁空间
//_World2Object
fixed3 normalDir= normalize(mul(v.normal, (float3x3)_World2Object)); //_World2Object这个矩阵用来吧一个方向从世界空间转换到模型空间 位置变换一下就是 从模型空间转换成世界空间
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 第一个直射光的位置 对于每一个顶点来说 光位置就是广德方向,因为光是平行光 并把它单位化 normalize
// 漫反射 Diffuse=直射光颜色*Max(0,cos夹角(光和法线的夹角)) cosθ=光的方向 点乘 法线的方向
fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0) ; //定义漫反射的颜色 在"Lighting.cginc"; 中取到 _LightColor0
f.color = diffuse;
return f;
}
//片元函数 返回模型对应屏幕上的每一个像素的颜色值
fixed4 frag(v2f f ):SV_Target //SV_Target 返回值 对应的屏幕颜色
{
return fixed4(f.color,1); //使用 法线
}
ENDCG
}
}
//Fallback "VertexLit"
}
020-给物体添加漫反射颜色和环境光颜色控制
Shader"MyShader04Diffuse"{
Properties{
_Diffuse("Diffuse Color",Color) = (1,1,1,1)
}
SubShader{
Pass
{ Tags{"LightMode" = "ForwardBase" }
CGPROGRAM
#include "Lighting.cginc" ///取得第一个直射光的颜色 _LightColor0 _WorldSpaceLightPos0 第一个直射光的位置
//定点函数 这里只是声明了 顶点函数的函数名
// 基本作用是 完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex vert
//片元函数 这里只是声明了 顶点函数的函数名
//基本作用 返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag
fixed4 _Diffuse; // 从新声明 一下
//只有定义了LightMode 才能得到一些Unity的内置光照变量
//a2v application to vertex 从应用传递到顶点 的数据
struct a2v //结构体 和CSharp的一样 不过也要返回 v:POSITION
{
/* float4 v:POSITION 通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法 */
float4 vertex:POSITION; //告诉unity 吧模型空间下的顶点坐标给到vertex
float3 normal:NORMAL; //取 到法线 法线在模型空间下面
};
//顶点函数的返回值也使用结构体
struct v2f{
float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明 // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统
fixed3 color : COLOR;
};
// 顶点函数 引用一个结构体 调用结构体中的 vertex
v2f vert(a2v v)
{
v2f f;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb; //取得 环境光
f.position= mul(UNITY_MATRIX_MVP,v.vertex); //UNITY_MATRIX_MVP 这个矩阵用来吧一个坐标从模型空间转换到剪裁空间
//_World2Object
fixed3 normalDir= normalize(mul(v.normal, (float3x3)_World2Object)); //_World2Object这个矩阵用来吧一个方向从世界空间转换到模型空间 位置变换一下就是 从模型空间转换成世界空间
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 第一个直射光的位置 对于每一个顶点来说 光位置就是广德方向,因为光是平行光 并把它单位化 normalize
// 漫反射 Diffuse=直射光颜色*Max(0,cos夹角(光和法线的夹角)) cosθ=光的方向 点乘 法线的方向
fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0) * _Diffuse.rgb; //定义漫反射的颜色 在"Lighting.cginc"; 中取到 _LightColor0
// _Diffuse.rgb 乘以 设置的RGB的值
f.color = diffuse + ambient;
return f;
}
//片元函数 返回模型对应屏幕上的每一个像素的颜色值
fixed4 frag(v2f f ):SV_Target //SV_Target 返回值 对应的屏幕颜色
{
return fixed4(f.color,1); //使用 法线
}
ENDCG
}
}
//Fallback "VertexLit"
}
021-实现逐像素光照(漫反射)
Shader"05-Diffuse Fragment"{
Properties{
_Diffuse("Diffuse Color",Color) = (1,1,1,1)
}
SubShader{
Pass
{ Tags{"LightMode" = "ForwardBase" }
CGPROGRAM
#include "Lighting.cginc" ///取得第一个直射光的颜色 _LightColor0 _WorldSpaceLightPos0 第一个直射光的位置
//定点函数 这里只是声明了 顶点函数的函数名
// 基本作用是 完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex vert
//片元函数 这里只是声明了 顶点函数的函数名
//基本作用 返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag
fixed4 _Diffuse; // 从新声明 一下
//只有定义了LightMode 才能得到一些Unity的内置光照变量
//a2v application to vertex 从应用传递到顶点 的数据
struct a2v //结构体 和CSharp的一样 不过也要返回 v:POSITION
{
/* float4 v:POSITION 通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法 */
float4 vertex:POSITION; //告诉unity 吧模型空间下的顶点坐标给到vertex
float3 normal:NORMAL; //取 到法线 法线在模型空间下面
};
//顶点函数的返回值也使用结构体
struct v2f{
float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明 // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统
fixed3 worldNormalDir : COLOR;
};
// 顶点函数 引用一个结构体 调用结构体中的 vertex
v2f vert(a2v v)
{
v2f f;
f.position= mul(UNITY_MATRIX_MVP, v.vertex); //UNITY_MATRIX_MVP 这个矩阵用来吧一个坐标从模型空间转换到剪裁空间
f.worldNormalDir =mul(v.normal, (float3x3)unity_WorldToObject);
return f;
}
//片元函数 返回模型对应屏幕上的每一个像素的颜色值
fixed4 frag(v2f f ):SV_Target //SV_Target 返回值 对应的屏幕颜色
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb; //取得 环境光
//_World2Object
fixed3 normalDir = normalize(f.worldNormalDir); //_World2Object这个矩阵用来吧一个方向从世界空间转换到模型空间 位置变换一下就是 从模型空间转换成世界空间
fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 第一个直射光的位置 对于每一个顶点来说 光位置就是广德方向,因为光是平行光 并把它单位化 normalize
// 漫反射 Diffuse=直射光颜色*Max(0,cos夹角(光和法线的夹角)) cosθ=光的方向 点乘 法线的方向
fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0) * _Diffuse.rgb; //定义漫反射的颜色 在"Lighting.cginc"; 中取到 _LightColor0
// _Diffuse.rgb 乘以 设置的RGB的值
fixed3 tempColor= diffuse + ambient;
return fixed4(tempColor,1); //使用 法线
}
ENDCG
}
}
Fallback "Diffuse"
}