在Editor\Data\CGIncludes\UnityCG.cginc中有响应的说明。
一、 光源
float4 _WorldSpaceLightPos0; // 表示光源的位置,_WorldSpaceLightPos0.w == 0是平行光。否则是点光源。
float4 _LightColor0; // 表示光源的颜色。
二、点光源存储,三个float4向量,表示4个点光源的x,y,z坐标。
float4 unity_4LightPosX0; // 存放(x0, x1, x2, x3)
float4 unity_4LightPosY0; // 存放(y0, y1, y2, y3)
float4 unity_4LightPosZ0; // 存放(z0, z1, z2, z3)
响应的:
float4 unity_4LightAtten0 表示这4个点光源的衰减系数。
float4 unity_4LightColor[4] 表示这4个点光源的颜色。
lightMode = Vertex的pass内,u3d并没有提供数据到unity_4LightPosX0等中, _WorldSpaceLightPos0,_LightColor0中也没有数据。Forward pass中却可以遗留在unity_4LightPosition中,但是不会马上清理。
三、通用光源信息存储
float4 unity_4LightPosition[4] 表示这4个点光源的的位置 或 平行光的方向向量(w = 0是平行光)。
float4 unity_4LightColor[4] 表示这4个光源的颜色。
float4 unity_4LightAtten[4] 表示这4个光源的衰减。
lightMode = Vertex的pass内,在这里u3d及时的更新了此数组中的光源信息。在Forward, Deferred路径中也存在。
unity_4LightPosition存储的坐标位置是在摄像机坐标系内的(无论是平行光 还是 点光源)。引擎内代码:
float3 ShadeVertexLights (float4 vertex, float3 normal)
{
float3 viewpos = mul (UNITY_MATRIX_MV, vertex).xyz; // 顶点变换到摄像机坐标系中
float3 viewN = mul ((float3x3)UNITY_MATRIX_IT_MV, normal);
float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz; // 加了环境光
// verte渲染路径下,多光源的vertex顶点光照累加。
for (int i = 0; i < 4; i++) {
float3 toLight = unity_LightPosition[i].xyz - viewpos.xyz * unity_LightPosition[i].w;
float lengthSq = dot(toLight, toLight);
float atten = 1.0 / (1.0 + lengthSq * unity_LightAtten[i].z); // 点光源衰减,亮度根据距离反比
float diff = max (0, dot (viewN, normalize(toLight)));
lightColor += unity_LightColor[i].rgb * (diff * atten);// 只有漫反射颜色
}
return lightColor;
}
小结:
在LightMode = vertex渲染路径下,不要使用_WorldSpaceLightPos0等因为可能是残留的数据,而是要使用unity_4LightPosition和unity_4LightColor, unity_4LightPosition是在相机坐标系下的。如果要重写顶点和片断 shader可以修改UnityCG.cginc下的ShadeVertexLights达到要求。
将unity中内置的LightMode = vertex顶点渲染路径下的surface shader用 vertex/fragment shader编写如下:
Shader "Tut/Lighting/VertexLit/Indicator/unity_LightPosition_0" {
Properties {
_Color ("Base Color", Color) =(1,1,1,1)
}
SubShader {
pass{
Tags{ "LightMode"="Vertex"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
uniform float4 _Color;
struct vertOut{
float4 pos:SV_POSITION;
float4 color:COLOR;
};
vertOut vert(appdata_base v)
{
//unity_LightPosition in viewSpace,ie,the camera space
float3 viewpos = mul (UNITY_MATRIX_MV, v.vertex).xyz;
float3 viewN = mul ((float3x3)UNITY_MATRIX_IT_MV, v.normal);
float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz;
float3 toLight = unity_LightPosition[0].xyz - viewpos.xyz * unity_LightPosition[0].w;
float lengthSq = dot(toLight, toLight);
float atten = 4.0 / (1.0 + lengthSq * unity_LightAtten[0].z);
float diff = max (0, dot (viewN, normalize(toLight)));
lightColor += unity_LightColor[0].rgb * (diff * atten);
vertOut o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.color=float4(lightColor,1)*_Color;
return o;
}
float4 frag(vertOut i):COLOR
{
return i.color;
}
ENDCG
}//end pass
}
}