-
Notifications
You must be signed in to change notification settings - Fork 40
DirLight
zilch edited this page Mar 9, 2021
·
3 revisions
这一章的目标是为自定义SRP管线加入平行光源(Directional Light)的支持。为了降低复杂度,我们暂且只实现一盏平行光源的支持,并将其认定为主光源。
-
CullingResults.visibleLights
- 可以获取视锥裁剪后的场景灯光列表 -
VisibleLight
- 一个结构,包含了所需的灯光数据信息
在此基础上,我们可以按照以下步骤来实现平行光源支持:
- 从裁剪后的
visibleLights
中按照一定规则筛选出主光源 - 将主光源的数据信息,传递到Shader中
- 按照特定的光照模型,为物体编写Shader
我们按照以下策略来筛选并排序场景光源:
- 遍历所有类型为Directional的灯光
- 按照LightRenderMode优先级排序 ForcePixel > Auto, ForceVertex类型暂不考虑
- LightRenderMode相同,则按照intensity(强度)优先级排序。
代码实现: 此处略
要在shader上支持平行光源,必须拿到以下两个数据
- 灯光方向
- 灯光颜色
var visibleLights = cullingResults.visibleLights;
var mainLightIndex = GetMainLightIndex(visibleLights);
if(mainLightIndex >= 0){
var mainLight = visibleLights[mainLightIndex];
var forward = - (Vector4)mainLight.light.gameObject.transform.forward;
//设置主灯光方向
Shader.SetGlobalVector(ShaderProperties.MainLightDirection,forward);
//设置主灯光颜色
Shader.SetGlobalColor(ShaderProperties.MainLightColor,mainLight.finalColor);
}else{
Shader.SetGlobalColor(ShaderProperties.MainLightColor,new Color(0,0,0,0));
}
ShaderProperties定义如下:
public class ShaderProperties{
public static int MainLightDirection = Shader.PropertyToID("_XMainLightDirection");
public static int MainLightColor = Shader.PropertyToID("_XMainLightColor");
}
创建ShaderLibrary/Light.hlsl
,在其中定义如下相同的两个全局变量:
//主灯光方向
float4 _XMainLightDirection;
//主灯光颜色
half4 _XMainLightColor;
这两个变量的值在3.2中,已从c#端传递进来。
为了支持我们自己的平行光源,需要创建自己的物体渲染Shader。此处,为了简单起见,采用最基础的BlinnPhong光照模型来实现。 关于BlinnPhong光照模型可以参考文章:
光照模型分为漫反射和镜面反射(高光)两部分,漫反射部分采用Lambert实现,如下:
half4 LambertDiffuse(float3 normal){
return max(0,dot(normal,_XMainLightDirection.xyz)) * _XMainLightColor;
}
高光部分实现如下:
half4 BlinnPhongSpecular(float3 viewDir,float3 normal,float shininess){
float3 halfDir = normalize((viewDir + _XMainLightDirection));
float nh = max(0,dot(halfDir,normal));
return pow(nh,shininess) * _XMainLightColor;
}
两者合并后:
//BlinnPhong光照模型
//positionWS为世界坐标
//normalWS为世界法线
half4 BlinnPongLight(float3 positionWS,float3 normalWS,float shininess,half4 diffuseColor,half4 specularColor){
float3 viewDir = normalize( _WorldSpaceCameraPos - positionWS);
return _XAmbientColor + LambertDiffuse(normalWS) * diffuseColor + BlinnPhongSpecular(viewDir,normalWS,shininess) * specularColor;
}
可以看到,这里多出了一个_XAmbientColor
,这是环境光,可以从RenderSettings.ambientLight
中获取,并以同样的方式传递到Shader。
完整的shader可以参考项目源代码.
为SRP写shader的时候有几个注意点:
- 一个是SRP Batcher - 传送门 - 官方文档
- 为了使用SRP Batcher,相关的变量需要用CBUFFER组织起来 - 传送门 - 什么是CBuffer
- 为了使CBUFFER关键字生效,shader中要加入
#pragma enable_cbuffer