1、纯色显示
主要结构,就是Shader下,包含一个SubShader和一个FallBack,FallBack不再赘述,就是上面子Shader不可用的时候调用,一般为紫色显示。而SubShader中的结构为Tag、CGPROGRAM,Tag只定义了RenderType,选用了最常用的Opaque,光照模型的使用也有注释,再有就是一个输入函数一个输出函数。颜色的展示就在surf函数中设置,o.Albedo = 1。
效果图:
源码:
Shader "Custom/Shader01"//Shader名
{
SubShader
{
//Opaque: 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器)。
//Transparent:用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)。
//TransparentCutout: 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)。
//Background: Skybox shaders. 天空盒着色器。
//Overlay: GUITexture, Halo, Flare shaders. 光晕着色器、闪光着色器。
//TreeOpaque: terrain engine tree bark. 地形引擎中的树皮。
//TreeTransparentCutout: terrain engine tree leaves. 地形引擎中的树叶。
//TreeBillboard: terrain engine billboarded trees. 地形引擎中的广告牌树。
//Grass: terrain engine grass. 地形引擎中的草。
//GrassBillboard: terrain engine billboarded grass. 地形引擎何中的广告牌草。
Tags { "RenderType" = "Opaque"}
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型,就是下面的void surf
//float3 viewDir - 视图方向 (view direction)。为了计算视差效果(Parallax effects),边缘光照等
//float4 with COLOR semantic -每个顶点插值后的颜色
//float4 screenPos - 屏幕空间中的位置。 为了反射效果,需要包含屏幕空间中的位置信息。
//float3 worldPos - 世界空间中的位置。
//float3 worldRefl - 世界空间中的反射向量。 如果surface shader没有赋值o.Normal,将会包含世界反射向量。参见例子:Reflect-Diffuse shader。
//float3 worldNormal - 世界空间中的法线向量。如果surface shader没有赋值o.Normal,将会包含世界法向量
//float3 worldRefl; INTERNAL_DATA - 世界空间中的反射向量。如果surface shader没有赋值o.Normal,将会包含这个参数。为了获得逐像素法线贴图的反射向量,请使用WorldReflectionVector (IN, o.Normal)。参见例子: Reflect-Bumped shader。
//float3 worldNormal; INTERNAL_DATA -世界空间中的法线向量。如果surface shader没有赋值o.Normal,将会包含世界法向量。为了获得逐像素法线贴图的法向量,请使用WorldNormalVector(IN, o.Normal)。
//在一个贴图变量之前加上uv两个字母,就代表提取它的uv值,例如uv_MainTex
//输入 结构体 名字不能改,只能为Input
struct Input {
float4 color : COLOR;
};
//第一个参数,纯输入的上述结构体参数。
//第二个参数,inout标识,意思是可为输入参数也可为输出参数。
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = 1;//Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}
2、颜色暴露
Properties中加入一个Color属性,CGPROGRAM中加入一个Color声明,surf函数中,o.Albedo = _Color去赋值颜色。
效果图:
源码:
Shader "Custom/Shader02"//Shader名
{
Properties
{
_Color("Color", Color) = (1, 1, 1, 1)//定义一个颜色属性
}
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型
fixed4 _Color;//颜色,和属性中的_Color相对应,需要同名
struct Input {
float4 color : COLOR;//四元素的颜色值(RGBA)
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _Color;//赋值为属性中的颜色值 Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}
3、显示贴图
Properties中加入一个Texture,同样CGPROGRAM中添加一个sampler2D贴图声明,Input中加入uv信息:float2 uv_MainTexture; 此处,uv+上面声明的贴图变量名,surf中将贴图颜色信息给材质:o.Albedo = tex2D (_MainTexture, IN.uv_MainTexture).rgb;
效果图:
源码:
Shader "Custom/Shader03"//Shader名
{
Properties {
//属性_MainTexture
//面板显示为Texture
//类型为2D
//white不是单纯的颜色名,而是是unity的build-in的textures名称
_MainTexture ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型
sampler2D _MainTexture;//贴图
struct Input {
float2 uv_MainTexture;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTexture, IN.uv_MainTexture).rgb;//将贴图颜色信息给材质 Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}
4、法线贴图
在上一个Shader的基础上添加一个NormalMap属性,同时CGPROGRAM添加一个NormalMap声明,Input添加一个uv_NormalMap,surf中,将法线贴图信息给材质球o.Normal = UnpackNormal (tex2D (_NormalMap, IN.uv_NormalMap));
效果图:
源码:
Shader "Custom/Shader04"//Shader名
{
Properties {
//属性_MainTexture
//面板显示为Texture
//类型为2D
//white不是单纯的颜色名,而是是unity的build-in的textures名称
_MainTexture ("Texture", 2D) = "white" {}
//法线贴图
_NormalMap ("NormalMap", 2D) = "" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型
sampler2D _MainTexture;//贴图
sampler2D _NormalMap;//法线贴图
struct Input {
float2 uv_MainTexture;
float2 uv_NormalMap;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTexture, IN.uv_MainTexture).rgb;//将贴图颜色信息给材质 Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
o.Normal = UnpackNormal (tex2D (_NormalMap, IN.uv_NormalMap));//UnpackNormal是unity自带的标准解压法线用的
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}
5、边缘发光
添加一个边缘发光颜色属性,一个强度属性,Input中的viewDir,是视图方向 (view direction),surf中根据视角去算强度都有详细注释说明,
源码:
Shader "Custom/Shader05"//Shader名
{
Properties {
//属性_MainTexture
//面板显示为Texture
//类型为2D
//white不是单纯的颜色名,而是是unity的build-in的textures名称
_MainTexture ("Texture", 2D) = "white" {}
//法线贴图
_NormalMap ("NormalMap", 2D) = "" {}
//边缘发光颜色
_RimColor ("RimColor", Color) = (0.26,0.19,0.16,0.0)
//边缘发光强度
_RimPower ("RimPower", Range(0.5,8.0)) = 3.0
}
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型
sampler2D _MainTexture;//贴图
sampler2D _NormalMap;//法线贴图
float4 _RimColor;
float _RimPower;
struct Input {
float2 uv_MainTexture;
float2 uv_NormalMap;
float3 viewDir;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTexture, IN.uv_MainTexture).rgb;//将贴图颜色信息给材质 Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
o.Normal = UnpackNormal (tex2D (_NormalMap, IN.uv_NormalMap));//UnpackNormal是unity自带的标准解压法线用的
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));//点积求夹角的Cos,夹角越大,Cos越小 saturate是取0-1 1-()取反,夹角越大,值越大 half是一种低精度的float
o.Emission = _RimColor.rgb * pow (rim, _RimPower);//rim的_EmissionPower次幂 * 颜色值
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}
6、贴图反射叠加
添加一个细节贴图属性,并通过“o.Albedo *=”将贴图反射叠加。
效果图
源码:
Shader "Custom/Shader07"//Shader名
{
Properties {
//属性_MainTexture
//面板显示为Texture
//类型为2D
//white不是单纯的颜色名,而是是unity的build-in的textures名称
_MainTexture ("Texture", 2D) = "white" {}
//细节贴图
_Detail ("Detail", 2D) = "gray" {}
}
SubShader
{
Tags { "RenderType" = "Opaque"}
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型
sampler2D _MainTexture;//贴图
sampler2D _Detail;//细节贴图
struct Input {
float2 uv_MainTexture;
float2 uv_Detail;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTexture, IN.uv_MainTexture).rgb;//将贴图颜色信息给材质 Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
o.Albedo *= tex2D (_Detail, IN.uv_Detail).rgb;//在原先的反射基础上,在加一层"_Detail"的反射
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}
7、通过齐次坐标还原点的真实坐标
其实这里主要是其次坐标,他到底实现了什么呢,其实就是把透视视图的坐标还原,在这里,存储一个点的坐标,不是使用3维,而是4维,多出来的这个w就是为了反映投影,正常世界中的两条平行线是不可能相交的,但是在视野中,无限远处是可以的。
可以看一下这边文章:https://zhuanlan.zhihu.com/p/440717663
效果图:
源码:
Shader "Custom/Shader08"//Shader名
{
Properties {
//属性_MainTexture
//面板显示为Texture
//类型为2D
//white不是单纯的颜色名,而是是unity的build-in的textures名称
_MainTexture ("Texture", 2D) = "white" {}
//细节贴图
_Detail ("Detail", 2D) = "gray" {}
}
SubShader
{
Tags { "RenderType" = "Opaque"}
CGPROGRAM
#pragma surface surf Lambert//指定响应方法为surf且采用Lambert的光照模型
sampler2D _MainTexture;//贴图
sampler2D _Detail;//细节贴图
struct Input {
float2 uv_MainTexture;
float4 screenPos;
};
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTexture, IN.uv_MainTexture).rgb;//将贴图颜色信息给材质 Albedo是一个rgb的值,如果给一个1,其实就是float3(1,1,1),就是反射出来的颜色为白色,如果为100,则是加强反射强度,并不会改变其颜色,为0或为负数时道理类似
float2 screenUV = IN.screenPos.xy / IN.screenPos.w;//(x,y,z,w)的齐次坐标对应三维点(x/w,y/w,z/w)
screenUV *= float2(9,16);
o.Albedo *= tex2D (_Detail, screenUV).rgb;
}
ENDCG
}
FallBack "Diffuse"//如果所有subshader在当前显卡都不支持,则默认返回自带的Diffuse
}