CARLA
 
载入中...
搜索中...
未找到
CarlaSettingsDelegate.cpp
浏览该文件的文档.
1#include "Carla.h"
4
7
8#include "Async.h"
9#include "Components/StaticMeshComponent.h"
10#include "Engine/DirectionalLight.h"
11#include "Engine/Engine.h"
12#include "Engine/LocalPlayer.h"
13#include "Engine/PostProcessVolume.h"
14#include "Engine/StaticMesh.h"
15#include "GameFramework/HUD.h"
16#include "InstancedFoliageActor.h"
17#include "Kismet/GameplayStatics.h"
18#include "Landscape.h"
19#include "Scalability.h"
20
21
22static constexpr float CARLA_SETTINGS_MAX_SCALE_SIZE = 50.0f;
23
24/// 运行之间的画质设置配置
26// 默认的低画质设置
28 : ActorSpawnedDelegate(FOnActorSpawned::FDelegate::CreateUObject(// 在构造函数中设置演员生成委托
29 this,
30 &UCarlaSettingsDelegate::OnActorSpawned)) {}
31
32void UCarlaSettingsDelegate::Reset()// 重置设置代理
33{
35}
36
38{
39 CheckCarlaSettings(InWorld);
40 InWorld->AddOnActorSpawnedHandler(ActorSpawnedDelegate);// 添加演员生成处理器
41}
42
44{
45 check(CarlaSettings != nullptr);
46 if (InActor != nullptr && IsValid(InActor) && !InActor->IsPendingKill() &&
47 !InActor->IsA<AInstancedFoliageActor>() && // 植被剔除由每个实例控制
48 !InActor->IsA<ALandscape>() && // 不要触碰景观和道路
49 !InActor->ActorHasTag(UCarlaSettings::CARLA_ROAD_TAG) &&
50 !InActor->ActorHasTag(UCarlaSettings::CARLA_SKY_TAG))
51 {
52 TArray<UPrimitiveComponent *> components;
53 InActor->GetComponents(components);
55 {
56 case EQualityLevel::Low: {
57 // 将设置应用于此参与者的当前画质级别
58 float dist = CarlaSettings->LowStaticMeshMaxDrawDistance;
59 const float maxscale = InActor->GetActorScale().GetMax();
60 if (maxscale > CARLA_SETTINGS_MAX_SCALE_SIZE)// 如果缩放尺寸超过最大值
61 {
62 dist *= 100.0f;
63 }
64 SetActorComponentsDrawDistance(InActor, dist);
65 break;
66 }
67 default: break;
68 }
69 }
70}
71
72void UCarlaSettingsDelegate::ApplyQualityLevelPostRestart()应用画质级别(重启后)
73{
74 CheckCarlaSettings(nullptr);
75 UWorld *InWorld = CarlaSettings->GetWorld();
76
77 const EQualityLevel QualityLevel = CarlaSettings->GetQualityLevel();
78
79 if (AppliedLowPostResetQualityLevel == QualityLevel)
80 {
81 return;
82 }
83
84 // 启用画质的临时变化(防止将最后的画质设置保存到文件)
85 Scalability::ToggleTemporaryQualityLevels(true);
86
87 switch (QualityLevel)
88 {
90 {
91 // 执行画质调整
93 // 迭代遍历所有方向光,停用阴影
94 SetAllLights(InWorld, CarlaSettings->LowLightFadeDistance, false, true);
95 // 将所有道路设置为低质量材料
96 SetAllRoads(InWorld, CarlaSettings->LowRoadPieceMeshMaxDrawDistance, CarlaSettings->LowRoadMaterials);
97 // 为所有具有静态网格的参与者设置全局设置中配置的最大距离,以实现低质量画质
98 SetAllActorsDrawDistance(InWorld, CarlaSettings->LowStaticMeshMaxDrawDistance);
99 // Disable all post process volumes
100 SetPostProcessEffectsEnabled(InWorld, false);
101 break;
102 }
103 default:
104 UE_LOG(LogCarla, Warning, TEXT("Unknown quality level, falling back to default."));
106 {
107 LaunchEpicQualityCommands(InWorld);// 启动史诗画质命令
108 SetAllLights(InWorld, 0.0f, true, false);// 设置所有灯光
109 SetAllRoads(InWorld, 0, CarlaSettings->EpicRoadMaterials);// 设置所有道路
110 SetAllActorsDrawDistance(InWorld, 0); // 设置所有演员的绘制距离
111 SetPostProcessEffectsEnabled(InWorld, true);// 启用后处理效果
112 break;
113 }
114 }
115 AppliedLowPostResetQualityLevel = QualityLevel;
116}
117
119{
120 CheckCarlaSettings(nullptr);
121 UWorld *InWorld = CarlaSettings->GetWorld();
122 if (!IsValid(InWorld) || InWorld->IsPendingKill())// 如果世界无效或即将销毁
123 {
124 return;
125 }
126 // 启用或禁用世界和头显渲染
127 APlayerController *playercontroller = UGameplayStatics::GetPlayerController(InWorld, 0);
128 if (playercontroller)
129 {
130 ULocalPlayer *player = playercontroller->GetLocalPlayer();// 获取本地玩家
131 if (player) // 如果本地玩家有效
132 {
133 player->ViewportClient->bDisableWorldRendering = CarlaSettings->bDisableRendering;// 设置是否禁用世界渲染
134 }
135 // 如果我们已经有一个头显类:
136 AHUD *hud = playercontroller->GetHUD();
137 if (hud)
138 {
139 hud->bShowHUD = !CarlaSettings->bDisableRendering;
140 }
141 }
142
143}
144
146{
147 return GEngine->GetWorldFromContextObjectChecked(this);// 从上下文对象获取世界
148}
149
151{
153 {
154 return;
155 }
156 if (world == nullptr || !IsValid(world) || world->IsPendingKill())
157 {
158 world = GetLocalWorld();
159 }
160 check(world != nullptr);
161 auto GameInstance = Cast<UCarlaGameInstance>(world->GetGameInstance());// 将游戏实例转换为Carla游戏实例
162 check(GameInstance != nullptr); // 确保游戏实例不为空
163 CarlaSettings = &GameInstance->GetCarlaSettings();
164 check(CarlaSettings != nullptr);
165}
166
167void UCarlaSettingsDelegate::LaunchLowQualityCommands(UWorld *world) const// 启动低画质命令
168{
169 if (!world)
170 {
171 return;
172 }
173
174 // 启动命令以降低画质设置
175 GEngine->Exec(world, TEXT("r.DefaultFeature.MotionBlur 0"));
176 GEngine->Exec(world, TEXT("r.DefaultFeature.Bloom 0"));
177 GEngine->Exec(world, TEXT("r.DefaultFeature.AmbientOcclusion 0"));
178 GEngine->Exec(world, TEXT("r.AmbientOcclusionLevels 0"));
179 GEngine->Exec(world, TEXT("r.DefaultFeature.AmbientOcclusionStaticFraction 0"));
180 GEngine->Exec(world, TEXT("r.RHICmdBypass 0"));
181 GEngine->Exec(world, TEXT("r.DefaultFeature.AntiAliasing 1"));
182 GEngine->Exec(world, TEXT("r.Streaming.PoolSize 2000"));
183 GEngine->Exec(world, TEXT("r.HZBOcclusion 0"));
184 GEngine->Exec(world, TEXT("r.MinScreenRadiusForLights 0.01"));
185 GEngine->Exec(world, TEXT("r.SeparateTranslucency 0"));
186 GEngine->Exec(world, TEXT("r.FinishCurrentFrame 0"));
187 GEngine->Exec(world, TEXT("r.MotionBlurQuality 0"));
188 GEngine->Exec(world, TEXT("r.PostProcessAAQuality 0"));
189 GEngine->Exec(world, TEXT("r.BloomQuality 1"));
190 GEngine->Exec(world, TEXT("r.SSR.Quality 0"));
191 GEngine->Exec(world, TEXT("r.DepthOfFieldQuality 0"));
192 GEngine->Exec(world, TEXT("r.SceneColorFormat 2"));
193 GEngine->Exec(world, TEXT("r.TranslucencyVolumeBlur 0"));
194 GEngine->Exec(world, TEXT("r.TranslucencyLightingVolumeDim 4"));
195 GEngine->Exec(world, TEXT("r.MaxAnisotropy 8"));
196 GEngine->Exec(world, TEXT("r.LensFlareQuality 0"));
197 GEngine->Exec(world, TEXT("r.SceneColorFringeQuality 0"));
198 GEngine->Exec(world, TEXT("r.FastBlurThreshold 0"));
199 GEngine->Exec(world, TEXT("r.SSR.MaxRoughness 0.1"));
200 GEngine->Exec(world, TEXT("r.AllowOcclusionQueries 1"));
201 GEngine->Exec(world, TEXT("r.SSR 0"));
202 // GEngine->Exec(world,TEXT("r.StencilForLODDither 1")); // 只读
203 GEngine->Exec(world, TEXT("r.EarlyZPass 2")); // 透明先于不透明
204 GEngine->Exec(world, TEXT("r.EarlyZPassMovable 1"));
205 GEngine->Exec(world, TEXT("Foliage.DitheredLOD 0"));
206 // GEngine->Exec(world,TEXT("r.ForwardShading 0")); // 只读
207 GEngine->Exec(world, TEXT("sg.PostProcessQuality 0"));
208 // GEngine->Exec(world,TEXT("r.ViewDistanceScale 0.1")); //--> 太过极端
209 // (far clip too short)
210 GEngine->Exec(world, TEXT("sg.ShadowQuality 0"));
211 GEngine->Exec(world, TEXT("sg.TextureQuality 0"));
212 GEngine->Exec(world, TEXT("sg.EffectsQuality 0"));
213 GEngine->Exec(world, TEXT("sg.FoliageQuality 0"));
214 GEngine->Exec(world, TEXT("foliage.DensityScale 0"));
215 GEngine->Exec(world, TEXT("grass.DensityScale 0"));
216 GEngine->Exec(world, TEXT("r.TranslucentLightingVolume 0"));
217 GEngine->Exec(world, TEXT("r.LightShaftDownSampleFactor 4"));
218 GEngine->Exec(world, TEXT("r.OcclusionQueryLocation 1"));
219 // GEngine->Exec(world,TEXT("r.BasePassOutputsVelocity 0")); //--> 只读
220 // GEngine->Exec(world,TEXT("r.DetailMode 0")); //-->will change to lods 0
221 GEngine->Exec(world, TEXT("r.DefaultFeature.AutoExposure 1"));
222
223}
224
226 UWorld *world,
227 const float max_draw_distance,
228 const TArray<FStaticMaterial> &road_pieces_materials) const
229{
230 if (!world || !IsValid(world) || world->IsPendingKill())
231 {
232 return;
233 }
234 AsyncTask(ENamedThreads::GameThread, [=]() {
235 if (!world || !IsValid(world) || world->IsPendingKill())
236 {
237 return;
238 }
239 TArray<AActor *> actors;
240 UGameplayStatics::GetAllActorsWithTag(world, UCarlaSettings::CARLA_ROAD_TAG, actors);
241
242 for (int32 i = 0; i < actors.Num(); i++)
243 {
244 AActor *actor = actors[i];
245 if (!IsValid(actor) || actor->IsPendingKill())
246 {
247 continue;
248 }
249 TArray<UStaticMeshComponent *> components;
250 actor->GetComponents(components);
251 for (int32 j = 0; j < components.Num(); j++)
252 {
253 UStaticMeshComponent *staticmeshcomponent = Cast<UStaticMeshComponent>(components[j]);
254 if (staticmeshcomponent)
255 {
256 staticmeshcomponent->bAllowCullDistanceVolume = (max_draw_distance > 0);
257 staticmeshcomponent->bUseAsOccluder = false;
258 staticmeshcomponent->LDMaxDrawDistance = max_draw_distance;
259 staticmeshcomponent->CastShadow = (max_draw_distance == 0);
260 if (road_pieces_materials.Num() > 0)
261 {
262 TArray<FName> meshslotsnames = staticmeshcomponent->GetMaterialSlotNames();
263 for (int32 k = 0; k < meshslotsnames.Num(); k++)
264 {
265 const FName &slotname = meshslotsnames[k];
266 road_pieces_materials.ContainsByPredicate(
267 [staticmeshcomponent, slotname](const FStaticMaterial &material)
268 {
269 if (material.MaterialSlotName.IsEqual(slotname))
270 {
271 staticmeshcomponent->SetMaterial(
272 staticmeshcomponent->GetMaterialIndex(slotname),
273 material.MaterialInterface);
274 return true;
275 }
276 else
277 {
278 return false;
279 }
280 });
281 }
282 }
283 }
284 }
285 }
286 }); // ,DELAY_TIME_TO_SET_ALL_ROADS, false);
287}
288
290 AActor *actor,
291 const float max_draw_distance) const
292{
293 if (!actor)
294 {
295 return;
296 }
297 TArray<UPrimitiveComponent *> components;
298 actor->GetComponents(components, false);
299 float dist = max_draw_distance;
300 const float maxscale = actor->GetActorScale().GetMax();
301 if (maxscale > CARLA_SETTINGS_MAX_SCALE_SIZE)
302 {
303 dist *= 100.0f;
304 }
305 for (int32 j = 0; j < components.Num(); j++)
306 {
307 UPrimitiveComponent *primitivecomponent = Cast<UPrimitiveComponent>(components[j]);
308 if (IsValid(primitivecomponent))
309 {
310 primitivecomponent->SetCullDistance(dist);
311 primitivecomponent->bAllowCullDistanceVolume = dist > 0;
312 }
313 }
314}
315
316void UCarlaSettingsDelegate::SetAllActorsDrawDistance(UWorld *world, const float max_draw_distance) const
317{
318 /// @TODO: 使用语义按类型(车辆、地面、人物、道具)抓取所有参与者,并设置全局属性中配置的不同距离
319 if (!world || !IsValid(world) || world->IsPendingKill())
320 {
321 return;
322 }
323 AsyncTask(ENamedThreads::GameThread, [=]() {
324 if (!world || !IsValid(world) || world->IsPendingKill())
325 {
326 return;
327 }
328 TArray<AActor *> actors;
329 // 设置较低画质 - 最大绘制距离
330 UGameplayStatics::GetAllActorsOfClass(world, AActor::StaticClass(), actors);
331 for (int32 i = 0; i < actors.Num(); i++)
332 {
333 AActor *actor = actors[i];
334 if (!IsValid(actor) || actor->IsPendingKill() ||
335 actor->IsA<AInstancedFoliageActor>() || // foliage culling is controlled
336 // per instance
337 actor->IsA<ALandscape>() || // 不要触碰景观和道路
338 actor->ActorHasTag(UCarlaSettings::CARLA_ROAD_TAG) ||
339 actor->ActorHasTag(UCarlaSettings::CARLA_SKY_TAG))
340 {
341 continue;
342 }
343 SetActorComponentsDrawDistance(actor, max_draw_distance);
344 }
345 });
346}
347
348void UCarlaSettingsDelegate::SetPostProcessEffectsEnabled(UWorld *world, const bool enabled) const
349{
350 TArray<AActor *> actors;
351 UGameplayStatics::GetAllActorsOfClass(world, APostProcessVolume::StaticClass(), actors);
352 for (int32 i = 0; i < actors.Num(); i++)
353 {
354 AActor *actor = actors[i];
355 if (!IsValid(actor) || actor->IsPendingKill())
356 {
357 continue;
358 }
359 APostProcessVolume *postprocessvolume = Cast<APostProcessVolume>(actor);
360 if (postprocessvolume)
361 {
362 postprocessvolume->bEnabled = enabled;
363 }
364 }
365}
366
368{
369 if (!world)
370 {
371 return;
372 }
373
374 GEngine->Exec(world, TEXT("r.AmbientOcclusionLevels -1"));
375 GEngine->Exec(world, TEXT("r.RHICmdBypass 1"));
376 GEngine->Exec(world, TEXT("r.DefaultFeature.AntiAliasing 1"));
377 GEngine->Exec(world, TEXT("r.Streaming.PoolSize 2000"));
378 GEngine->Exec(world, TEXT("r.MinScreenRadiusForLights 0.03"));
379 GEngine->Exec(world, TEXT("r.SeparateTranslucency 1"));
380 GEngine->Exec(world, TEXT("r.PostProcessAAQuality 4"));
381 GEngine->Exec(world, TEXT("r.BloomQuality 5"));
382 GEngine->Exec(world, TEXT("r.SSR.Quality 3"));
383 GEngine->Exec(world, TEXT("r.DepthOfFieldQuality 2"));
384 GEngine->Exec(world, TEXT("r.SceneColorFormat 4"));
385 GEngine->Exec(world, TEXT("r.TranslucencyVolumeBlur 1"));
386 GEngine->Exec(world, TEXT("r.TranslucencyLightingVolumeDim 64"));
387 GEngine->Exec(world, TEXT("r.MaxAnisotropy 8"));
388 GEngine->Exec(world, TEXT("r.LensFlareQuality 2"));
389 GEngine->Exec(world, TEXT("r.SceneColorFringeQuality 1"));
390 GEngine->Exec(world, TEXT("r.FastBlurThreshold 100"));
391 GEngine->Exec(world, TEXT("r.SSR.MaxRoughness -1"));
392 // GEngine->Exec(world,TEXT("r.StencilForLODDither 0")); // 只读
393 GEngine->Exec(world, TEXT("r.EarlyZPass 3"));
394 GEngine->Exec(world, TEXT("r.EarlyZPassMovable 1"));
395 GEngine->Exec(world, TEXT("Foliage.DitheredLOD 1"));
396 GEngine->Exec(world, TEXT("sg.PostProcessQuality 3"));
397 GEngine->Exec(world, TEXT("r.ViewDistanceScale 1")); // --> too extreme (far
398 // clip too short)
399 GEngine->Exec(world, TEXT("sg.ShadowQuality 3"));
400 GEngine->Exec(world, TEXT("sg.TextureQuality 3"));
401 GEngine->Exec(world, TEXT("sg.EffectsQuality 3"));
402 GEngine->Exec(world, TEXT("sg.FoliageQuality 3"));
403 GEngine->Exec(world, TEXT("foliage.DensityScale 1"));
404 GEngine->Exec(world, TEXT("grass.DensityScale 1"));
405 GEngine->Exec(world, TEXT("r.TranslucentLightingVolume 1"));
406 GEngine->Exec(world, TEXT("r.LightShaftDownSampleFactor 2"));
407 // GEngine->Exec(world,TEXT("r.OcclusionQueryLocation 0"));
408 // GEngine->Exec(world,TEXT("r.BasePassOutputsVelocity 0")); // 只读
409 GEngine->Exec(world, TEXT("r.DetailMode 2"));
410}
411
413 UWorld *world,
414 const float max_distance_fade,
415 const bool cast_shadows,
416 const bool hide_non_directional) const
417{
418 if (!world || !IsValid(world) || world->IsPendingKill())
419 {
420 return;
421 }
422 AsyncTask(ENamedThreads::GameThread, [=]() {
423 if (!world || !IsValid(world) || world->IsPendingKill())
424 {
425 return;
426 }
427 TArray<AActor *> actors;
428 UGameplayStatics::GetAllActorsOfClass(world, ALight::StaticClass(), actors);
429 for (int32 i = 0; i < actors.Num(); i++)
430 {
431 if (!IsValid(actors[i]) || actors[i]->IsPendingKill())
432 {
433 continue;
434 }
435 // 调整方向光
436 ADirectionalLight *directionallight = Cast<ADirectionalLight>(actors[i]);
437 if (directionallight)
438 {
439 directionallight->SetCastShadows(cast_shadows);
440 directionallight->SetLightFunctionFadeDistance(max_distance_fade);
441 continue;
442 }
443 // 禁用任何其他类型的灯
444 actors[i]->SetActorHiddenInGame(hide_non_directional);
445 }
446 });
447
448}
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
static constexpr float CARLA_SETTINGS_MAX_SCALE_SIZE
EQualityLevel
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
用于为生成到世界中的每个角色设置设置
void SetAllRoads(UWorld *world, float max_draw_distance, const TArray< FStaticMaterial > &road_pieces_materials) const
void SetPostProcessEffectsEnabled(UWorld *world, bool enabled) const
void ApplyQualityLevelPreRestart()
加载关卡之前,应用当前设置
void LaunchLowQualityCommands(UWorld *world) const
执行引擎命令,将低质量水平应用于世界
void ApplyQualityLevelPostRestart()
加载关卡后,应用当前设置
void Reset()
将设置重置为默认值
void LaunchEpicQualityCommands(UWorld *world) const
执行引擎命令,将史诗般的质量水平应用于世界
void CheckCarlaSettings(UWorld *world)
检查世界、实例和设置是否有效,并保存CarlaSettings实例
void SetAllActorsDrawDistance(UWorld *world, float max_draw_distance) const
void RegisterSpawnHandler(UWorld *World)
在此处为所有新生成的参与者创建事件触发器处理程序,以便使用自定义函数进行处理。
FOnActorSpawned::FDelegate ActorSpawnedDelegate
static EQualityLevel AppliedLowPostResetQualityLevel
重新启动级别后当前应用的质量级别
void SetAllLights(UWorld *world, float max_distance_fade, bool cast_shadows, bool hide_non_directional) const
void OnActorSpawned(AActor *Actor)
函数应用于正在生成的参与者,以应用当前设置
void SetActorComponentsDrawDistance(AActor *actor, float max_draw_distance) const
bool bDisableRendering
启用或禁用世界的视窗渲染。默认情况下禁用。
EQualityLevel GetQualityLevel() const
static const FName CARLA_SKY_TAG
CARLA_SKY 名称用于标记场景中的天空球(sky sphere, BPS)参与者。
static const FName CARLA_ROAD_TAG
CARLA_ROAD 名称用于标记道路网格参与者。
float LowLightFadeDistance
光照函数应完全淡化为 禁用亮度(DisabledBrightness)的距离。 这对于隐藏在远处应用的光照函数的混叠很有用。