1.Forward Add要和Forward Base一起使用。
Tags{ "LightMode"="ForwardBase"}
Tags{ "LightMode"="ForwardAdd"}
否则Forward Add在任何渲染路径下都不被渲染。
2.Vertex list渲染路径下,Forward的Shader,都不会被渲染出来。在向前或延后渲染路径下,Forward 的Shader,都会被渲染出来(
尽管是自定义的vertex/fragment forward shader,应该在延后渲染下有延后的材质就用延后渲染路径,否则采用的向前/vertex光照shader)。因为渲染路径如同小路国道高速路,shader的光照渲染模式类似摩托车小车大车,大路可以容纳各种车,小路只能容纳小车。
3.ForwardAdd是向前渲染路径下,多于一个的pixel光源会执行该pass,也就是说n个pixel光源,ForwardAdd会被执行n-1次。
4.灯光有pixel类型,vertex类型,对应Render Mode important 和非important的设置。
在Editor\Data\CGIncludes\UnityCG.cginc中有响应的说明。
一、 光源
float4 _WorldSpaceLightPos0; // 表示光源的位置,_WorldSpaceLightPos0.w == 0是平行光。否则是点光源。
float4 _LightColor0; // 表示光源的颜色。
摄像机Forward 和 Deferred模式下:
在Forward Path渲染路径下,只有含有pixel平行光(important)下_WorldSpaceLightPos0和_LightColor0才有数据。没有pixel 平行光,但有pixel点光源下WorldSpaceLightPos0有数据,_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个点光源的颜色。
摄像机Forward 和 Deferred模式下:
在只有ForwardBase情况下,ForwardBasePass内的unity_4LightPos[XYZ]0和unity_4LightColor只含有点光源信息(可以是pixel的点光源且排名会更靠前)。
在有ForwardAdd情况下,ForwardBasePass内的unity_4LightPos[XYZ]0和unity_4LightColor只含有vertex点光源信息(不能有pixel的点光源)。且unity_4LightPos[XYZ]0内都是世界坐标系中的位置。
在ForwardAddPass内,只有两个以上的Pixel光源(important)情况下,才会执行;在该情况下unity_4LightPos[XYZ]0中拿不到数据。
三、通用光源信息存储
float4 unity_4LightPosition[4] 表示这4个点光源的的位置 或 平行光的方向向量(w = 0是平行光)。
float4 unity_4LightColor[4] 表示这4个光源的颜色。
float4 unity_4LightAtten[4] 表示这4个光源的衰减。
在ForwardBasePass和ForwardAddPass内都不包含有效数据。
四、总结:
在Forward渲染路径下,对于Vertex光源,可以简单使用Shade4PointLights 函数在ForwardBase中计算光照(当然使用
unity_4LightPos[XYZ]0和unity_4LightColor也可以,只是不包含平行光
)。对于Pixel光源,在BasePass和ForwardPass中都是使用_WorldSpaceLightPos0和_LightColor0来计算光照。
float3 Shade4PointLights (
float4 lightPosX, float4 lightPosY, float4 lightPosZ,
float3 lightColor0, float3 lightColor1, float3 lightColor2, float3 lightColor3,
float4 lightAttenSq,
float3 pos, float3 normal)
{
// to light vectors
float4 toLightX = lightPosX - pos.x;
float4 toLightY = lightPosY - pos.y;
float4 toLightZ = lightPosZ - pos.z;
// squared lengths
float4 lengthSq = 0;
lengthSq += toLightX * toLightX;
lengthSq += toLightY * toLightY;
lengthSq += toLightZ * toLightZ;
// NdotL
float4 ndotl = 0;
ndotl += toLightX * normal.x;
ndotl += toLightY * normal.y;
ndotl += toLightZ * normal.z;
// correct NdotL
float4 corr = rsqrt(lengthSq);
ndotl = max (float4(0,0,0,0), ndotl * corr);
// attenuation
float4 atten = 1.0 / (1.0 + lengthSq * lightAttenSq);
float4 diff = ndotl * atten;
// final color
float3 col = 0;
col += lightColor0 * diff.x;
col += lightColor1 * diff.y;
col += lightColor2 * diff.z;
col += lightColor3 * diff.w;
return col;
}