光照
光照模式
Light组件的包含Mode的信息。光源的Mode属性用于定义光源的目标用途。 目前提供的模式有:
- Baked:在运行时之前预先计算烘焙光源所需光照,而不会将这些光源包括在任何运行时光照计算中。
- Realtime:在运行时每帧计算并更新光源的光照。引擎不会对实时光源进行任何预先计算。
- Mixed:混合光源既会参与实时计算,同样也会在运行时每帧计算并更新光源的光照。
Realtime
实时光源会在运行时动态执行光照计算,每帧进行一次。您可以在运行时更改实时光源的属性,从而创建火把,路灯,来自远方的车灯等效果。 实时光源可用于在角色或可移动的几何体上提供光照和投射阴影。 实时光源可以投射不超过阴影距离的阴影。默认情况下,实时光源仅为场景提供实时直接光照。而不会参与简介光照烘焙。
- 实时光源的局限性
- 为实时光源执行运行时计算可能成本很高,尤其是在复杂场景中或低端硬件上。
- 由于实时光源在默认情况下仅为场景提供直接光照,若无其他光照渲染,阴影看起来完全是黑色的,并且没有任何间接光照效果。这可能会导致场景中的光照不真实。
Mixed
混合光源整合了实时光照和烘焙光照的元素。使用混合光源可以将动态阴影与来自同一光源的烘焙光照结合起来,或者在希望光源提供直接实时光照和烘焙间接光照时,也可以使用混合光源。
混合光源会在运行时动态执行光照计算,每帧进行一次。您可以在运行时更改实时光源的属性,也可以可用于在角色或可移动的几何体上提供光照和投射阴影。
并且在进行烘焙时,混合光源也会参与烘焙计算,从而影响到全局光照的效果。
引擎在编辑器中为烘焙光源执行计算,并将结果作为光照数据保存到磁盘中。这一过程称为烘焙。在运行时,引擎将加载烘焙的光照数据,并使用这一数据来照亮场景。由于复杂的计算是预先执行的,因此烘培光源可以减少运行时的着色成本,并减少阴影的渲染成本。
烘焙光照过程中,引擎将直接光照和间接光照从烘培光源烘焙到光照贴图中。光照探针的烘焙过程同样受到烘焙光照影响。
- 烘焙光照的局限性
- 无法在运行时更改烘培光源的属性。
- 烘焙光源不影响镜面反射光照。
- 动态游戏对象不会接收来自烘焙光源的光线或阴影。
光源类型
平行光(NDirectionalLight)
方向光对于在场景中创建诸如阳光的效果非常有用。方向光在许多方面的表现很像太阳光,可视为存在于无限远处的光源,。方向光没有任何可识别的光源位置,因此光源对象可以放置在场景中的任何位置。场景中的所有对象都被照亮,就像光线始终来自同一方向一样。光源与目标对象的距离是未定义的,因此光线不会减弱。
方向光代表来自游戏世界范围之外位置的大型远处光源。在逼真的场景中,方向光可用于模拟太阳或月亮。在抽象的游戏世界中,要为对象添加令人信服的阴影,而无需精确指定光源的来源,方向光是一种很有用的方法。所以默认情况下,场景中会自带一个名为Sun的方向光用于模拟阳光的照射,在大气模拟开启的情况下,Sun也会作为太阳提供的光照数据

- 阴影类型:可设置此灯光是否投射阴影。
- 模式:可设置光照模式。
- 光照强度:可设置数值控制此光源的亮度,默认值为1。
- 光照颜色:可设置光照的颜色。
- 阴影强度:可设置此光源投射阴影的强度,默认值为1。
- 阴影偏移:可设置阴影深度偏移。
- ShadowNormalBias:可设置阴影法线偏移。
点光源(PointLight)
点光源是位于空间中的一个点,并在所有方向上均匀发光。照射到表面的光线的方向是从接触点返回到光源对象中心的线。强度随着远离光源而衰减,在到达指定距离时变为零。
点光源可用于模拟场景中的灯和其他局部光源。您还可以用点光源逼真地模拟火花或爆炸照亮周围环境。但主要的是,过多的光源在场景中会造成极大的性能开支,需要谨慎考虑。
基础光照属性与平行光一致,点光源特殊的属性有:
- 光照强度单位:可以选择光照强度的单位。
- 光源范围:可以通过设置数值控制点光源的光照范围。
阴影类型
阴影是使得场景真实的重要因素,因为它们可以显示对象的比例和位置,否则对象看起来就会显得扁平,不立体。
在使用阴影时,我们需要考虑不同阴影类型的优点以及局限性。
软阴影
软阴影的优点: 在光源的数量较多,且强度并非十分强烈的时候,阴影往往不会显得十分锐利和明显。而是往往有着较为模糊的分界线。软阴影可以较为合理的表现出这种交汇的阴影方式,合适的模拟出光照阴影效果。
软阴影的局限: 对于阴影的渲染十分消耗性能,在场景中光源较多,并且光源和物体都频繁移动的情况下,往往会造成极大的性能开销
硬阴影
硬阴影的优点: 硬阴影可以在较少的性能消耗下模拟出一些场景中的光照效果,例如被平行光照射的立方体,阴影往往锐利且清晰。这样的阴影可以容易的被硬阴影模拟出。并且消耗较小的性能开销。
硬阴影的局限: 过于锐利的阴影往往并不能真实的表现出场景中的光照表现,特别在多光照条件下,硬阴影的效果可能与现实的光照出现较大的偏差。
环境光
Solid Color
环境光(也称为漫射环境光)是场景周围存在的光,并非来自任何特定的光源对象。它可以是场景整体外观和亮度的重要影响因素。
环境光在许多情况下都很有用,如果采用简单的艺术风格,不需要较为真实的反射效果,例如卡通风格渲染时,如果需要整体的调整场景光照,便可以调节环境光的颜色。方便的调节场景光照。 
代码示例:
//在自定义Shader中获取环境光着色
fs:
#NS_DECLARE_MULTIVIEW
#NS_INCLUDE(Common.glsl);
#include "MaterialUniforms/MaterialShader1.glsl"
#NS_INCLUDE(Light/LightCommon.glsl);
/*
声明精度:
#NS_PRECISION_HIGH(类型); == precision highp 类型;
#NS_PRECISION_MEDIUM(类型); == precision mediump 类型;
#NS_PRECISION_LOW(类型); == precision lowp 类型;
*/
#NS_PRECISION_HIGH(float);
in vec2 TexCoord;
in vec3 NormalWS;
out vec4 FragColor;
void main()
{
InitUniforms();
FragColor.rgb = NS_Ambient;
FragColor.a =1.0;
NS_HandleDepth_FS(gl_FragDepth);
}IBL
IBL是基于立方体贴图技术改进的一种环境反射技术,它最大的特点是可以灵活控制反射属性,轻松模拟出物体材质光滑、粗糙等特性。
烘焙IBL
烘培IBL支持记录场景信息保存为贴图数据,在运行时直接读取烘焙结果计算出渲染光照信息。
搭建场景时,需要区分可能会被全局光照影响的物体,例如:地形,不会移动的房屋,车辆,围栏等几乎不会移动的物体,还有经常移动,并不适合被烘焙在全局光照的物体,例如会改变颜色的告示牌,移动的人物等,提前烘焙这些物体会导致实际的场景与烘焙光照出现偏差。所以,在设计时,需要设定那些物体适合被渲染在IBL光照贴图上。
对于需要烘焙的物体,在物体层级中,将层级设置为5:IBLRender,在渲染时就会将物体渲染至光照贴图中。 场景设计完毕后,点击渲染场景IBL,等待弹窗渲染完毕后,即可完成渲染。
渲染完毕后,贴图会被保存在Assets/Textures/IBL/场景名称/文件夹中,可以查看渲染结果是否正确。
在自定义着色器中使用IBL纹理
烘培完IBL后,除了引擎内置的Shader使用外,也可以在外部读取光照贴图,自行进行光照计算。
代码示例:
float perceptualRoughnessToMipmapLevel(float perceptualRoughness)
{
return perceptualRoughness * 5.0f;
}
vec3 GlossyEnvironmentReflection(vec3 reflectVector, float perceptualRoughness)
{
float mip = perceptualRoughnessToMipmapLevel(perceptualRoughness);
vec3 encodedIrradiance = textureLod(preFilerMap, vec3(-reflectVector.x, reflectVector.y, -reflectVector.z), mip).rgb;
vec3 irradiance = encodedIrradiance.rgb;
return irradiance;
}
void main()
{
InitUniforms();
vec3 m_IBLColor = GlossyEnvironmentReflection(Normal,Roughness);
FragColor.rgb = m_IBLColor;
NS_HandleDepth_FS(gl_FragDepth);
}
光照探针
在烘焙过程中,动态物体收到的光照影响是不能直接烘焙进光照贴图进行计算的,而用实时光照就会产生强大的额外开销。此时使用反射探针就能够将动态物体的实时光照烘焙进GI中,这样就可以取代实时光照而减少渲染的开销。
烘焙光照探针
为了记录场景中动态物体会收到的光照影响,需要在场景中相关位置放置光照探针组,探针组会捕捉周围物体的光照影响,并对收到影响的物体提供光照数据,为了使得物体运动中的光照变化具体且连续,需要在场景中光照变化较大的场景,以及运动物体常移动的地点布置光照探针。
搭建场景时,需要区分可能会被全局光照影响的物体,以及会提供全局光照影响的物体。对于提供光照影响的物体,大部分为道路,场景这些不会移动的物体。渲染技术后光照信息固定。所以提供光照的物体移动后会导致光照与实际信息不符的错误,例如一个物体已经离开,但是某个光滑的表面还是照出了他的影子。
为了避免这种错误,对于需要光照探针渲染的物体,我们需要将其设置为静态物体。即不会移动的物体,这样的物体也才会给光照探针提供数据影响。
设计完物体后,即可拖动光照探针至场景中。
添加探针组后,添加的探针组将和原有探针组自动组成新的大四面体集合。 确认位置后,点击烘焙场景球谐系数,即可完成光照探针渲染。
完成探针数据后,对于场景中的物体,开启使用探针光照时,即可动态的收到周围物体的光照影响。在编辑器移动时,可以直接看到影响此物体的四面体。 
自定义着色器中使用光照探针数据
记录了全局光照的贴图数据后,除了引擎内置的Shader使用外,也可以在外部读取光照贴图,自行进行光照计算。
示例代码:
顶点着色器:
#NS_DECLARE_VERSION
//NS_DECLARE_VERSION版本声明必须放在第一行
//XR设备上声明启用Multiview扩展
#NS_DECLARE_MULTIVIEW
//包含引擎内部文件
#NS_INCLUDE(Common.glsl);
#include "MaterialUniforms/MaterialShader1.glsl"
#NS_INCLUDE(GpuDrive.glsl);
//XR设备下声明Multiview视图数量
#NS_DECLARE_MULTIVIEW_NUM顶点属性:
/*
#NS_DATA_POSITION(变量名); 位置
#NS_DATA_TEXCOORD0(变量名); 第一套uv
#NS_DATA_VERTEXCOLOR(变量名); 颜色
#NS_DATA_NORMAL(变量名); 法线
#NS_DATA_TANGENT(变量名); 切线
#NS_DATA_BINORMAL(变量名); 副法线
#NS_DATA_TEXCOORD1(变量名); 第二套uv
*/
#NS_DATA_POSITION(aPos);
#NS_DATA_TEXCOORD0(aTexCoord)
#NS_DATA_NORMAL(aNormal);
out vec3 NormalWS;
out vec2 TexCoord;
void main()
{
InitUniforms();
gl_Position = NSObjectToClipPos(vec4(aPos, 1.0));
TexCoord.xy = aTexCoord.xy * Tiling.xy + Offset.xy;
NormalWS =NSGetNormalInObjectSpace(aNormal);
NS_HandleDepth_VS(gl_Position);
}像素着色器:
#NS_DECLARE_VERSION
//NS_DECLARE_VERSION版本声明必须放在第一行
//XR设备上声明启用Multiview扩展
#NS_DECLARE_MULTIVIEW
#NS_INCLUDE(Common.glsl);
#include "MaterialUniforms/MaterialShader1.glsl"
#NS_INCLUDE(MathCommon.glsl);
#NS_INCLUDE(SH.glsl);声明精度:
/*
#NS_PRECISION_HIGH(类型); == precision highp 类型;
#NS_PRECISION_MEDIUM(类型); == precision mediump 类型;
#NS_PRECISION_LOW(类型); == precision lowp 类型;
*/
#NS_PRECISION_HIGH(float);
in vec2 TexCoord;
in vec3 NormalWS;
out vec4 FragColor;
void main()
{
InitUniforms();
FragColor.rgb = SHEvaluate(NormalWS)/10.0f;
FragColor.a =1.0;
NS_HandleDepth_FS(gl_FragDepth);
}

