首先,我们需要指示我们的 着色器在 GPU 上运行的程序。 更多信息
参见 术语表 确实需要传递给它的光照信息。Unity 的 渲染管线 支持各种渲染方式;这里我们将使用默认的 正向渲染一种渲染路径,它根据影响对象的灯光,在一次或多次传递中渲染每个对象。正向渲染对灯光本身的处理方式也不同,这取决于它们的设置和强度。 更多信息
参见 术语表。
我们将从只支持一个方向光开始。Unity 中的正向渲染通过渲染主方向光、环境光、光照贴图一种预渲染纹理,包含场景中静态对象的光源效果。光照贴图叠加在场景几何体之上,以创建光照效果。 更多信息
参见 术语表 和反射在一个称为 ForwardBase 的单次传递中完成。在着色器中,这是通过添加一个 传递标签 来指示的:Tags {“LightMode”=“ForwardBase”}。这将使方向光数据通过一些 内置变量 传递到着色器中。
以下是在每个顶点计算简单漫射光照,并使用单个主纹理的着色器
Shader "Lit/Simple Diffuse"
{
Properties
{
[NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
// indicate that our pass is the "base" pass in forward
// rendering pipeline. It gets ambient and main directional
// light data set up; light direction in _WorldSpaceLightPos0
// and color in _LightColor0
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" // for UnityObjectToWorldNormal
#include "UnityLightingCommon.cginc" // for _LightColor0
struct v2f
{
float2 uv : TEXCOORD0;
fixed4 diff : COLOR0; // diffuse lighting color
float4 vertex : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
// get vertex normal in world space
half3 worldNormal = UnityObjectToWorldNormal(v.normal);
// dot product between normal and light direction for
// standard diffuse (Lambert) lighting
half nl = max(0, dot(worldNormal, _WorldSpaceLightPos0.xyz));
// factor in the light color
o.diff = nl * _LightColor0;
return o;
}
sampler2D _MainTex;
fixed4 frag (v2f i) : SV_Target
{
// sample texture
fixed4 col = tex2D(_MainTex, i.uv);
// multiply by lighting
col *= i.diff;
return col;
}
ENDCG
}
}
}
这使对象对光照方向做出反应 - 面向光照的部分被照亮,而面向远离光照的部分则完全不亮。