光照与阴影
1. 光照的基本概念
在Unreal Engine中,光照是指模拟现实世界中光源对场景中物体的影响。光照可以为场景添加真实感,使物体看起来更加自然。Unreal Engine提供了多种类型的光源,包括定向光(Directional Light)、点光源(Point Light)、聚光灯(Spot Light)和天空光照(Sky Light)。
1.1 定向光(Directional Light)
定向光模拟的是来自无限远的光源,例如太阳。这种光源的特点是光线是平行的,因此对所有物体的影响是一致的。
示例:添加定向光
-
打开Unreal Engine编辑器,创建一个新的关卡。
-
在“模式”面板中选择“光源”类别。
-
从列表中拖动“定向光”到关卡中。
-
选中定向光,在“详细信息”面板中可以调整光源的方向、颜色和强度等属性。
// 示例代码:通过蓝图脚本添加定向光
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建定向光
ADirectionalLight* DirectionalLight = GetWorld()->SpawnActor<ADirectionalLight>(ADirectionalLight::StaticClass(), FVector(0, 0, 1000), FRotator(-45, 0, 0));
// 设置光源的颜色和强度
DirectionalLight->SetLightColor(FLinearColor(1.0f, 1.0f, 1.0f));
DirectionalLight->SetIntensity(1.0f);
}
2. 点光源(Point Light)
点光源是位于场景中的一个点,从该点向四周发射光线。这种光源适用于模拟电灯泡或烛光等近距离光源。
2.1 点光源的属性
-
位置(Location):光源在场景中的坐标。
-
颜色(Color):光源的颜色。
-
强度(Intensity):光源的亮度。
-
衰减半径(Attenuation Radius):光源影响的范围。
示例:添加点光源
-
打开Unreal Engine编辑器,创建一个新的关卡。
-
在“模式”面板中选择“光源”类别。
-
从列表中拖动“点光源”到关卡中。
-
选中点光源,在“详细信息”面板中可以调整光源的位置、颜色、强度和衰减半径等属性。
// 示例代码:通过蓝图脚本添加点光源
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建点光源
APointLight* PointLight = GetWorld()->SpawnActor<APointLight>(APointLight::StaticClass(), FVector(500, 500, 500), FRotator(0, 0, 0));
// 设置光源的颜色和强度
PointLight->SetLightColor(FLinearColor(1.0f, 0.8f, 0.6f));
PointLight->SetIntensity(5000.0f);
// 设置衰减半径
PointLight->SetAttenuationRadius(1000.0f);
}
3. 聚光灯(Spot Light)
聚光灯是一种具有特定方向和角度的光源,适用于模拟手电筒或舞台灯光等。聚光灯的光线形成一个锥形区域,只有在该区域内的物体才能受到光照的影响。
3.1 聚光灯的属性
-
位置(Location):光源在场景中的坐标。
-
方向(Direction):光源的朝向。
-
颜色(Color):光源的颜色。
-
强度(Intensity):光源的亮度。
-
内锥角(Inner Cone Angle):内锥角度,光线最强的区域。
-
外锥角(Outer Cone Angle):外锥角度,光线开始衰减的区域。
示例:添加聚光灯
-
打开Unreal Engine编辑器,创建一个新的关卡。
-
在“模式”面板中选择“光源”类别。
-
从列表中拖动“聚光灯”到关卡中。
-
选中聚光灯,在“详细信息”面板中可以调整光源的位置、方向、颜色、强度、内锥角和外锥角等属性。
// 示例代码:通过蓝图脚本添加聚光灯
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建聚光灯
ASpotLight* SpotLight = GetWorld()->SpawnActor<ASpotLight>(ASpotLight::StaticClass(), FVector(500, 500, 500), FRotator(-45, 0, 0));
// 设置光源的颜色和强度
SpotLight->SetLightColor(FLinearColor(0.8f, 0.6f, 0.4f));
SpotLight->SetIntensity(1000.0f);
// 设置内锥角和外锥角
SpotLight->SetInnerConeAngle(15.0f);
SpotLight->SetOuterConeAngle(30.0f);
}
4. 天空光照(Sky Light)
天空光照模拟的是天空对场景的光照效果,通常用于室外场景。它可以通过环境立方体贴图或球体贴图来提供全局光照。
4.1 天空光照的属性
-
光源类型(Light Source Type):可以选择环境立方体贴图(Captured Scene)或球体贴图(Spherical Environment Map)。
-
强度(Intensity):光源的亮度。
-
捕获设备(Capture Device):选择用于捕获环境的设备,例如静态捕获或动态捕获。
示例:添加天空光照
-
打开Unreal Engine编辑器,创建一个新的关卡。
-
在“模式”面板中选择“光源”类别。
-
从列表中拖动“天空光照”到关卡中。
-
选中天空光照,在“详细信息”面板中可以调整光源类型、强度和捕获设备等属性。
// 示例代码:通过蓝图脚本添加天空光照
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建天空光照
ASkyLight* SkyLight = GetWorld()->SpawnActor<ASkyLight>(ASkyLight::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));
// 设置光源类型和强度
SkyLight->SetLightSourceMode(ELightSourceMode::LSM_CapturedScene);
SkyLight->SetIntensity(1.0f);
// 设置捕获设备
USkyLightComponent* SkyLightComponent = SkyLight->GetSkyLightComponent();
if (SkyLightComponent)
{
SkyLightComponent->SetSourceCubemap(UTextureCube::StaticClass());
}
}
5. 光照模式
Unreal Engine提供了多种光照模式,包括静态光照(Static Lighting)、固定光照(Stationary Lighting)和动态光照(Dynamic Lighting)。不同的光照模式会影响光照的计算方式和性能。
5.1 静态光照(Static Lighting)
静态光照是预计算的光照,适用于不经常变化的场景。这种模式下,光照效果会烘焙到光照贴图中,因此性能较高,但无法实时改变。
示例:设置静态光照
-
在场景中添加一个静态光源,例如定向光。
-
选中光源,在“详细信息”面板中将“光源移动性”设置为“静态(Static)”。
-
选择“构建”菜单中的“生成光照”选项,烘焙光照效果。
// 示例代码:通过蓝图脚本设置光源移动性为静态
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建定向光
ADirectionalLight* DirectionalLight = GetWorld()->SpawnActor<ADirectionalLight>(ADirectionalLight::StaticClass(), FVector(0, 0, 1000), FRotator(-45, 0, 0));
// 设置光源移动性为静态
DirectionalLight->SetMobility(EComponentMobility::Static);
}
5.2 固定光照(Stationary Lighting)
固定光照是一种介于静态和动态之间的光照模式。它可以在编辑器中预计算,但可以在运行时进行部分修改。这种模式适用于需要在运行时进行少量变化的场景。
示例:设置固定光照
-
在场景中添加一个固定光源,例如点光源。
-
选中光源,在“详细信息”面板中将“光源移动性”设置为“固定(Stationary)”。
-
选择“构建”菜单中的“生成光照”选项,烘焙光照效果。
// 示例代码:通过蓝图脚本设置光源移动性为固定
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建点光源
APointLight* PointLight = GetWorld()->SpawnActor<APointLight>(APointLight::StaticClass(), FVector(500, 500, 500), FRotator(0, 0, 0));
// 设置光源移动性为固定
PointLight->SetMobility(EComponentMobility::Stationary);
}
5.3 动态光照(Dynamic Lighting)
动态光照是完全在运行时计算的光照模式。它适用于需要频繁变化的场景,例如角色的灯光效果。这种模式下,光照效果可以实时改变,但性能较低。
示例:设置动态光照
-
在场景中添加一个动态光源,例如聚光灯。
-
选中光源,在“详细信息”面板中将“光源移动性”设置为“动态(Dynamic)”。
// 示例代码:通过蓝图脚本设置光源移动性为动态
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建聚光灯
ASpotLight* SpotLight = GetWorld()->SpawnActor<ASpotLight>(ASpotLight::StaticClass(), FVector(500, 500, 500), FRotator(-45, 0, 0));
// 设置光源移动性为动态
SpotLight->SetMobility(EComponentMobility::Dynamic);
}
6. 阴影的基本概念
阴影是指物体挡住光线后形成的暗区。在Unreal Engine中,阴影可以通过多种方式生成,包括静态阴影、固定阴影和动态阴影。
6.1 静态阴影(Static Shadows)
静态阴影是预计算的阴影,适用于不经常变化的场景。这种模式下,阴影会烘焙到光照贴图中,因此性能较高,但无法实时改变。
示例:设置静态阴影
-
在场景中添加一个静态光源,例如定向光。
-
选中光源,在“详细信息”面板中将“光源移动性”设置为“静态(Static)”。
-
选中需要投射阴影的物体,在“详细信息”面板中将“投射阴影”设置为“启用(Enabled)”。
-
选择“构建”菜单中的“生成光照”选项,烘焙阴影效果。
// 示例代码:通过蓝图脚本设置物体投射静态阴影
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建静态光源
ADirectionalLight* DirectionalLight = GetWorld()->SpawnActor<ADirectionalLight>(ADirectionalLight::StaticClass(), FVector(0, 0, 1000), FRotator(-45, 0, 0));
DirectionalLight->SetMobility(EComponentMobility::Static);
// 创建一个物体
AStaticMeshActor* StaticMeshActor = GetWorld()->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));
UStaticMeshComponent* StaticMeshComponent = StaticMeshActor->GetStaticMeshComponent();
// 启用投射阴影
if (StaticMeshComponent)
{
StaticMeshComponent->SetCastShadow(true);
}
}
6.2 固定阴影(Stationary Shadows)
固定阴影是一种介于静态和动态之间的阴影模式。它可以在编辑器中预计算,但可以在运行时进行部分修改。这种模式适用于需要在运行时进行少量变化的场景。
示例:设置固定阴影
-
在场景中添加一个固定光源,例如点光源。
-
选中光源,在“详细信息”面板中将“光源移动性”设置为“固定(Stationary)”。
-
选中需要投射阴影的物体,在“详细信息”面板中将“投射阴影”设置为“启用(Enabled)”。
-
选择“构建”菜单中的“生成光照”选项,烘焙阴影效果。
// 示例代码:通过蓝图脚本设置物体投射固定阴影
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建固定光源
APointLight* PointLight = GetWorld()->SpawnActor<APointLight>(APointLight::StaticClass(), FVector(500, 500, 500), FRotator(0, 0, 0));
PointLight->SetMobility(EComponentMobility::Stationary);
// 创建一个物体
AStaticMeshActor* StaticMeshActor = GetWorld()->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));
UStaticMeshComponent* StaticMeshComponent = StaticMeshActor->GetStaticMeshComponent();
// 启用投射阴影
if (StaticMeshComponent)
{
StaticMeshComponent->SetCastShadow(true);
}
}
6.3 动态阴影(Dynamic Shadows)
动态阴影是完全在运行时计算的阴影,适用于需要频繁变化的场景,例如角色的阴影效果。这种模式下,阴影效果可以实时改变,但性能较低。
示例:设置动态阴影
-
在场景中添加一个动态光源,例如聚光灯。
-
选中光源,在“详细信息”面板中将“光源移动性”设置为“动态(Dynamic)”。
-
选中需要投射阴影的物体,在“详细信息”面板中将“投射阴影”设置为“启用(Enabled)”。
// 示例代码:通过蓝图脚本设置物体投射动态阴影
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建动态光源
ASpotLight* SpotLight = GetWorld()->SpawnActor<ASpotLight>(ASpotLight::StaticClass(), FVector(500, 500, 500), FRotator(-45, 0, 0));
SpotLight->SetMobility(EComponentMobility::Dynamic);
// 创建一个物体
AStaticMeshActor* StaticMeshActor = GetWorld()->SpawnActor<AStaticMeshActor>(AStaticMeshActor::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));
UStaticMeshComponent* StaticMeshComponent = StaticMeshActor->GetStaticMeshComponent();
// 启用投射阴影
if (StaticMeshComponent)
{
StaticMeshComponent->SetCastShadow(true);
}
}
7. 光照和阴影的优化
在Unreal Engine中,光照和阴影的优化是提高游戏性能的关键。以下是一些常见的优化技巧:
7.1 减少光源数量
过多的光源会显著增加渲染时间,因此应尽量减少场景中的光源数量。对于不重要的光源,可以考虑使用更高效的灯光类型,例如环境光源。
示例:优化光源数量
-
评估场景中每个光源的重要性。
-
移除或合并不需要的光源。
// 示例代码:移除不必要的光源
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 获取所有光源
TArray<AActor*> LightActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ALight::StaticClass(), LightActors);
// 遍历光源,移除不必要的光源
for (AActor* LightActor : LightActors)
{
ALight* Light = Cast<ALight>(LightActor);
if (Light && Light->GetMobility() == EComponentMobility::Dynamic && Light->GetIntensity() < 100.0f)
{
Light->Destroy();
}
}
}
7.2 使用光照贴图
光照贴图是一种将光照效果烘焙到纹理中的技术,可以显著提高性能。对于不经常变化的场景,应尽量使用光照贴图。
示例:使用光照贴图
-
选择需要烘焙的光源,将其移动性设置为“静态(Static)”或“固定(Stationary)”。
-
选择需要烘焙的物体,确保它们的光照属性设置正确。
-
选择“构建”菜单中的“生成光照”选项,烘焙光照效果。
// 示例代码:通过蓝图脚本烘焙光照
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 获取所有静态和固定的光源
TArray<AActor*> LightActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), ALight::StaticClass(), LightActors);
for (AActor* LightActor : LightActors)
{
ALight* Light = Cast<ALight>(LightActor);
if (Light && (Light->GetMobility() == EComponentMobility::Static || Light->GetMobility() == EComponentMobility::Stationary))
{
// 确保物体的光照属性设置正确
TArray<AActor*> MeshActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AStaticMeshActor::StaticClass(), MeshActors);
for (AActor* MeshActor : MeshActors)
{
AStaticMeshActor* StaticMeshActor = Cast<AStaticMeshActor>(MeshActor);
if (StaticMeshActor)
{
UStaticMeshComponent* StaticMeshComponent = StaticMeshActor->GetStaticMeshComponent();
if (StaticMeshComponent)
{
StaticMeshComponent->SetCastShadow(true);
}
}
}
// 烘焙光照效果
FLevelUtils::BuildLighting(GetWorld());
}
}
}
7.3 使用光照通道
光照通道(Lighting Channels)可以帮助优化光照计算。通过将不同的物体质感分配到不同的光照通道,可以减少光照计算的负担。
示例:使用光照通道
-
在“编辑”菜单中选择“项目设置”(Project Settings)。
-
在“渲染”(Rendering)类别中找到“光照通道”(Lighting Channels)。
-
创建并命名新的光照通道。
-
选择需要分配光照通道的物体,在“详细信息”面板中设置光照通道。
// 示例代码:通过蓝图脚本设置光照通道
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 获取所有静态网格物体
TArray<AActor*> MeshActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AStaticMeshActor::StaticClass(), MeshActors);
for (AActor* MeshActor : MeshActors)
{
AStaticMeshActor* StaticMeshActor = Cast<AStaticMeshActor>(MeshActor);
if (StaticMeshActor)
{
UStaticMeshComponent* StaticMeshComponent = StaticMeshActor->GetStaticMeshComponent();
if (StaticMeshComponent)
{
// 设置光照通道
StaticMeshComponent->SetLightingChannel(0, true);
StaticMeshComponent->SetLightingChannel(1, false);
StaticMeshComponent->SetLightingChannel(2, false);
}
}
}
}
7.4 使用光照体积
光照体积(Light Volumes)用于优化动态光照的计算。它们可以减少动态光照在场景中的传播范围,从而提高性能。
示例:使用光照体积
-
在“模式”面板中选择“体积”(Volumes)类别。
-
从列表中拖动“光照体积”(Lightmass Importance Volume)到关卡中。
-
调整光照体积的大小,使其覆盖需要优化的区域。
-
选择“构建”菜单中的“生成光照”选项,烘焙光照效果。
// 示例代码:通过蓝图脚本添加光照体积
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建光照体积
ALightmass ImportanceVolume* LightVolume = GetWorld()->SpawnActor<ALightmassImportanceVolume>(ALightmassImportanceVolume::StaticClass(), FVector(0, 0, 0), FRotator(0, 0, 0));
// 调整光照体积的大小
if (LightVolume)
{
LightVolume->SetBounds(FVector(1000, 1000, 1000));
}
}
8. 光照和阴影的高级技巧
除了基本的光照和阴影设置,Unreal Engine还提供了许多高级技巧,可以帮助你实现更复杂和逼真的光照效果。
8.1 使用IES纹理
IES(Industry Standard)纹理可以模拟真实世界中的光源分布。通过使用IES纹理,可以为场景中的光源添加更复杂的光照模式。
示例:使用IES纹理
-
在内容浏览器中创建一个新的IES纹理。
-
选择需要使用IES纹理的光源,在“详细信息”面板中找到“IES纹理”(IES Texture)属性。
-
将IES纹理分配给光源。
// 示例代码:通过蓝图脚本设置IES纹理
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建点光源
APointLight* PointLight = GetWorld()->SpawnActor<APointLight>(APointLight::StaticClass(), FVector(500, 500, 500), FRotator(0, 0, 0));
// 加载IES纹理
UTexture2D* IESTexture = Cast<UTexture2D>(StaticLoadObject(UTexture2D::StaticClass(), nullptr, TEXT("/Game/Textures/IES_Profile")));
// 设置IES纹理
if (PointLight && IESTexture)
{
PointLight->SetLightSourceTexture(IESTexture);
}
}
8.2 使用光源函数
光源函数(Light Functions)可以为光源添加更复杂的光照效果,例如颜色渐变或纹理映射。通过使用光源函数,可以创建更具创意的光照效果。
示例:使用光源函数
-
在内容浏览器中创建一个新的光源函数。
-
选择需要使用光源函数的光源,在“详细信息”面板中找到“光源函数”(Light Function)属性。
-
将光源函数分配给光源。
// 示例代码:通过蓝图脚本设置光源函数
void AMyGameMode::BeginPlay()
{
Super::BeginPlay();
// 创建点光源
APointLight* PointLight = GetWorld()->SpawnActor<APointLight>(APointLight::StaticClass(), FVector(500, 500, 500), FRotator(0, 0, 0));
// 加载光源函数
ULightFunction* LightFunction = Cast<ULightFunction>(StaticLoadObject(ULightFunction::StaticClass(), nullptr, TEXT("/Game/Textures/LightFunction")));
// 设置光源函数
if (PointLight && LightFunction)
{
PointLight->SetLightFunction(LightFunction);
}
}
9. 总结
通过合理设置和优化光照与阴影,可以显著提升Unreal Engine场景的真实感和性能。不同的光源类型和光照模式适用于不同的场景需求,而高级技巧如IES纹理和光源函数则可以帮助你实现更加复杂和创意的光照效果。希望本文档能帮助你在Unreal Engine中更好地理解和应用光照与阴影技术。
10. 常见问题解答
10.1 为什么我的场景中的阴影看起来不够真实?
-
光源设置:检查光源的属性,确保光源的颜色、强度和方向设置正确。
-
阴影质量:在“项目设置”(Project Settings)中调整阴影的质量设置,提高阴影分辨率和细节。
-
物体设置:确保需要投射阴影的物体的“投射阴影”属性已启用。
-
烘焙设置:对于静态和固定光源,重新烘焙光照效果,确保烘焙参数设置合理。
10.2 如何优化动态光照的性能?
-
减少动态光源数量:尽量减少场景中的动态光源数量,特别是那些对视觉效果影响不大的光源。
-
使用光照体积:为动态光源添加光照体积,限制其影响范围。
-
降低阴影分辨率:在“项目设置”中调整动态阴影的分辨率,降低其对性能的影响。
-
优化材质:使用更高效的材质和纹理,减少光照计算的复杂度。
10.3 如何实现环境光遮挡(Ambient Occlusion)?
-
启用全局光照:在“项目设置”中启用全局光照(Global Illumination)。
-
调整环境光遮挡参数:在“渲染”(Rendering)类别中找到“环境光遮挡”(Ambient Occlusion)设置,调整相关参数。
-
烘焙光照:对于静态和固定光源,重新烘焙光照效果,确保环境光遮挡效果正确。
11. 进一步阅读
希望本文档能帮助你更好地理解和应用Unreal Engine中的光照与阴影技术。如果有任何问题或需要进一步的帮助,请参考Unreal Engine的官方文档或社区资源。