CARLA
Loading...
Searching...
No Matches
SceneCaptureSensor.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
9#include "Carla.h"
11
12#include <util/ue-header-guard-begin.h>
14#include "ContentStreaming.h"
15#include "Engine/PostProcessVolume.h"
16#include "EngineUtils.h"
17#include "GameFramework/SpectatorPawn.h"
18#include "Misc/App.h"
19#include "SceneManagement.h"
20#include <util/ue-header-guard-end.h>
21
22#include <mutex>
23#include <atomic>
24#include <thread>
25
26// Monotonic across the process lifetime so subobject names assigned to
27// CaptureRenderTarget / USceneCaptureComponent2D never collide on respawn.
28// Atomic so concurrent sensor construction (rare but possible during world
29// load) cannot hand out the same index twice.
30static std::atomic<int> SCENE_CAPTURE_COUNTER{0};
31
32// Registered by CarlaDeviceProfileSelectorModule, which loads first and sets it
33// per quality tier. -1 follows each sensor's bUseRayTracing, 0 forces ray
34// tracing off and 1 forces it on for every camera.
36{
37 static std::atomic<const TConsoleVariableData<int32> *> CVar{nullptr};
38 const TConsoleVariableData<int32> *Cached = CVar.load(std::memory_order_relaxed);
39 if (Cached == nullptr)
40 {
41 Cached = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("carla.Camera.UseRayTracing"));
42 CVar.store(Cached, std::memory_order_relaxed);
43 }
44 return (Cached != nullptr) ? Cached->GetValueOnAnyThread() : -1;
45}
46
47// Rollback / debug switch for the lazy GBuffer capture path. GBuffer captures
48// are only allocated when a client subscribes via listen_to_gbuffer(); setting
49// this to 1 forces every frame to request the full GBuffer set regardless of
50// subscription, matching the pre-refactor behavior.
51static TAutoConsoleVariable<int32> CVarCarlaCameraForceAllGBuffers(
52 TEXT("carla.Camera.ForceAllGBuffers"),
53 0,
54 TEXT("Force CARLA scene-capture cameras to request every GBuffer texture\n")
55 TEXT("each frame, irrespective of client subscription. Intended as a\n")
56 TEXT("one-release rollback path; default is 0 (lazy, by subscription)."),
57 ECVF_Default);
58
59// Exposure-linked motion blur for the RGB cameras. A real camera blurs what
60// moves during its exposure time, which its auto exposure lengthens in the
61// dark (a machine-vision AV camera: ~0.1 ms by day, capped around 20 ms at
62// night, gain above that). Every capture reads the exposure the sensor's own
63// eye adaptation settled on (EV100 = log2(1 / (1.2 * Exposure))), turns it into
64// an exposure time t = N^2 / 2^EV100 for an f/N lens at base ISO, clamps it and
65// sets MotionBlurAmount = t / capture interval (1 = 360 degree shutter). Night
66// lamps then streak along their motion instead of twinkling between pixels.
67static TAutoConsoleVariable<int32> CVarCarlaCameraExposureMotionBlur(
68 TEXT("carla.Camera.ExposureMotionBlur"),
69 1,
70 TEXT("1: RGB cameras derive their motion blur from the auto exposure time (overrides motion_blur_intensity).\n")
71 TEXT("0: use the motion_blur_* attributes / post-process profile as they are."),
72 ECVF_Default);
73
74static TAutoConsoleVariable<float> CVarCarlaCameraFNumber(
75 TEXT("carla.Camera.FNumber"),
76 2.0f,
77 TEXT("Lens f-number used to turn the auto exposure into an exposure time (carla.Camera.ExposureMotionBlur)."),
78 ECVF_Default);
79
80static TAutoConsoleVariable<float> CVarCarlaCameraMinExposureMs(
81 TEXT("carla.Camera.MinExposureMs"),
82 0.05f,
83 TEXT("Shortest exposure time in ms (carla.Camera.ExposureMotionBlur)."),
84 ECVF_Default);
85
86static TAutoConsoleVariable<float> CVarCarlaCameraMaxExposureMs(
87 TEXT("carla.Camera.MaxExposureMs"),
88 20.0f,
89 TEXT("Longest exposure time in ms; darker scenes raise the gain instead (carla.Camera.ExposureMotionBlur)."),
90 ECVF_Default);
91
92// A new camera has no eye adaptation history: left alone it starts from a
93// default exposure and takes seconds to adapt (a white sky flash every time a
94// client respawns a camera, e.g. manual_control's TAB). Its first captures are
95// rendered as camera cuts, which makes the eye adaptation jump to its target:
96// the first image is still metered from scratch, the second one is settled.
97// (Extra unsent captures in the same tick do not help: the exposure a capture
98// computes only reaches the captures of later ticks.)
99static TAutoConsoleVariable<int32> CVarCarlaCameraSpawnCameraCuts(
100 TEXT("carla.Camera.SpawnCameraCuts"),
101 2,
102 TEXT("Number of first captures of a new camera rendered as camera cuts, so its auto exposure settles ")
103 TEXT("from the second image on instead of adapting for seconds from a default exposure (0 disables)."),
104 ECVF_Default);
105
106static TAutoConsoleVariable<int32> CVarCarlaCameraExposureLog(
107 TEXT("carla.Camera.ExposureLog"),
108 0,
109 TEXT("1: log each RGB capture's exposure, exposure time and motion blur amount."),
110 ECVF_Default);
111
112// =============================================================================
113// -- Local static methods -----------------------------------------------------
114// =============================================================================
115
116// Local namespace to avoid name collisions on unit builds.
118{
119
120 static void SetCameraDefaultOverrides(USceneCaptureComponent2D &CaptureComponent2D);
121
122 static auto GetQualitySettings(UWorld *World)
123 {
124 auto Settings = UCarlaStatics::GetCarlaSettings(World);
125 check(Settings != nullptr);
126 return Settings->GetQualityLevel();
127 }
128
129} // namespace SceneCaptureSensor_local_ns
130
131// =============================================================================
132// -- ASceneCaptureSensor ------------------------------------------------------
133// =============================================================================
134
135ASceneCaptureSensor::ASceneCaptureSensor(const FObjectInitializer &ObjectInitializer)
136 : Super(ObjectInitializer)
137{
138 PrimaryActorTick.bCanEverTick = true;
139 PrimaryActorTick.TickGroup = TG_PrePhysics;
140
141 // Snapshot the counter once so the render target and capture component
142 // share the same suffix on this instance.
143 const int Index = SCENE_CAPTURE_COUNTER.fetch_add(1, std::memory_order_relaxed);
144
145 CaptureRenderTarget = CreateDefaultSubobject<UTextureRenderTarget2D>(
146 FName(*FString::Printf(TEXT("CaptureRenderTarget_d%d"), Index)));
147 CaptureRenderTarget->CompressionSettings = TextureCompressionSettings::TC_Default;
148 CaptureRenderTarget->SRGB = false;
149 CaptureRenderTarget->bAutoGenerateMips = false;
150 CaptureRenderTarget->AddressX = TextureAddress::TA_Clamp;
151 CaptureRenderTarget->AddressY = TextureAddress::TA_Clamp;
152
153 CaptureComponent2D = CreateDefaultSubobject<USceneCaptureComponent2D_CARLA>(
154 FName(*FString::Printf(TEXT("USceneCaptureComponent2D%d"), Index)));
155 check(CaptureComponent2D != nullptr);
156 CaptureComponent2D->ViewActor = this;
157 CaptureComponent2D->SetupAttachment(RootComponent);
158 CaptureComponent2D->PrimitiveRenderMode = ESceneCapturePrimitiveRenderMode::PRM_RenderScenePrimitives;
159 CaptureComponent2D->bCaptureOnMovement = false;
160 CaptureComponent2D->bCaptureEveryFrame = false;
161 // Persistent rendering state is the baseline for every scene-capture
162 // subclass. The encoding cameras (depth, semantic / instance
163 // segmentation, normals, DVS) require it for their post-process
164 // material pipeline; RGB and optical-flow inherit it without needing
165 // to re-assert in their own ctors.
166 CaptureComponent2D->bAlwaysPersistRenderingState = true;
168
170}
171
173{
174 Super::Set(Description);
176}
177
178void ASceneCaptureSensor::SetImageSize(uint32 InWidth, uint32 InHeight)
179{
180 ImageWidth = InWidth;
181 ImageHeight = InHeight;
182}
183
185{
186 bUseRayTracing = Enable;
188}
189
191{
192 if (CaptureComponent2D == nullptr)
193 {
194 return;
195 }
197}
198
199bool ASceneCaptureSensor::ResolveCameraRayTracing(const bool bSensorEnabled, const bool bRequired)
200{
201 if (bRequired)
202 {
203 return true;
204 }
205 const int32 CVarOverride = GetCameraRayTracingOverride();
206 return (CVarOverride < 0) ? bSensorEnabled : (CVarOverride > 0);
207}
208
209void ASceneCaptureSensor::SetFOVAngle(const float FOVAngle)
210{
211 check(CaptureComponent2D != nullptr);
212 CaptureComponent2D->FOVAngle = FOVAngle;
213}
214
216{
217 check(CaptureComponent2D != nullptr);
218 return CaptureComponent2D->FOVAngle;
219}
220
222{
223 check(CaptureComponent2D != nullptr);
224 return CaptureComponent2D->PostProcessSettings.BloomDirtMaskIntensity;
225}
226
227void ASceneCaptureSensor::SetExposureMethod(EAutoExposureMethod Method)
228{
229 check(CaptureComponent2D != nullptr);
230 CaptureComponent2D->PostProcessSettings.AutoExposureMethod = Method;
231}
232
233void ASceneCaptureSensor::SetLocalExposureMethod(ELocalExposureMethod Method)
234{
235 check(CaptureComponent2D != nullptr);
236 CaptureComponent2D->PostProcessSettings.LocalExposureMethod = Method;
237}
238
240{
241 check(CaptureComponent2D != nullptr);
242 return CaptureComponent2D->PostProcessSettings.LocalExposureMethod;
243}
244
246{
247 check(CaptureComponent2D != nullptr);
248 CaptureComponent2D->PostProcessSettings.BloomConvolutionTexture = Texture;
249}
250
252{
253 check(CaptureComponent2D != nullptr);
254 CaptureComponent2D->PostProcessSettings.BloomDirtMaskIntensity = Intensity;
255}
256
258{
259 check(CaptureComponent2D != nullptr);
260 return CaptureComponent2D->PostProcessSettings.BloomMethod;
261}
262
264{
265 check(CaptureComponent2D != nullptr);
266 return CaptureComponent2D->PostProcessSettings.BloomConvolutionTexture;
267}
268
269EAutoExposureMethod ASceneCaptureSensor::GetExposureMethod() const
270{
271 check(CaptureComponent2D != nullptr);
272 return CaptureComponent2D->PostProcessSettings.AutoExposureMethod;
273}
274
276{
277 check(CaptureComponent2D != nullptr);
278#if PLATFORM_LINUX
279 // Looks like Windows and Linux have different outputs with the
280 // same exposure compensation, this fixes it.
281 CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation + 0.0f;
282#else
283 CaptureComponent2D->PostProcessSettings.AutoExposureBias = Compensation;
284#endif
285}
286
288{
289 check(CaptureComponent2D != nullptr);
290 return CaptureComponent2D->PostProcessSettings.AutoExposureBias;
291}
292
294{
295 check(CaptureComponent2D != nullptr);
296 CaptureComponent2D->PostProcessSettings.CameraShutterSpeed = Speed;
297}
298
300{
301 check(CaptureComponent2D != nullptr);
302 return CaptureComponent2D->PostProcessSettings.CameraShutterSpeed;
303}
304
306{
307 check(CaptureComponent2D != nullptr);
308 CaptureComponent2D->PostProcessSettings.CameraISO = ISO;
309}
310
312{
313 check(CaptureComponent2D != nullptr);
314 return CaptureComponent2D->PostProcessSettings.CameraISO;
315}
316
318{
319 check(CaptureComponent2D != nullptr);
320 CaptureComponent2D->PostProcessSettings.DepthOfFieldFstop = Aperture;
321}
322
324{
325 check(CaptureComponent2D != nullptr);
326 return CaptureComponent2D->PostProcessSettings.DepthOfFieldFstop;
327}
328
330{
331 check(CaptureComponent2D != nullptr);
332 CaptureComponent2D->PostProcessSettings.DepthOfFieldSensorWidth = Width;
333}
334
336{
337 check(CaptureComponent2D != nullptr);
338 return CaptureComponent2D->PostProcessSettings.DepthOfFieldSensorWidth;
339}
340
342{
343 check(CaptureComponent2D != nullptr);
344 CaptureComponent2D->PostProcessSettings.DepthOfFieldFocalDistance = Distance;
345}
346
348{
349 check(CaptureComponent2D != nullptr);
350 return CaptureComponent2D->PostProcessSettings.DepthOfFieldFocalDistance;
351}
352
354{
355 check(CaptureComponent2D != nullptr);
356 CaptureComponent2D->PostProcessSettings.DepthOfFieldDepthBlurAmount = Amount;
357}
358
360{
361 check(CaptureComponent2D != nullptr);
362 return CaptureComponent2D->PostProcessSettings.DepthOfFieldDepthBlurAmount;
363}
364
366{
367 check(CaptureComponent2D != nullptr);
368 CaptureComponent2D->PostProcessSettings.DepthOfFieldDepthBlurRadius = Radius;
369}
370
372{
373 check(CaptureComponent2D != nullptr);
374 return CaptureComponent2D->PostProcessSettings.DepthOfFieldDepthBlurRadius;
375}
376
378{
379 check(CaptureComponent2D != nullptr);
380 CaptureComponent2D->PostProcessSettings.DepthOfFieldMinFstop = MinFstop;
381}
382
384{
385 check(CaptureComponent2D != nullptr);
386 return CaptureComponent2D->PostProcessSettings.DepthOfFieldMinFstop;
387}
388
390{
391 check(CaptureComponent2D != nullptr);
392 CaptureComponent2D->PostProcessSettings.DepthOfFieldBladeCount = Count;
393}
394
396{
397 check(CaptureComponent2D != nullptr);
398 return CaptureComponent2D->PostProcessSettings.DepthOfFieldBladeCount;
399}
400
402{
403 check(CaptureComponent2D != nullptr);
404 CaptureComponent2D->PostProcessSettings.FilmSlope = Slope;
405}
406
408{
409 check(CaptureComponent2D != nullptr);
410 return CaptureComponent2D->PostProcessSettings.FilmSlope;
411}
412
414{
415 check(CaptureComponent2D != nullptr);
416 CaptureComponent2D->PostProcessSettings.FilmToe = Toe; // FilmToeAmount?
417}
418
420{
421 check(CaptureComponent2D != nullptr);
422 return CaptureComponent2D->PostProcessSettings.FilmToe;
423}
424
426{
427 check(CaptureComponent2D != nullptr);
428 CaptureComponent2D->PostProcessSettings.FilmShoulder = Shoulder;
429}
430
432{
433 check(CaptureComponent2D != nullptr);
434 return CaptureComponent2D->PostProcessSettings.FilmShoulder;
435}
436
438{
439 check(CaptureComponent2D != nullptr);
440 CaptureComponent2D->PostProcessSettings.FilmBlackClip = BlackClip;
441}
442
444{
445 check(CaptureComponent2D != nullptr);
446 return CaptureComponent2D->PostProcessSettings.FilmBlackClip;
447}
448
450{
451 check(CaptureComponent2D != nullptr);
452 CaptureComponent2D->PostProcessSettings.FilmWhiteClip = WhiteClip;
453}
454
456{
457 check(CaptureComponent2D != nullptr);
458 return CaptureComponent2D->PostProcessSettings.FilmWhiteClip;
459}
460
462{
463 check(CaptureComponent2D != nullptr);
464 CaptureComponent2D->PostProcessSettings.AutoExposureMinBrightness = Brightness;
465}
466
468{
469 check(CaptureComponent2D != nullptr);
470 return CaptureComponent2D->PostProcessSettings.AutoExposureMinBrightness;
471}
472
474{
475 check(CaptureComponent2D != nullptr);
476 CaptureComponent2D->PostProcessSettings.AutoExposureMaxBrightness = Brightness;
477}
478
480{
481 check(CaptureComponent2D != nullptr);
482 return CaptureComponent2D->PostProcessSettings.AutoExposureMaxBrightness;
483}
484
486{
487 check(CaptureComponent2D != nullptr);
488 CaptureComponent2D->PostProcessSettings.AutoExposureSpeedDown = Speed;
489}
490
492{
493 check(CaptureComponent2D != nullptr);
494 return CaptureComponent2D->PostProcessSettings.AutoExposureSpeedDown;
495}
496
498{
499 check(CaptureComponent2D != nullptr);
500 CaptureComponent2D->PostProcessSettings.AutoExposureSpeedUp = Speed;
501}
502
504{
505 check(CaptureComponent2D != nullptr);
506 return CaptureComponent2D->PostProcessSettings.AutoExposureSpeedUp;
507}
508
510{
511 check(CaptureComponent2D != nullptr);
512 CaptureComponent2D->PostProcessSettings.AutoExposureCalibrationConstant_DEPRECATED = Constant;
513}
514
516{
517 check(CaptureComponent2D != nullptr);
518 return CaptureComponent2D->PostProcessSettings.AutoExposureCalibrationConstant_DEPRECATED;
519}
520
522{
523 check(CaptureComponent2D != nullptr);
524 CaptureComponent2D->PostProcessSettings.MotionBlurAmount = Intensity;
525}
526
528{
529 check(CaptureComponent2D != nullptr);
530 return CaptureComponent2D->PostProcessSettings.MotionBlurAmount;
531}
532
534{
535 check(CaptureComponent2D != nullptr);
536 CaptureComponent2D->PostProcessSettings.MotionBlurMax = MaxDistortion;
537}
538
540{
541 check(CaptureComponent2D != nullptr);
542 return CaptureComponent2D->PostProcessSettings.MotionBlurMax;
543}
544
546{
547 check(CaptureComponent2D != nullptr);
548 CaptureComponent2D->PostProcessSettings.MotionBlurPerObjectSize = ScreenSize;
549}
550
552{
553 check(CaptureComponent2D != nullptr);
554 return CaptureComponent2D->PostProcessSettings.MotionBlurPerObjectSize;
555}
556
558{
559 check(CaptureComponent2D != nullptr);
560 CaptureComponent2D->PostProcessSettings.LensFlareIntensity = Intensity;
561}
562
564{
565 check(CaptureComponent2D != nullptr);
566 return CaptureComponent2D->PostProcessSettings.LensFlareIntensity;
567}
568
569void ASceneCaptureSensor::SetBloomMethod(EBloomMethod Method)
570{
571 check(CaptureComponent2D != nullptr);
572 CaptureComponent2D->PostProcessSettings.BloomMethod = Method;
573}
574
576{
577 check(CaptureComponent2D != nullptr);
578 CaptureComponent2D->PostProcessSettings.BloomIntensity = Intensity;
579}
580
582{
583 check(CaptureComponent2D != nullptr);
584 return CaptureComponent2D->PostProcessSettings.BloomIntensity;
585}
586
588{
589 check(CaptureComponent2D != nullptr);
590 CaptureComponent2D->PostProcessSettings.WhiteTemp = Temp;
591}
592
594{
595 check(CaptureComponent2D != nullptr);
596 return CaptureComponent2D->PostProcessSettings.WhiteTemp;
597}
598
600{
601 check(CaptureComponent2D != nullptr);
602 CaptureComponent2D->PostProcessSettings.WhiteTint = Tint;
603}
604
606{
607 check(CaptureComponent2D != nullptr);
608 return CaptureComponent2D->PostProcessSettings.WhiteTint;
609}
610
612{
613 check(CaptureComponent2D != nullptr);
614 CaptureComponent2D->PostProcessSettings.SceneFringeIntensity = Intensity;
615}
616
618{
619 check(CaptureComponent2D != nullptr);
620 return CaptureComponent2D->PostProcessSettings.SceneFringeIntensity;
621}
622
624{
625 check(CaptureComponent2D != nullptr);
626 CaptureComponent2D->PostProcessSettings.ChromaticAberrationStartOffset = ChromAberrOffset;
627}
628
630{
631 check(CaptureComponent2D != nullptr);
632 return CaptureComponent2D->PostProcessSettings.ChromaticAberrationStartOffset;
633}
634
635void ASceneCaptureSensor::SetColorSaturation(FVector4 ColorSaturation)
636{
637 check(CaptureComponent2D != nullptr);
638 CaptureComponent2D->PostProcessSettings.ColorSaturation = ColorSaturation;
639}
640
642{
643 check(CaptureComponent2D != nullptr);
644 return CaptureComponent2D->PostProcessSettings.ColorSaturation;
645}
646
648{
649 check(CaptureComponent2D != nullptr);
650 CaptureComponent2D->PostProcessSettings.ColorSaturationMidtones = ColorSaturation;
651}
652
654{
655 check(CaptureComponent2D != nullptr);
656 return CaptureComponent2D->PostProcessSettings.ColorSaturationMidtones;
657}
658
660{
661 check(CaptureComponent2D != nullptr);
662 CaptureComponent2D->PostProcessSettings.ColorSaturationHighlights = ColorSaturation;
663}
664
666{
667 check(CaptureComponent2D != nullptr);
668 return CaptureComponent2D->PostProcessSettings.ColorSaturationHighlights;
669}
670
671void ASceneCaptureSensor::SetColorContrast(FVector4 ColorContrast)
672{
673 check(CaptureComponent2D != nullptr);
674 CaptureComponent2D->PostProcessSettings.ColorContrast = ColorContrast;
675}
676
678{
679 check(CaptureComponent2D != nullptr);
680 return CaptureComponent2D->PostProcessSettings.ColorContrast;
681}
682
684{
685 check(CaptureComponent2D != nullptr);
686 CaptureComponent2D->PostProcessSettings.ColorContrastMidtones = ColorContrast;
687}
688
690{
691 check(CaptureComponent2D != nullptr);
692 return CaptureComponent2D->PostProcessSettings.ColorContrastMidtones;
693}
694
696{
697 check(CaptureComponent2D != nullptr);
698 CaptureComponent2D->PostProcessSettings.ColorContrastHighlights = ColorContrast;
699}
700
702{
703 check(CaptureComponent2D != nullptr);
704 return CaptureComponent2D->PostProcessSettings.ColorContrastHighlights;
705}
706
707void ASceneCaptureSensor::SetColorGamma(FVector4 ColorGamma)
708{
709 check(CaptureComponent2D != nullptr);
710 CaptureComponent2D->PostProcessSettings.ColorGamma = ColorGamma;
711}
712
714{
715 check(CaptureComponent2D != nullptr);
716 return CaptureComponent2D->PostProcessSettings.ColorGamma;
717}
718
719void ASceneCaptureSensor::SetHighlightsGamma(FVector4 HighlightsGamma)
720{
721 check(CaptureComponent2D != nullptr);
722 CaptureComponent2D->PostProcessSettings.ColorGammaHighlights = HighlightsGamma;
723}
724
726{
727 check(CaptureComponent2D != nullptr);
728 return CaptureComponent2D->PostProcessSettings.ColorGammaHighlights;
729}
730
732{
733 check(CaptureComponent2D != nullptr);
734 CaptureComponent2D->PostProcessSettings.ToneCurveAmount = ToneCurveAmount;
735}
736
738{
739 check(CaptureComponent2D != nullptr);
740 return CaptureComponent2D->PostProcessSettings.ToneCurveAmount;
741}
742
743void ASceneCaptureSensor::SetSceneColorTint(FLinearColor SceneColorTint)
744{
745 check(CaptureComponent2D != nullptr);
746 CaptureComponent2D->PostProcessSettings.SceneColorTint = SceneColorTint;
747}
748
750{
751 check(CaptureComponent2D != nullptr);
752 return CaptureComponent2D->PostProcessSettings.SceneColorTint;
753}
754
755void ASceneCaptureSensor::SetVignetteIntensity(float VignetteIntensity)
756{
757 check(CaptureComponent2D != nullptr);
758 CaptureComponent2D->PostProcessSettings.VignetteIntensity = VignetteIntensity;
759}
760
762{
763 check(CaptureComponent2D != nullptr);
764 return CaptureComponent2D->PostProcessSettings.VignetteIntensity;
765}
766
768{
769 check(CaptureComponent2D != nullptr);
770 CaptureComponent2D->PostProcessSettings.ColorGain = Gain;
771}
772
774{
775 check(CaptureComponent2D != nullptr);
776 return CaptureComponent2D->PostProcessSettings.ColorGain;
777}
778
780{
781 check(CaptureComponent2D != nullptr);
782 CaptureComponent2D->PostProcessSettings.BlueCorrection = Val;
783}
784
786{
787 check(CaptureComponent2D != nullptr);
788 return CaptureComponent2D->PostProcessSettings.BlueCorrection;
789}
790
792{
793 check(CaptureComponent2D != nullptr);
794 CaptureComponent2D->PostProcessSettings.LocalExposureDetailStrength = Val;
795}
796
798{
799 check(CaptureComponent2D != nullptr);
800 return CaptureComponent2D->PostProcessSettings.LocalExposureDetailStrength;
801}
802
804{
805 check(CaptureComponent2D != nullptr);
806 CaptureComponent2D->PostProcessSettings.FilmGrainIntensity = Val;
807}
808
810{
811 check(CaptureComponent2D != nullptr);
812 return CaptureComponent2D->PostProcessSettings.FilmGrainIntensity;
813}
814
816{
817 check(CaptureComponent2D != nullptr);
818 CaptureComponent2D->PostProcessSettings.AmbientOcclusionIntensity = Intensity;
819}
820
822{
823 check(CaptureComponent2D != nullptr);
824 return CaptureComponent2D->PostProcessSettings.AmbientOcclusionIntensity;
825}
826
828{
829 check(CaptureComponent2D != nullptr);
830 CaptureComponent2D->PostProcessSettings.AmbientOcclusionRadius = Radius;
831}
832
834{
835 check(CaptureComponent2D != nullptr);
836 return CaptureComponent2D->PostProcessSettings.AmbientOcclusionRadius;
837}
838
839void ASceneCaptureSensor::SetHighlightContrastScale(float HighlightContrastScale)
840{
841 check(CaptureComponent2D != nullptr);
842 CaptureComponent2D->PostProcessSettings.LocalExposureHighlightContrastScale = HighlightContrastScale;
843}
844
846{
847 check(CaptureComponent2D != nullptr);
848 return CaptureComponent2D->PostProcessSettings.LocalExposureHighlightContrastScale;
849}
850
851void ASceneCaptureSensor::SetShadowContrastScale(float ShadowContrastScale)
852{
853 check(CaptureComponent2D != nullptr);
854 CaptureComponent2D->PostProcessSettings.LocalExposureShadowContrastScale = ShadowContrastScale;
855}
856
858{
859 check(CaptureComponent2D != nullptr);
860 return CaptureComponent2D->PostProcessSettings.LocalExposureShadowContrastScale;
861}
862
864 FPostProcessConfig &InOutPostProcessConfig)
865{
866}
867
868bool ASceneCaptureSensor::ApplyPostProcessVolumeToSensor(APostProcessVolume *Origin, ASceneCaptureSensor *Dest, bool bOverrideCurrentCamera)
869{
870 if (!IsValid(Origin) || !IsValid(Dest))
871 {
872 return false;
873 }
874
875 if (!bOverrideCurrentCamera)
876 {
877 // Cache postprocesssettings
878 float CacheGamma = Dest->GetTargetGamma();
879 EAutoExposureMethod CacheAutoExposureMethod = Dest->GetExposureMethod();
880 EBloomMethod CacheBloomMethod = Dest->GetBloomMethod();
881 UTexture2D *CacheBloomConvolutionTexture = Dest->GetBloomKernelTexture();
882 ELocalExposureMethod CacheLocalExposureMethod = Dest->GetLocalExposureMethod();
883 FVector4 CacheColorSaturation = Dest->GetColorSaturation();
884 FVector4 CacheColorSaturationMidtones = Dest->GetColorSaturationMidtones();
885 FVector4 CacheColorSaturationHighlights = Dest->GetColorSaturationHighlights();
886 FVector4 CacheColorContrast = Dest->GetColorContrast();
887 FVector4 CacheColorContrastMidtones = Dest->GetColorContrastMidtones();
888 FVector4 CacheColorContrastHighlights = Dest->GetColorContrastHighlights();
889 float CacheDetailStrength = Dest->GetDetailStrength();
890 float CacheBlueCorrection = Dest->GetBlueCorrection();
891 float CacheAmbientOcclusionIntensity = Dest->GetAOIntensity();
892 float CacheAmbientOcclusionRadius = Dest->GetAORadius();
893 float CacheFilmGrainIntensity = Dest->GetFilmGrainIntensity();
894 float CacheDirtIntensity = Dest->GetDirtMaskIntensity();
895 FVector4 CacheGain = Dest->GetGlobalGain();
896 float CacheEC = Dest->GetExposureCompensation();
897 float CacheSS = Dest->GetShutterSpeed();
898 float CacheISO = Dest->GetISO();
899 float CacheA = Dest->GetAperture();
900 float CacheFD = Dest->GetFocalDistance();
901 float CacheDBA = Dest->GetDepthBlurAmount();
902 float CacheDBR = Dest->GetDepthBlurRadius();
903 float CacheBC = Dest->GetBladeCount();
904 float CacheDFMinFStop = Dest->GetDepthOfFieldMinFstop();
905 float CacheFS = Dest->GetFilmSlope();
906 float CacheFT = Dest->GetFilmToe();
907 float CacheFShoulder = Dest->GetFilmShoulder();
908 float CacheFBC = Dest->GetFilmBlackClip();
909 float CacheFWC = Dest->GetFilmWhiteClip();
910 float CacheEMinB = Dest->GetExposureMinBrightness();
911 float CacheEMaxB = Dest->GetExposureMaxBrightness();
912 float CacheESDown = Dest->GetExposureSpeedDown();
913 float CacheESUp = Dest->GetExposureSpeedUp();
914 float CacheCC = Dest->GetExposureCalibrationConstant();
915 float CacheMBI = Dest->GetMotionBlurIntensity();
916 float CacheMBMaxD = Dest->GetMotionBlurMaxDistortion();
917 float CacheMBMinOSS = Dest->GetMotionBlurMinObjectScreenSize();
918 float CacheLFI = Dest->GetLensFlareIntensity();
919 float CacheBI = Dest->GetBloomIntensity();
920 float CacheWTemp = Dest->GetWhiteTemp();
921 float CacheWTint = Dest->GetWhiteTint();
922 float CacheCAI = Dest->GetChromAberrIntensity();
923 float CacheCAO = Dest->GetChromAberrOffset();
924
925 Dest->CaptureComponent2D->PostProcessSettings = Origin->Settings;
926
927 Dest->SetLocalExposureMethod(CacheLocalExposureMethod);
928 Dest->SetColorSaturation(CacheColorSaturation);
929 Dest->SetColorSaturationMidtones(CacheColorSaturationMidtones);
930 Dest->SetColorSaturationHighlights(CacheColorSaturationHighlights);
931 Dest->SetColorContrast(CacheColorContrast);
932 Dest->SetColorContrastMidtones(CacheColorContrastMidtones);
933 Dest->SetColorContrastHighlights(CacheColorContrastHighlights);
934 Dest->SetAOIntensity(CacheAmbientOcclusionIntensity);
935 Dest->SetAORadius(CacheAmbientOcclusionRadius);
936 Dest->SetBloomMethod(CacheBloomMethod);
937 Dest->SetBloomConvolutionTexture(CacheBloomConvolutionTexture);
938 Dest->SetDetailStrength(CacheDetailStrength);
939 Dest->SetBlueCorrection(CacheBlueCorrection);
940 Dest->SetFilmGrainIntensity(CacheFilmGrainIntensity);
941 Dest->SetDirtMaskIntensity(CacheDirtIntensity);
942 Dest->SetGlobalGain(CacheGain);
943 Dest->SetTargetGamma(CacheGamma);
944 Dest->SetExposureMethod(CacheAutoExposureMethod);
945 Dest->SetExposureCompensation(CacheEC);
946 Dest->SetShutterSpeed(CacheSS);
947 Dest->SetISO(CacheISO);
948 Dest->SetAperture(CacheA);
949 Dest->SetFocalDistance(CacheFD);
950 Dest->SetDepthBlurAmount(CacheDBA);
951 Dest->SetDepthBlurRadius(CacheDBR);
952 Dest->SetBladeCount(CacheBC);
953 Dest->SetDepthOfFieldMinFstop(CacheDFMinFStop);
954 Dest->SetFilmSlope(CacheFS);
955 Dest->SetFilmToe(CacheFT);
956 Dest->SetFilmShoulder(CacheFShoulder);
957 Dest->SetFilmBlackClip(CacheFBC);
958 Dest->SetFilmWhiteClip(CacheFWC);
959 Dest->SetExposureMinBrightness(CacheEMinB);
960 Dest->SetExposureMaxBrightness(CacheEMaxB);
961 Dest->SetExposureSpeedDown(CacheESDown);
962 Dest->SetExposureSpeedUp(CacheESUp);
963 Dest->SetExposureCalibrationConstant(CacheCC);
964 Dest->SetMotionBlurIntensity(CacheMBI);
965 Dest->SetMotionBlurMaxDistortion(CacheMBMaxD);
966 Dest->SetMotionBlurMinObjectScreenSize(CacheMBMinOSS);
967 Dest->SetLensFlareIntensity(CacheLFI);
968 Dest->SetBloomIntensity(CacheBI);
969 Dest->SetWhiteTemp(CacheWTemp);
970 Dest->SetWhiteTint(CacheWTint);
971 Dest->SetChromAberrIntensity(CacheCAI);
972 Dest->SetChromAberrOffset(CacheCAO);
973 }
974 else
975 {
976 Dest->CaptureComponent2D->PostProcessSettings = Origin->Settings;
977 }
978
979 return true;
980}
981
983{
984 TRACE_CPUPROFILER_EVENT_SCOPE(ASceneCaptureSensor::EnqueueRenderSceneImmediate);
985 // Show-only mode: refresh the actor list (only rescans when the world's
986 // actor count changed) and push it into the capture component so actors
987 // spawned since the last capture are included.
989 {
990 ShowOnlyFilter.Refresh(GetWorld(), &GetEpisode());
992 }
993 if (NumCaptures < CVarCarlaCameraSpawnCameraCuts.GetValueOnGameThread())
994 {
995 // Reset by the renderer after the capture.
996 CaptureComponent2D->bCameraCutThisFrame = true;
997 ++NumCaptures;
998 }
999 // Creates an snapshot of the scene, requieres bCaptureEveryFrame = false.
1000#ifdef CARLA_HAS_GBUFFER_API
1002#else
1003 GetCaptureComponent2D()->CaptureScene();
1004#endif
1005}
1006
1008{
1009 using namespace SceneCaptureSensor_local_ns;
1010
1011 // Determine the gamma of the player.
1012 const bool bInForceLinearGamma = !bEnablePostProcessingEffects;
1013
1014 CaptureRenderTarget->InitCustomFormat(
1015 ImageWidth,
1017 bEnable16BitFormat ? PF_FloatRGBA : PF_B8G8R8A8,
1018 bInForceLinearGamma);
1019
1021 {
1022 CaptureRenderTarget->TargetGamma = TargetGamma;
1023 }
1024
1025 check(IsValid(CaptureComponent2D) && IsValidChecked(CaptureComponent2D));
1026
1027 CaptureComponent2D->Deactivate();
1028 CaptureComponent2D->TextureTarget = CaptureRenderTarget;
1029
1030 // Optional DLSS upscaling: render the capture at a fraction of the target
1031 // resolution and let the engine's scene-capture temporal upscaler (DLSS
1032 // Super Resolution, bilinear fallback on non-NVIDIA hardware) fill the
1033 // render target. The render target itself stays at ImageWidth x ImageHeight,
1034 // so client-visible output resolution is unchanged.
1035 CaptureComponent2D->CaptureScreenPercentage =
1036 bEnableDLSSUpscale ? FMath::Clamp(DLSSScreenPercentage, 25.0f, 100.0f) : 100.0f;
1038 {
1039 UE_LOG(LogCarla, Warning, TEXT(
1040 "%s: DLSS upscaling requested but post-processing effects are disabled; "
1041 "the capture has no temporal AA method, so the engine will spatially "
1042 "upscale instead of DLSS."), *GetName());
1043 }
1044
1045 // Call derived classes to set up their things.
1047
1048 // The capture component's own settings assert bOverride_ on every camera
1049 // field (SetCameraDefaultOverrides), so map post-process volumes never blend
1050 // into sensor renders and sensors don't match the main viewport. Absorb the
1051 // map's enabled unbound PostProcessVolume here; the cache logic inside
1052 // ApplyPostProcessVolumeToSensor keeps the camera attributes configured
1053 // through the sensor API (exposure, film curve, DoF, ...) authoritative.
1054 {
1055 int32 VolumeCount = 0;
1056 bool bApplied = false;
1057 for (TActorIterator<APostProcessVolume> It(GetWorld()); It; ++It)
1058 {
1059 APostProcessVolume *Volume = *It;
1060 ++VolumeCount;
1061 if (!bApplied && bEnablePostProcessingEffects &&
1062 IsValid(Volume) && Volume->bEnabled && Volume->bUnbound)
1063 {
1064 ApplyPostProcessVolumeToSensor(Volume, this, false);
1065 UE_LOG(LogCarla, Log, TEXT("%s: absorbed map post-process volume %s"),
1066 *GetName(), *Volume->GetName());
1067 bApplied = true;
1068 }
1069 }
1070 if (!bApplied && VolumeCount > 0)
1071 {
1072 UE_LOG(LogCarla, Verbose, TEXT(
1073 "%s: no map post-process volume absorbed (bEnablePP=%d, volumes in world=%d)"),
1074 *GetName(), bEnablePostProcessingEffects ? 1 : 0, VolumeCount);
1075 }
1076 }
1077
1078 CaptureComponent2D->CaptureSource = ESceneCaptureSource::SCS_FinalToneCurveHDR;
1079
1080 CaptureComponent2D->UpdateContent();
1081 CaptureComponent2D->Activate();
1082
1083 // Nudge texture streaming priority at the new sensor's location so
1084 // a freshly attached camera does not stall the first few captures
1085 // waiting for its local region to reach full mip. One-shot 2-second
1086 // duration fades out naturally; permanent hints would widen the
1087 // priority surface on multi-camera dataset runs (N sensors = N
1088 // permanent streaming sources).
1089 IStreamingManager::Get().AddViewLocation(
1090 GetActorLocation(),
1091 /*BoostFactor=*/ 1.5f,
1092 /*bOverrideLocation=*/ true,
1093 /*Duration=*/ 2.0f);
1094
1095 auto PostProcessConfig = FPostProcessConfig(
1096 CaptureComponent2D->PostProcessSettings,
1097 CaptureComponent2D->ShowFlags);
1098 PostProcessConfig.UpdateFromSceneCaptureComponent2D(*CaptureComponent2D);
1099 PostProcessConfig.EnablePostProcessingEffects(ArePostProcessingEffectsEnabled());
1100 UpdatePostProcessConfig(PostProcessConfig);
1101 CaptureComponent2D->ShowFlags = PostProcessConfig.EngineShowFlags;
1102 CaptureComponent2D->PostProcessSettings = PostProcessConfig.PostProcessSettings;
1103
1104 // Exposure-linked motion blur (UpdateExposureMotionBlur) manages the flag
1105 // itself; otherwise motion blur stays off below 1080p as before.
1106 if ((ImageWidth < 1920 || ImageHeight < 1080) &&
1107 (CVarCarlaCameraExposureMotionBlur.GetValueOnGameThread() == 0 || !ArePostProcessingEffectsEnabled()))
1108 CaptureComponent2D->ShowFlags.SetMotionBlur(false);
1109
1110 // This ensures the camera is always spawning the raindrops in case the
1111 // weather was previously set to have rain.
1112 auto Weather = GetEpisode().GetWeather();
1113 if (Weather != nullptr)
1114 Weather->NotifyWeather(this);
1115
1116 ReadbackPool = MakeShared<FRHIGPUReadbackPool, ESPMode::ThreadSafe>(
1117 TEXT("SceneCaptureReadback"));
1118
1119 Super::BeginPlay();
1120}
1121
1123{
1124#ifdef CARLA_HAS_GBUFFER_API
1125 const auto HasListener = [](const auto &GBufferEntry)
1126 {
1127 return GBufferEntry.Stream.AreClientsListening();
1128 };
1129 const auto &GBuffers = CameraGBuffers;
1130 return
1131 HasListener(GBuffers.SceneColor) ||
1132 HasListener(GBuffers.SceneDepth) ||
1133 HasListener(GBuffers.SceneStencil) ||
1134 HasListener(GBuffers.GBufferA) ||
1135 HasListener(GBuffers.GBufferB) ||
1136 HasListener(GBuffers.GBufferC) ||
1137 HasListener(GBuffers.GBufferD) ||
1138 HasListener(GBuffers.GBufferE) ||
1139 HasListener(GBuffers.GBufferF) ||
1140 HasListener(GBuffers.Velocity) ||
1141 HasListener(GBuffers.SSAO) ||
1142 HasListener(GBuffers.CustomDepth) ||
1143 HasListener(GBuffers.CustomStencil);
1144#else
1145 return false;
1146#endif
1147}
1148
1150{
1151 // A process without an RHI (-nullrhi) never creates the capture render
1152 // target. Its cameras are rendered by a Multi-GPU secondary, so skip the
1153 // capture even when a local listener (for example ROS 2) is active.
1154 if (!FApp::CanEverRender())
1155 {
1156 return false;
1157 }
1158 if (CVarCarlaCameraForceAllGBuffers.GetValueOnAnyThread() > 0)
1159 {
1160 return true;
1161 }
1163}
1164
1165void ASceneCaptureSensor::PrePhysTick(float DeltaSeconds)
1166{
1167 TRACE_CPUPROFILER_EVENT_SCOPE(ASceneCaptureSensor::PrePhysTick);
1168 Super::PrePhysTick(DeltaSeconds);
1169
1171 {
1172 return;
1173 }
1174
1175 const float FOVRadians = FMath::DegreesToRadians(CaptureComponent2D->FOVAngle);
1176 const float HalfTan = FMath::Tan(0.5f * FOVRadians);
1177 const float StreamingBoundingRadius =
1178 HalfTan > 0.0f ? ImageWidth / HalfTan : static_cast<float>(ImageWidth);
1179 IStreamingManager::Get().AddViewInformation(
1180 CaptureComponent2D->GetComponentLocation(),
1181 ImageWidth,
1182 StreamingBoundingRadius);
1183}
1184
1185void ASceneCaptureSensor::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime)
1186{
1187 TRACE_CPUPROFILER_EVENT_SCOPE(ASceneCaptureSensor::PostPhysTick);
1188 Super::PostPhysTick(World, TickType, DeltaTime);
1189
1191 {
1192 return;
1193 }
1194 UpdateExposureMotionBlur(World, DeltaTime);
1196}
1197
1198void ASceneCaptureSensor::UpdateExposureMotionBlur(UWorld *World, float DeltaTime)
1199{
1200 // Simulation time between two captures of this sensor: the motion vectors
1201 // span it (the view state keeps the previous capture's matrices).
1202 const double Now = World != nullptr ? World->GetTimeSeconds() : 0.0;
1203 const float Interval = LastCaptureTime >= 0.0 && Now > LastCaptureTime
1204 ? static_cast<float>(Now - LastCaptureTime)
1205 : FMath::Max(DeltaTime, 1e-3f);
1206 LastCaptureTime = Now;
1207
1208 if (!ArePostProcessingEffectsEnabled() || CVarCarlaCameraExposureMotionBlur.GetValueOnGameThread() == 0)
1209 {
1210 return;
1211 }
1212 FSceneViewStateInterface *ViewState = CaptureComponent2D->GetViewState(0);
1213 const float Exposure = ViewState != nullptr ? ViewState->GetLastEyeAdaptationExposure() : 0.0f;
1214 if (!(Exposure > 0.0f) || !FMath::IsFinite(Exposure))
1215 {
1216 return; // no eye adaptation readback yet (first frames)
1217 }
1218 const float FNumber = FMath::Max(CVarCarlaCameraFNumber.GetValueOnGameThread(), 0.5f);
1219 const float MinSeconds = FMath::Max(CVarCarlaCameraMinExposureMs.GetValueOnGameThread(), 0.0f) * 1e-3f;
1220 const float MaxSeconds = FMath::Max(CVarCarlaCameraMaxExposureMs.GetValueOnGameThread() * 1e-3f, MinSeconds);
1221 ExposureSeconds = FMath::Clamp(FNumber * FNumber * 1.2f * Exposure, MinSeconds, MaxSeconds);
1222
1223 FPostProcessSettings &Settings = CaptureComponent2D->PostProcessSettings;
1224 Settings.bOverride_MotionBlurAmount = true;
1225 Settings.MotionBlurAmount = FMath::Clamp(ExposureSeconds / FMath::Max(Interval, 1e-3f), 0.0f, 1.0f);
1226 // 0 = follow the render rate, so the blur length does not depend on how
1227 // fast the simulator runs in wall-clock time (a fixed target FPS scales it
1228 // by target / real delta, wrong in synchronous mode).
1229 Settings.bOverride_MotionBlurTargetFPS = true;
1230 Settings.MotionBlurTargetFPS = 0;
1231 CaptureComponent2D->ShowFlags.SetMotionBlur(Settings.MotionBlurAmount > 0.001f);
1232
1233 if (CVarCarlaCameraExposureLog.GetValueOnGameThread() != 0)
1234 {
1235 UE_LOG(LogCarla, Log, TEXT("%s exposure %.4g (EV100 %.2f) -> %.3f ms, interval %.1f ms, motion blur %.3f"),
1236 *GetName(), Exposure, FMath::Log2(1.0f / (1.2f * Exposure)), ExposureSeconds * 1e3f, Interval * 1e3f,
1237 Settings.MotionBlurAmount);
1238 }
1239}
1240
1241void ASceneCaptureSensor::EndPlay(const EEndPlayReason::Type EndPlayReason)
1242{
1243 Super::EndPlay(EndPlayReason);
1244
1246 {
1247 CaptureRenderTarget->ReleaseResource();
1248 }
1249 // Free the persistent view state (Lumen scene, TSR history...) now instead
1250 // of at the next garbage collection; see USceneCaptureComponent2D_CARLA.
1252 {
1253 FlushRenderingCommands();
1254 CaptureComponent2D->Deactivate();
1255 CaptureComponent2D->ReleaseViewStates();
1256 }
1257 // Drop the sensor's strong ref. Any in-flight AsyncTask still holds a copy
1258 // of the shared_ptr, so the pool dies with the last consuming task.
1259 ReadbackPool.Reset();
1260 // SCENE_CAPTURE_COUNTER intentionally not reset: monotonic across the
1261 // process lifetime so subobject names assigned to the next sensor do not
1262 // collide with any sibling sensor still alive on that suffix.
1263}
1264
1265#ifdef CARLA_HAS_GBUFFER_API
1266
1267constexpr const TCHAR *GBufferNames[] =
1268 {
1269 TEXT("SceneColor"),
1270 TEXT("SceneDepth"),
1271 TEXT("SceneStencil"),
1272 TEXT("GBufferA"),
1273 TEXT("GBufferB"),
1274 TEXT("GBufferC"),
1275 TEXT("GBufferD"),
1276 TEXT("GBufferE"),
1277 TEXT("GBufferF"),
1278 TEXT("Velocity"),
1279 TEXT("SSAO"),
1280 TEXT("CustomDepth"),
1281 TEXT("CustomStencil"),
1282};
1283
1284template <EGBufferTextureID ID, typename T>
1285static void CheckGBufferStream(T &GBufferStream, FGBufferRequest &GBuffer)
1286{
1287 const bool bForceAll = CVarCarlaCameraForceAllGBuffers.GetValueOnAnyThread() > 0;
1288 GBufferStream.bIsUsed = bForceAll || GBufferStream.Stream.AreClientsListening();
1289 if (GBufferStream.bIsUsed)
1290 GBuffer.MarkAsRequested(ID);
1291}
1292
1293static uint64 Prior = 0;
1294
1296{
1297 // Fast path: no GBuffer client subscribed (and the force-all CVar off)
1298 // means every CheckGBufferStream below would no-op and we would fall
1299 // through to CaptureScene() anyway. Skip the per-frame FGBufferRequest
1300 // allocation and the 13 stream-listener checks.
1302 CVarCarlaCameraForceAllGBuffers.GetValueOnAnyThread() <= 0)
1303 {
1304 CaptureComponent2D->CaptureScene();
1305 return;
1306 }
1307
1308 auto GBufferPtr = MakeUnique<FGBufferRequest>();
1309 auto &GBuffer = *GBufferPtr;
1310
1311 CheckGBufferStream<EGBufferTextureID::SceneColor>(CameraGBuffers.SceneColor, GBuffer);
1312 CheckGBufferStream<EGBufferTextureID::SceneDepth>(CameraGBuffers.SceneDepth, GBuffer);
1313 CheckGBufferStream<EGBufferTextureID::SceneStencil>(CameraGBuffers.SceneStencil, GBuffer);
1314 CheckGBufferStream<EGBufferTextureID::GBufferA>(CameraGBuffers.GBufferA, GBuffer);
1315 CheckGBufferStream<EGBufferTextureID::GBufferB>(CameraGBuffers.GBufferB, GBuffer);
1316 CheckGBufferStream<EGBufferTextureID::GBufferC>(CameraGBuffers.GBufferC, GBuffer);
1317 CheckGBufferStream<EGBufferTextureID::GBufferD>(CameraGBuffers.GBufferD, GBuffer);
1318 CheckGBufferStream<EGBufferTextureID::GBufferE>(CameraGBuffers.GBufferE, GBuffer);
1319 CheckGBufferStream<EGBufferTextureID::GBufferF>(CameraGBuffers.GBufferF, GBuffer);
1320 CheckGBufferStream<EGBufferTextureID::Velocity>(CameraGBuffers.Velocity, GBuffer);
1321 CheckGBufferStream<EGBufferTextureID::SSAO>(CameraGBuffers.SSAO, GBuffer);
1322 CheckGBufferStream<EGBufferTextureID::CustomDepth>(CameraGBuffers.CustomDepth, GBuffer);
1323 CheckGBufferStream<EGBufferTextureID::CustomStencil>(CameraGBuffers.CustomStencil, GBuffer);
1324
1325 if (GBufferPtr->DesiredTexturesMask == 0)
1326 {
1327 // Creates an snapshot of the scene, requieres bCaptureEveryFrame = false.
1328 CaptureComponent2D->CaptureScene();
1329 return;
1330 }
1331
1332 if (Prior != GBufferPtr->DesiredTexturesMask)
1333 UE_LOG(LogCarla, Verbose, TEXT("GBuffer selection changed (%llu)."), GBufferPtr->DesiredTexturesMask);
1334
1335 Prior = GBufferPtr->DesiredTexturesMask;
1336 GBufferPtr->OwningActor = CaptureComponent2D->GetViewOwner();
1337
1338 // Flipping ShowFlags.TemporalAA per-frame (pre-UE5 workaround) destroys the
1339 // TSR history every capture. Leave temporal state alone; users needing
1340 // jitter-free GBuffer output can set r.AntiAliasingMethod 2 (FXAA) globally.
1341 CaptureComponent2D->CaptureSceneWithGBuffer(GBuffer);
1342
1343 AsyncTask(ENamedThreads::AnyHiPriThreadNormalTask, [this, GBuffer = MoveTemp(GBufferPtr)]() mutable
1344 { SendGBufferTextures(*GBuffer); });
1345}
1346
1347void ASceneCaptureSensor::SendGBufferTextures(FGBufferRequest &GBuffer)
1348{
1349 SendGBufferTexturesInternal(*this, GBuffer);
1350}
1351
1352#endif
1353
1354// =============================================================================
1355// -- Local static functions implementations -----------------------------------
1356// =============================================================================
1357
1359{
1360
1362 {
1363 auto &PostProcessSettings = CaptureComponent2D.PostProcessSettings;
1364
1365 PostProcessSettings.bOverride_ColorSaturationMidtones = true;
1366 PostProcessSettings.bOverride_ColorContrastMidtones = true;
1367 PostProcessSettings.bOverride_ColorSaturationHighlights = true;
1368 PostProcessSettings.bOverride_ColorContrastHighlights = true;
1369 PostProcessSettings.bOverride_AutoExposureMethod = true;
1370 PostProcessSettings.bOverride_ColorGain = true;
1371 PostProcessSettings.bOverride_LocalExposureMethod = true;
1372 PostProcessSettings.bOverride_BlueCorrection = true;
1373 PostProcessSettings.bOverride_FilmGrainIntensity = true;
1374 PostProcessSettings.bOverride_AmbientOcclusionIntensity = true;
1375 PostProcessSettings.bOverride_AmbientOcclusionRadius = true;
1376 PostProcessSettings.bOverride_BloomMethod = true;
1377 PostProcessSettings.bOverride_BloomDirtMaskIntensity = true;
1378 PostProcessSettings.bOverride_BloomConvolutionTexture = true;
1379 PostProcessSettings.bOverride_AutoExposureBias = true;
1380 PostProcessSettings.bOverride_CameraShutterSpeed = true;
1381 PostProcessSettings.bOverride_CameraISO = true;
1382 PostProcessSettings.bOverride_DepthOfFieldFstop = true;
1383 PostProcessSettings.bOverride_DepthOfFieldFocalDistance = true;
1384 PostProcessSettings.bOverride_DepthOfFieldDepthBlurAmount = true;
1385 PostProcessSettings.bOverride_DepthOfFieldDepthBlurRadius = true;
1386 PostProcessSettings.bOverride_DepthOfFieldMinFstop = true;
1387 PostProcessSettings.bOverride_DepthOfFieldBladeCount = true;
1388 PostProcessSettings.bOverride_DepthOfFieldSensorWidth = true;
1389 PostProcessSettings.bOverride_FilmSlope = true;
1390 PostProcessSettings.bOverride_FilmToe = true;
1391 PostProcessSettings.bOverride_FilmShoulder = true;
1392 PostProcessSettings.bOverride_FilmBlackClip = true;
1393 PostProcessSettings.bOverride_FilmWhiteClip = true;
1394 PostProcessSettings.bOverride_AutoExposureMinBrightness = true;
1395 PostProcessSettings.bOverride_AutoExposureMaxBrightness = true;
1396 PostProcessSettings.bOverride_AutoExposureSpeedDown = true;
1397 PostProcessSettings.bOverride_AutoExposureSpeedUp = true;
1398 PostProcessSettings.bOverride_AutoExposureCalibrationConstant_DEPRECATED = true;
1399 PostProcessSettings.bOverride_TemperatureType = true;
1400 PostProcessSettings.bOverride_MotionBlurAmount = true;
1401 PostProcessSettings.bOverride_MotionBlurMax = true;
1402 PostProcessSettings.bOverride_MotionBlurPerObjectSize = true;
1403 PostProcessSettings.bOverride_LensFlareIntensity = true;
1404 PostProcessSettings.bOverride_BloomIntensity = true;
1405 PostProcessSettings.bOverride_WhiteTemp = true;
1406 PostProcessSettings.bOverride_WhiteTint = true;
1407 PostProcessSettings.bOverride_SceneFringeIntensity = true;
1408 PostProcessSettings.bOverride_ChromaticAberrationStartOffset = true;
1409 PostProcessSettings.bOverride_ColorSaturation = true;
1410 PostProcessSettings.bOverride_ColorContrast = true;
1411 PostProcessSettings.bOverride_ColorGamma = true;
1412 PostProcessSettings.bOverride_ColorGammaHighlights = true;
1413 PostProcessSettings.bOverride_ToneCurveAmount = true;
1414 PostProcessSettings.bOverride_SceneColorTint = true;
1415 PostProcessSettings.bOverride_VignetteIntensity = true;
1416 PostProcessSettings.bOverride_LocalExposureHighlightContrastScale = true;
1417 PostProcessSettings.bOverride_LocalExposureShadowContrastScale = true;
1418
1419 PostProcessSettings.bOverride_DynamicGlobalIlluminationMethod = true;
1420 PostProcessSettings.DynamicGlobalIlluminationMethod = EDynamicGlobalIlluminationMethod::Lumen;
1421 PostProcessSettings.bOverride_LumenSceneLightingQuality = true;
1422 PostProcessSettings.LumenSceneLightingQuality = 1.0f;
1423 PostProcessSettings.bOverride_LumenSceneDetail = true;
1424 PostProcessSettings.LumenSceneDetail = 1.0f;
1425 PostProcessSettings.bOverride_LumenSceneViewDistance = true;
1426 PostProcessSettings.LumenSceneViewDistance = 20000.0f;
1427 PostProcessSettings.bOverride_LumenFinalGatherQuality = true;
1428 PostProcessSettings.LumenFinalGatherQuality = 1.0f;
1429 PostProcessSettings.bOverride_LumenMaxTraceDistance = true;
1430 PostProcessSettings.LumenMaxTraceDistance = 20000.0f;
1431 PostProcessSettings.bOverride_LumenSurfaceCacheResolution = true;
1432 PostProcessSettings.LumenSurfaceCacheResolution = 1.0f;
1433 PostProcessSettings.bOverride_LumenSceneLightingUpdateSpeed = true;
1434 PostProcessSettings.LumenSceneLightingUpdateSpeed = 1.0f;
1435 PostProcessSettings.bOverride_LumenFinalGatherLightingUpdateSpeed = true;
1436 PostProcessSettings.LumenFinalGatherLightingUpdateSpeed = 1.0f;
1437 PostProcessSettings.bOverride_LumenDiffuseColorBoost = true;
1438 PostProcessSettings.LumenDiffuseColorBoost = 1.0f;
1439 PostProcessSettings.bOverride_LumenSkylightLeaking = true;
1440 PostProcessSettings.LumenSkylightLeaking = 0.1f;
1441 PostProcessSettings.bOverride_LumenFullSkylightLeakingDistance = true;
1442 PostProcessSettings.LumenFullSkylightLeakingDistance = 1000.0f;
1443 PostProcessSettings.bOverride_ReflectionMethod = true;
1444 PostProcessSettings.ReflectionMethod = EReflectionMethod::Lumen;
1445 PostProcessSettings.bOverride_LumenReflectionQuality = true;
1446 PostProcessSettings.LumenReflectionQuality = 1.0f;
1447 PostProcessSettings.bOverride_LumenRayLightingMode = true;
1448 PostProcessSettings.LumenRayLightingMode = ELumenRayLightingModeOverride::Default;
1449 PostProcessSettings.bOverride_LumenFrontLayerTranslucencyReflections = true;
1450 PostProcessSettings.LumenFrontLayerTranslucencyReflections = true;
1451 PostProcessSettings.bOverride_LumenMaxReflectionBounces = true;
1452 PostProcessSettings.LumenMaxReflectionBounces = 3;
1453 }
1454} // namespace SceneCaptureSensor_local_ns
static TAutoConsoleVariable< int32 > CVarCarlaCameraSpawnCameraCuts(TEXT("carla.Camera.SpawnCameraCuts"), 2, TEXT("from the second image on instead of adapting for seconds from a default exposure (0 disables)."), ECVF_Default)
static TAutoConsoleVariable< float > CVarCarlaCameraMaxExposureMs(TEXT("carla.Camera.MaxExposureMs"), 20.0f, TEXT("Longest exposure time in ms; darker scenes raise the gain instead (carla.Camera.ExposureMotionBlur)."), ECVF_Default)
static TAutoConsoleVariable< int32 > CVarCarlaCameraExposureLog(TEXT("carla.Camera.ExposureLog"), 0, TEXT("1: log each RGB capture's exposure, exposure time and motion blur amount."), ECVF_Default)
static TAutoConsoleVariable< float > CVarCarlaCameraMinExposureMs(TEXT("carla.Camera.MinExposureMs"), 0.05f, TEXT("Shortest exposure time in ms (carla.Camera.ExposureMotionBlur)."), ECVF_Default)
static int32 GetCameraRayTracingOverride()
static TAutoConsoleVariable< int32 > CVarCarlaCameraForceAllGBuffers(TEXT("carla.Camera.ForceAllGBuffers"), 0, TEXT("one-release rollback path; default is 0 (lazy, by subscription)."), ECVF_Default)
static TAutoConsoleVariable< float > CVarCarlaCameraFNumber(TEXT("carla.Camera.FNumber"), 2.0f, TEXT("Lens f-number used to turn the auto exposure into an exposure time (carla.Camera.ExposureMotionBlur)."), ECVF_Default)
static TAutoConsoleVariable< int32 > CVarCarlaCameraExposureMotionBlur(TEXT("carla.Camera.ExposureMotionBlur"), 1, TEXT("0: use the motion_blur_* attributes / post-process profile as they are."), ECVF_Default)
static std::atomic< int > SCENE_CAPTURE_COUNTER
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
Base class for sensors using a USceneCaptureComponent2D for rendering the scene.
void SetExposureMethod(EAutoExposureMethod Method)
void SetFOVAngle(float FOVAngle)
virtual void PrePhysTick(float DeltaSeconds) override
float GetMotionBlurMaxDistortion() const
void SetShutterSpeed(float Speed)
bool ShouldCaptureThisFrame()
Aggregate gate: main stream or any GBuffer stream has listeners, or CVarCarlaCameraForceAllGBuffers f...
void SetHighlightsGamma(FVector4 HighlightsGamma)
static bool ApplyPostProcessVolumeToSensor(APostProcessVolume *Origin, ASceneCaptureSensor *Dest, bool bOverrideCurrentCamera=false)
TObjectPtr< UTextureRenderTarget2D > CaptureRenderTarget
Render target necessary for scene capture.
FRHIGPUReadbackPoolPtr ReadbackPool
Per-sensor pool of recyclable RHI readback objects.
void SetImageSize(uint32 Width, uint32 Height)
UTexture2D * GetBloomKernelTexture() const
void SetChromAberrIntensity(float Intensity)
float GetDepthOfFieldMinFstop() const
void SetMotionBlurMinObjectScreenSize(float ScreenSize)
void SetHighlightContrastScale(float HighlightContrastScale)
void Set(const FActorDescription &ActorDescription) override
float DLSSScreenPercentage
Internal render resolution as a percentage of the target resolution when bEnableDLSSUpscale is set.
void SetVignetteIntensity(float VignetteIntensity)
float GetDirtMaskIntensity() const
FVector4 GetColorContrast() const
float GetChromAberrOffset() const
void SetFilmShoulder(float Shoulder)
void SetExposureCompensation(float Compensation)
TObjectPtr< USceneCaptureComponent2D_CARLA > CaptureComponent2D
Scene capture component.
ELocalExposureMethod GetLocalExposureMethod() const
void SetMotionBlurMaxDistortion(float MaxDistortion)
void SetDepthBlurAmount(float Amount)
void SetExposureMaxBrightness(float Brightness)
static bool ResolveCameraRayTracing(bool bSensorEnabled, bool bRequired)
Applies the carla.Camera.UseRayTracing tier policy to a camera's own ray-tracing preference.
void SetUseRayTracing(bool Enable)
FVector4 GetColorContrastMidtones() const
struct ASceneCaptureSensor::@0 CameraGBuffers
float GetShadowContrastScale() const
bool IsAnyGBufferClientListening() const
Returns true if any GBuffer stream has an active listener.
float GetLensFlareIntensity() const
void SetWhiteTemp(float Temp)
void SetFilmBlackClip(float BlackClip)
void SetBloomMethod(EBloomMethod Method)
float ExposureSeconds
Exposure time of the last capture in seconds (exposure-linked motion blur).
float GetMotionBlurMinObjectScreenSize() const
void SetAORadius(float Radius)
void SetExposureCalibrationConstant(float Constant)
void SetAperture(float Aperture)
void SetBlueCorrection(float Val)
FLinearColor GetSceneColorTint() const
uint32 ImageWidth
Image width in pixels.
FVector4 GetColorSaturationMidtones() const
void SetDepthBlurRadius(float Radius)
void SetFocalDistance(float Distance)
void SetChromAberrOffset(float ChromAberrOffset)
bool bEnableDLSSUpscale
Render the capture at DLSSScreenPercentage of the target resolution and upscale back with DLSS Super ...
FVector4 GetColorGamma() const
virtual void UpdatePostProcessConfig(FPostProcessConfig &InOutPostProcessConfig)
USceneCaptureComponent2D * GetCaptureComponent2D()
bool ArePostProcessingEffectsEnabled() const
FVector4 GetColorContrastHighlights() const
void SetDirtMaskIntensity(float Intensity)
FVector4 GetGlobalGain() const
float GetExposureMaxBrightness() const
void SetLensFlareIntensity(float Intensity)
void SetBladeCount(int Count)
bool bUseRayTracing
Whether this sensor uses hardware ray tracing for its scene capture.
void SetSensorWidth(float Width)
float GetChromAberrIntensity() const
void SetDetailStrength(float Val)
void EnqueueRenderSceneImmediate()
Immediate enqueues render commands of the scene at the current time.
void SetColorSaturationMidtones(FVector4 ColorSaturation)
void SetFilmWhiteClip(float WhiteClip)
void SetBloomIntensity(float Intensity)
void SetMotionBlurIntensity(float Intensity)
void SetColorContrastMidtones(FVector4 ColorContrast)
void SetGlobalGain(FVector4 Gain)
virtual void SetUpSceneCaptureComponent(USceneCaptureComponent2D &SceneCapture)
void SetFilmGrainIntensity(float Val)
float GetFilmGrainIntensity() const
void SetAOIntensity(float Intensity)
double LastCaptureTime
Simulation time of this sensor's previous capture (-1 before the first).
void SetBloomConvolutionTexture(UTexture2D *Texture)
uint32 ImageHeight
Image height in pixels.
void UpdateExposureMotionBlur(UWorld *World, float DeltaTime)
Motion blur from the auto exposure time (carla.Camera.ExposureMotionBlur).
float GetExposureSpeedDown() const
EBloomMethod GetBloomMethod() const
void SetTargetGamma(float InTargetGamma)
void SetDepthOfFieldMinFstop(float MinFstop)
bool bEnable16BitFormat
Whether to change render target format to PF_A16B16G16R16, offering 16bit / channel.
void SetColorContrast(FVector4 ColorContrast)
bool bEnablePostProcessingEffects
Whether to render the post-processing effects present in the scene.
float GetExposureCalibrationConstant() const
virtual void BeginPlay() override
void SetColorSaturation(FVector4 ColorSaturation)
float GetExposureCompensation() const
float GetVignetteIntensity() const
void SetColorGamma(FVector4 ColorGamma)
void SetWhiteTint(float Tint)
virtual bool RequiresRayTracing() const
True for sensors that cannot render without hardware ray tracing (path-traced lens cameras); the tier...
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
int32 NumCaptures
Captures rendered as camera cuts since BeginPlay (carla.Camera.SpawnCameraCuts).
FCarlaShowOnlyFilter ShowOnlyFilter
Show-only actor filter, applied to the capture component right before every capture (see FCarlaShowOn...
void SetShadowContrastScale(float ShadowContrastScale)
ASceneCaptureSensor(const FObjectInitializer &ObjectInitializer)
EAutoExposureMethod GetExposureMethod() const
float GetExposureMinBrightness() const
void SetLocalExposureMethod(ELocalExposureMethod Method)
void SetExposureSpeedDown(float Speed)
FVector4 GetColorSaturation() const
void SetFilmSlope(float Slope)
float GetHighlightContrastScale() const
FVector4 GetColorSaturationHighlights() const
void SetExposureSpeedUp(float Speed)
float GetMotionBlurIntensity() const
void SetExposureMinBrightness(float Brightness)
virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override
void SetColorSaturationHighlights(FVector4 ColorSaturation)
void SetColorContrastHighlights(FVector4 ColorContrast)
FVector4 GetHighlightsGamma() const
void SetToneCurveAmount(float ToneCurveAmount)
void SetSceneColorTint(FLinearColor SceneColorTint)
void NotifyWeather(ASensor *Sensor=nullptr)
Notifing the weather to the blueprint's event.
Definition Weather.cpp:2650
static void SetCamera(const FActorDescription &Description, ASceneCaptureSensor *Camera)
AWeather * GetWeather() const
static UCarlaSettings * GetCarlaSettings(const UObject *WorldContextObject)
static void SetCameraDefaultOverrides(USceneCaptureComponent2D &CaptureComponent2D)
static auto GetQualitySettings(UWorld *World)
A description of a Carla Actor with all its variation.
void Refresh(UWorld *World, const UCarlaEpisode *Episode)
Rebuild the cached actor list if the world changed since the last call.
void ApplyTo(USceneCaptureComponent2D &Capture) const
Push the current list into Capture (or restore full-scene rendering when the filter is disabled).