学习笔记 整理来至《Unity Shader入门精要》
单张纹理
//单张纹理(SingleTexture)
Shader "LYY/SingleTexture"
{
Properties
{
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
_Specular ("Specular", Color) = (1, 1, 1, 1) //高光反射颜色
_Gloss ("Gloss", Range(1, 256)) = 20 //高光区域的大小
_MainTex ("MainTex", 2d) = "white" {}
}
SubShader
{
pass
{
Tags { "LightMode" = "ForwardBase" }
//只有定义了LightMode才能得到一些Unity的内置光照变量
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
fixed4 _Diffuse; //声明Properties参数
fixed4 _Specular;
float _Gloss;
sampler2D _MainTex;
float4 _MainTex_ST; //声明纹理变量ST是缩放值(_MainTex_ST.xy)和偏移,(_MainTex_ST_zw)
struct a2v
{
//定义顶点着色器输入结构体
float4 vertex : POSITION;
//把模型空间下的顶点坐标填充给vertex
float3 normal : NORMAL;
//把模型空间下的顶点法线填充给normal
float4 texcoord : TEXCOORD0;
//把模型uv坐标填充给texcoord
};
struct v2f
{
//定义顶点着色器输出结构体
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
//顶点着色器的输出结构体同时也是片元着色器的输入结构
v2f vert(a2v v)
{
//定义顶点着色器
v2f o; //定义返回值o
o.pos = UnityObjectToClipPos(v.vertex);
//通过内置矩阵把顶点位置从模型空间转换到裁剪空间
//o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
//顶点法线从模型空间转换到世界空间
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
//在把顶点位置从模型空间转换到时间空间下
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//公式
return o; //返回参数o
}
fixed4 frag(v2f i) : SV_TARGET
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLinghtDir = normalize(_WorldSpaceLightPos0.xyz);
//获得世界空间光的方向,并归一化处理
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Diffuse.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
//通过内置变换获得环境光(想要获得正确的值需要定义合适的LightMode标签)
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLinghtDir));
//带入漫反射公式运算,使用saturate参数代替max
fixed3 reflectDir = normalize(reflect(-worldLinghtDir, worldNormal));
//CG的reflect函数的入射方向要求是由光源指向交点处的,因此对worldLightDir取反后再传给函数
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
//通过_WorldSpaceCameraPos得到世界空间中摄像机的位置,和i.worldPos相减可得世界空间下的视角方向
fixed3 halfDir = normalize(worldLinghtDir + viewDir);
//带入公式 视角方向+光照方向在归一化