读一读

Tags{ "LightMode"="ForwardBase" }

CGPROGRAM
#include "Lighting.cginc"
fixed4 _Diffuse;//假装是物体的自身颜色

struct a2v{
	float4 v:POSITION;
	float3 nor:NORMAL;
};

struct v2f{
	float4 position:SV_POSITION;
	float3 col:COLOR0;
};

#pragma vertex vert
#pragma fragment frag

v2f vert(a2v v){
	v2f f;
	f.position = UnityObjectToClipPos(v.v);

	//计算光颜色
	fixed3 norDir = normalize((fixed3) mul(unity_ObjectToWorld,float4(v.nor,0)));
	fixed3 lightDir = normalize( _WorldSpaceLightPos0.xyz );
        
        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;//环境光

	f.col = _LightColor0.rgb  * max(dot(norDir,lightDir),0) * _Diffuse + ambient;

	return f;
}

fixed4 frag(v2f f):SV_Target{
	return fixed4(f.col,1);
}

ENDCG


内置变量和方法:

UnityObjectToClipPos(pos) 其实就是:mul(UNITY_MATRIX_MVP,pos),变换模型坐标到裁剪坐标

unity_ObjectToWorld就是_Object2World,模型坐标到世界坐标的变换矩阵

_WorldSpaceLightPos0.xyz 就是第一个平行光的位置(方向)

_LightColor0.rgb 就是第一个平行光的颜色

UNITY_LIGHTMODEL_AMBIENT.rgb 环境光的颜色

normalize() 单位化向量的方法

max() 返回参数中的较大值

dot() 向量的点积


这里针对只有平行环境光的情况下,点受光照的影响与光的位置方向有关

已知a·b = |a||b|*cosβ,a就是单位点的法向量b是光的单位方向

那么a·b = cosβ,cosβ的值是-1~1的,那么可以用cosβ也就是a·b来表示该点受光影响的强度系数(负数的时候视为0)。


公式:diffuse = 直射光的颜色 * max(a·b,0)


  1. UnityCG.cginc 包含了最常用的帮助函数、宏和结构体

  2. UnityShaderVariables.cginc 在编译的时候自动包含,包含许多内置的全局变量(UNITY_MATRIX_MVP)

  3. Lighting.cginc 包含了各种内置的关照模型,如果是Surface Shader的话会自动包含

  4. HLSLSupport.cginc 自动包含,用来跨平台


4f5ab2.png


光照模型就是一个公式,使用这个公式来计算某个点的光照效果。

能进入摄像机的光照模型的分类:

  1. 自发光

  2. 高光反射(模拟镜子等光滑面)

  3. 漫反射(粗糙面,默认四周发散)

  4. 环境光


从应用程序传递到顶点函数的语义a2v

lala.png


从顶点函数传递给片元函数v2f

toto.png


片元函数传递给系统

  1. SV_Target 颜色值,显示到屏幕上的颜色


struct a2v{
    float4 vertex:POSITION;//模型空间的顶点坐标
    float3 normal:NORMAL;//模型空间的法线
    float4 texcoord:TEXCOORD0;//第一套纹理坐标
};

struct v2f{
    float4 position:SV_POSITION;//剪裁空间坐标
    float3 temp:COLOR0;
    .../其他要传递给frag的,要有语义
};

v2f vert(a2v v){
    v2f f;
    f.position = mul(UNITY_MATRIX_MVP,v.vertex);
    f.temp = v.normal;
    return f;
}

fixed4 frag(v2f f):SV_Target{
   return fixed4(f.temp,1);
}

通过语义:后面的,来说明这个参数是什么,或者说这个返回值是什么

float4 vert(float4 v:POSITION):SV_POSITION{
  return mul(UNITY_MATRIX_MVP,v);//矩阵变换
}

fixed4 frag():SV_Target{
    return fixed4(r,g,b,a);//针对每个像素
}

POSITION说明这个参数传入的就是顶点值

SV_POSITION说明返回的是剪裁空间的坐标

SV_Target说明这个返回值为像素颜色


顶点函数,说白了就是处理顶点的,一般的作用就是将顶点从模型空间转换到剪裁空间。

片元函数,说白了就是赋予顶点(其实是像素)颜色的

需要在CG(或其他语言)块中声明处理函数

Pass{
    CGPRAGRAM
    
    #pragma vertex vert(顶点函数名)
    #pragma fragment frag(片元函数名)
    
    xxx vert(xx){}
    xxx frag(xx){} 
    
    ENDCG
}



在Properties定义的属性并不能直接用到Pass通道的着色器代码中,需要再声明一次,在声明的使用什么语言编写块里。语言块里面注意语句要加;了。

Pass{
    CGPROGRAM
    
    float4 _Color;//Color
    float4 _Vector;//Vector
    float _Int;//Int
    float _Float;//Float
    float _Range;//Range
    sampler2D _2D;//2D
    samplerCube _Cube;//Cube
    sampler3D _3D;//3D
    
    ENDCG
}

float4表示4个float,同理的有float3,float2等

还有half(存储大小是float的一半),还有fixed(12位定点数,最小)


555.png


属性块下面就是子Shader了,硬件会在子着色器中从上到下选择一个可以运行的子着色器。

SubShader{
    Pass{
        //声明使用的语言cg hlsl?
        CGPROGRAM
        //渲染代码
        ENDCG
    }
}

SubShader{
    .....
}

Fallback "最后的选择,Unity存在的Shader"