一、漫反射光照
直接上代码:
注意其中 Tags 需要设置光照模式为 ForwardBase,它定义了该 Pass 在光照流水线中的角色,在不同的光照模式下 Unity 的内置光照变量属性和含义都有可能不同
关于光照模式需要了解的的还有不少,不过可以暂时不用这么深究
Shader "Jaihk662/NewSurfaceShader"
{
Properties
{
_DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
}
SubShader
{
Tags { "LightMode" = "ForwardBase" }
LOD 200
PASS
{
CGPROGRAM
#pragma vertex vert //声明顶点着色器的函数
#pragma fragment frag //声明片段着色器的函数
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _DiffuseColor;
struct _2vert
{
float4 vertex: POSITION;
float3 normal: NORMAL;
};
struct vert2frag
{
float4 pos: SV_POSITION;
fixed3 color: COLOR0;
};
vert2frag vert(_2vert v)
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 wNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
fixed3 wLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(wNormal, wLightDir));
vert2frag o;
o.pos = UnityObjectToClipPos(v.vertex);
o.color = ambient + diffuse;
return o;
}
fixed4 frag(vert2frag i): SV_Target
{
return fixed4(i.color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
效果如下:
代码中用到的 CG 数学方法:
- saturate(x):将 x 中的所有参数都截取到 [0, 1] 的范围内
关于 CG 中所有的数学方法百科,可以见下一章
关于 Lighting.cginc:
若代码中用了 ForwardBase 光照模式,并且场景中有且只有一个光源:平行光,此时就可使用下面的光照参数(不同模式下参数含义可能不同,关于前向渲染模式具体可参考:https://blog.csdn.net/Jaihk662/article/details/112055588)
- _WorldSpaceLightPos0:光源方向
- _LightColor0:光源颜色
关于环境光 UNITY_LIGHTMODEL_AMBIENT:
在 Window → Rendering → LightingSetting → 下面这个界面设置,Source 选项默认是天空盒
在着色器中,只需要通过 Unity 的内置变量 UNITY_LIGHTMODEL_AMBIENT 就可以得到对应的环境光颜色和强度信息
同理,逐像素光照代码如下:
Shader "Jaihk662/NewSurfaceShader"
{
Properties
{
_DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
}
SubShader
{
LOD 200
PASS
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert //声明顶点着色器的函数
#pragma fragment frag //声明片段着色器的函数
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _DiffuseColor;
struct _2vert
{
float4 vertex: POSITION;
float3 normal: NORMAL;
};
struct vert2frag
{
float4 pos: SV_POSITION;
fixed3 wNormal: NORMAL;
};
vert2frag vert(_2vert v)
{
vert2frag o;
o.pos = UnityObjectToClipPos(v.vertex);
o.wNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
return o;
}
fixed4 frag(vert2frag i): SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 wNormal = i.wNormal;
fixed3 wLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(wNormal, wLightDir));
return fixed4(ambient + diffuse, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
二、镜面光照
一样的:
Shader "Jaihk662/NewSurfaceShader"
{
Properties
{
_DiffuseColor ("DiffuseColor", Color) = (1.0, 1.0, 1.0, 1.0)
_SpecularColor ("SpecularColor", Color) = (1.0, 1.0, 1.0, 1.0)
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
LOD 200
PASS
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert //声明顶点着色器的函数
#pragma fragment frag //声明片段着色器的函数
#include "UnityCG.cginc"
#include "Lighting.cginc"
fixed4 _DiffuseColor;
fixed4 _SpecularColor;
float _Gloss;
struct _2vert
{
float4 vertex: POSITION;
float3 normal: NORMAL;
};
struct vert2frag
{
float4 pos: SV_POSITION;
float3 wPos: TEXCOORD0;
float3 wNormal: TEXCOORD1;
};
vert2frag vert(_2vert v)
{
vert2frag o;
o.pos = UnityObjectToClipPos(v.vertex);
o.wNormal = mul(v.normal, (float3x3)unity_WorldToObject);
o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(vert2frag i): SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 w1Normal = normalize(i.wNormal);
fixed3 wLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _DiffuseColor.rgb * saturate(dot(w1Normal, wLightDir));
fixed3 reflectDir = normalize(reflect(-wLightDir, w1Normal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos - i.wPos);
fixed3 specular = _LightColor0.rgb * _SpecularColor.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}