CARLA
Loading...
Searching...
No Matches
SceneCaptureCamera_RayTracedLens.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
8#include "Carla.h"
12
14
15#include <type_traits>
16
17// Path-tracer DOF piggybacks on the standard cinematic depth-of-field
18// post-process fields (DepthOfFieldFstop / DepthOfFieldFocalDistance,
19// inherited from ASceneCaptureSensor) -- the path tracer's circle-of-confusion
20// model already reads those to derive its physical lens radius, no separate
21// DOF mechanism needed. aperture_fstop=0 requests a pinhole (no depth of
22// field); there is no literal "infinite f-stop" so approximate it with a very
23// small aperture instead.
24static constexpr float GPinholeApertureFstop = 32.0f;
25
26// Rollback valve for the synchronous-mode blocking delivery below. Off, the
27// sensor keeps the asynchronous one-frame-late readback in every mode.
28static TAutoConsoleVariable<int32> CVarRTLensSyncBlockingReadback(
29 TEXT("carla.RTLens.SyncModeBlockingReadback"),
30 1,
31 TEXT("In synchronous mode, deliver the rt_lens image captured on the same tick.\n")
32 TEXT(" 0: always use the asynchronous, one-tick-late, droppable readback.\n")
33 TEXT(" 1: capture then read back through the per-tick batched GPU sync (default)."),
34 ECVF_Default);
35
36// Rollback valve for the synchronous-mode complete-pipeline policy (see
37// RTLensEngineAdapter::SetBlockingRayTracingPipelineCreation). Off, the sensor
38// leaves r.RayTracing.NonBlockingPipelineCreation alone and freshly spawned
39// actors render black and untagged for the ticks their ray tracing pipeline
40// takes to compile.
41static TAutoConsoleVariable<int32> CVarRTLensSyncBlockingPipelineCreation(
42 TEXT("carla.RTLens.SyncModeBlockingPipelineCreation"),
43 1,
44 TEXT("In synchronous mode, wait for the ray tracing material pipeline before rendering.\n")
45 TEXT(" 0: leave r.RayTracing.NonBlockingPipelineCreation as configured (new actors may render with the fallback hit shader for a few ticks).\n")
46 TEXT(" 1: set r.RayTracing.NonBlockingPipelineCreation 0 while synchronous, restore it when asynchronous (default)."),
47 ECVF_Default);
48
49// The path-traced view's eye adaptation can meter the raw sun disk radiance and
50// adapt to ~EV18 (measured on Town12), crushing the frame to black. Its
51// exposure range is the camera profile's, with the upper end capped here.
52static TAutoConsoleVariable<float> CVarRTLensMaxAutoExposureEV(
53 TEXT("carla.RTLens.MaxAutoExposureEV"),
54 12.0f,
55 TEXT("Upper limit (EV100) of the rt_lens auto exposure range; the lower limit is the camera profile's."),
56 ECVF_Default);
57
58// =============================================================================
59// -- Local static helpers ------------------------------------------------------
60// =============================================================================
61
63{
64
65 static ECameraModel ParseCameraModelName(const FString &Name)
66 {
67 static const FString Lookup[] =
68 {
69 TEXT("perspective"),
70 TEXT("stereographic"),
71 TEXT("equidistant"),
72 TEXT("equisolid"),
73 TEXT("orthographic"),
74 TEXT("kannala_brandt"),
75 TEXT("brown_conrady"),
76 TEXT("lut"),
77 TEXT("ftheta"),
78 };
79
80 using I = std::underlying_type_t<ECameraModel>;
81
82 static_assert(
83 sizeof(Lookup) / sizeof(Lookup[0]) == (I)ECameraModel::MaxEnum,
84 "camera_model string lookup size mismatch.");
85
86 for (I i = 0; i != (I)ECameraModel::MaxEnum; ++i)
87 {
88 if (Name == Lookup[i])
89 return (ECameraModel)i;
90 }
91
92 UE_LOG(LogCarla, Warning,
93 TEXT("ASceneCaptureCamera_RayTracedLens: unknown camera_model '%s', defaulting to perspective."),
94 *Name);
96 }
97
98 // Image-plane radius (normalized units, half-width = 0.5 at fx = 1) that the
99 // given model maps a ray at angle Theta from the optical axis to. Used to
100 // derive fx from a requested horizontal field of view. LUT1D is excluded:
101 // its scale is part of the calibration data itself.
102 static float RadialAtTheta(
103 ECameraModel Model,
104 float Theta,
105 TArrayView<const float> Coeffs)
106 {
107 switch (Model)
108 {
110 case ECameraModel::BrownConrady: // distortion applies on top of a tan projection
111 return FMath::Tan(FMath::Min(Theta, FMath::DegreesToRadians(89.5f)));
113 return 2.0f * FMath::Tan(Theta * 0.5f);
115 return Theta;
117 return 2.0f * FMath::Sin(Theta * 0.5f);
119 return FMath::Sin(FMath::Min(Theta, PI * 0.5f));
123 return CameraModelUtil::FTheta::SolveRadius(Theta, Coeffs);
124 default:
125 return FMath::Tan(FMath::Min(Theta, FMath::DegreesToRadians(89.5f)));
126 }
127 }
128
129 static TArray<float> ParseFloatCSV(const FString &CSV)
130 {
131 TArray<float> Result;
132 if (CSV.IsEmpty())
133 return Result;
134 TArray<FString> Parts;
135 CSV.ParseIntoArray(Parts, TEXT(","), true);
136 Result.Reserve(Parts.Num());
137 for (const auto &Part : Parts)
138 Result.Add(FCString::Atof(*Part));
139 return Result;
140 }
141
142} // namespace SceneCaptureCameraRayTracedLens_local_ns
143
144// =============================================================================
145// -- ASceneCaptureCamera_RayTracedLens -----------------------------------------
146// =============================================================================
147
149{
150 constexpr bool bEnableModifyingPostProcessEffects = true;
152 TEXT("rt_lens"),
153 bEnableModifyingPostProcessEffects);
154}
155
157 : Super(ObjectInitializer)
158{
159 // The path tracer has no rasterized fallback the way ASceneCaptureCamera
160 // does; without hardware ray tracing this sensor cannot render at all.
161 SetUseRayTracing(true);
162
163 check(CaptureComponent2D != nullptr);
164 auto &PostProcessSettings = CaptureComponent2D->PostProcessSettings;
165 PostProcessSettings.bOverride_PathTracingSamplesPerPixel = true;
166 PostProcessSettings.bOverride_PathTracingEnableDenoiser = true;
167 PostProcessSettings.PathTracingSamplesPerPixel = SamplesPerPixel;
168 PostProcessSettings.PathTracingEnableDenoiser = bEnableDenoiser;
170}
171
173{
174 // Keep the camera profile's auto exposure (method, speeds, bias and the
175 // lower end of its range, which night scenes need) and only cap the upper
176 // end, so the path-traced view cannot meter the sun disk and go black (see
177 // carla.RTLens.MaxAutoExposureEV). A fixed daylight range (EV 10-12) used to
178 // be pinned here, which crushed every night frame to black.
179 auto &PostProcessSettings = CaptureComponent2D->PostProcessSettings;
180 const float MaxEV = CVarRTLensMaxAutoExposureEV.GetValueOnGameThread();
181 if (!PostProcessSettings.bOverride_AutoExposureMaxBrightness ||
182 PostProcessSettings.AutoExposureMaxBrightness > MaxEV)
183 {
184 PostProcessSettings.bOverride_AutoExposureMaxBrightness = true;
185 PostProcessSettings.AutoExposureMaxBrightness = MaxEV;
186 }
187 if (PostProcessSettings.bOverride_AutoExposureMinBrightness &&
188 PostProcessSettings.AutoExposureMinBrightness > MaxEV)
189 {
190 PostProcessSettings.AutoExposureMinBrightness = MaxEV;
191 }
192}
193
195{
196 // Handles image_size_x/y, fov, use_ray_tracing, enable_postprocess_effects,
197 // post_process_profile, sensor_tick -- via SetCamera(Description,
198 // ASceneCaptureSensor*), the same as every other scene-capture camera.
199 Super::Set(Description);
200
202
203 const auto &Variations = Description.Variations;
204
205 check(CaptureComponent2D != nullptr);
206
207 // -- Lens model -------------------------------------------------------------
208 LensModel.Model = ParseCameraModelName(
210 "camera_model", Variations, TEXT("perspective")));
211 LensModel.Coeffs = ParseFloatCSV(
213 "distortion_coeffs", Variations, TEXT("")));
214 LensModel.LUT = ParseFloatCSV(
216 "lut", Variations, TEXT("")));
218 "fx", Variations, 0.0f);
220 "fy", Variations, 0.0f);
222 "cx", Variations, 0.5f);
224 "cy", Variations, 0.5f);
225
226 // fx/fy <= 0 requests automatic focal length: place the requested horizontal
227 // fov (through the selected model's projection) exactly across the image
228 // width. An explicit calibration (fx > 0) always wins.
229 // Cap at 170 degrees for now: half-angles at/above 90 degrees (rays entering
230 // the backward hemisphere) currently spin the lens ray-generation shader and
231 // hang the GPU. Lift the cap once the shader handles theta >= pi/2 robustly.
233 "fov", Variations, 90.0f);
234 const float FOVDeg = FMath::Clamp(FOVDegRequested, 1.0f, 170.0f);
235 if (FOVDegRequested > 170.0f)
236 {
237 UE_LOG(LogCarla, Warning,
238 TEXT("ASceneCaptureCamera_RayTracedLens: fov=%.1f clamped to 170 (known shader limitation beyond 170 degrees)."),
239 FOVDegRequested);
240 }
241 const float ThetaHalf = FMath::DegreesToRadians(FOVDeg) * 0.5f;
242 if (LensModel.FocalX <= 0.0f)
243 {
245 {
246 UE_LOG(LogCarla, Warning,
247 TEXT("ASceneCaptureCamera_RayTracedLens: camera_model=lut/ftheta needs an explicit fx (1/width for pixel-unit coefficients); using fx=1."));
248 LensModel.FocalX = 1.0f;
249 }
250 else
251 {
252 const float Radius = RadialAtTheta(LensModel.Model, ThetaHalf, LensModel.Coeffs);
253 LensModel.FocalX = 0.5f / FMath::Max(Radius, 1.0e-6f);
254 }
255 }
256 if (LensModel.FocalY <= 0.0f)
257 {
258 // The focal lengths are normalized per axis (x by width, y by height), so square
259 // pixels are fy = fx * width/height; fy = fx would squash by the aspect ratio.
260 const float AspectRatio =
261 FMath::Max((float)GetImageWidth(), 1.0f) / FMath::Max((float)GetImageHeight(), 1.0f);
262 LensModel.FocalY = LensModel.FocalX * AspectRatio;
263 }
264
265 // theta_max_deg <= 0 requests automatic coverage: extend the acceptance
266 // angle to the frame corners so no pixel is left without a ray.
268 "theta_max_deg", Variations, 0.0f);
269 if (ThetaMaxDeg > 0.0f)
270 {
271 LensModel.ThetaMax = FMath::DegreesToRadians(ThetaMaxDeg);
272 }
273 else
274 {
275 const float Width = FMath::Max((float)GetImageWidth(), 1.0f);
276 const float Height = FMath::Max((float)GetImageHeight(), 1.0f);
277 const float CornerScale = FMath::Sqrt(1.0f + FMath::Square(Height / Width));
278 LensModel.ThetaMax = FMath::Min(ThetaHalf * CornerScale, FMath::DegreesToRadians(89.0f));
279 }
281 "ca_shift_r", Variations, 1.0f);
283 "ca_shift_b", Variations, 1.0f);
284
286
287 // -- Depth of field, through the standard scene-capture post-process ------
288 // fields inherited from ASceneCaptureSensor (see GPinholeApertureFstop).
290 "aperture_fstop", Variations, 0.0f);
291 SetAperture(ApertureFstop > 0.0f ? ApertureFstop : GPinholeApertureFstop);
294 "focus_distance_m", Variations, 1000.0f)
295 * 100.0f); // meters -> UE centimeters.
296
297 // -- Path-tracer quality -----------------------------------------------------
299 "samples_per_pixel", Variations, 16);
301 "enable_denoiser", Variations, true);
302
303 // The path tracer runs at most r.PathTracing.MaxFramePassCount sample passes per
304 // frame. A sensor asking for more can never finish (and denoise) within a tick:
305 // every frame it would deliver a partially accumulated image, which is far noisier
306 // than a smaller count that converges. Clamp to the cap and say so.
307 if (const IConsoleVariable* MaxPassCountVar =
308 IConsoleManager::Get().FindConsoleVariable(TEXT("r.PathTracing.MaxFramePassCount")))
309 {
310 const int32 MaxPassCount = FMath::Max(MaxPassCountVar->GetInt(), 1);
311 if (SamplesPerPixel > MaxPassCount)
312 {
313 UE_LOG(LogCarla, Warning,
314 TEXT("rt_lens: samples_per_pixel %d exceeds r.PathTracing.MaxFramePassCount %d; "
315 "clamping so every frame converges and denoises within the tick"),
316 SamplesPerPixel, MaxPassCount);
317 SamplesPerPixel = MaxPassCount;
318 }
319 }
320
321 CaptureComponent2D->PostProcessSettings.bOverride_PathTracingSamplesPerPixel = true;
322 CaptureComponent2D->PostProcessSettings.bOverride_PathTracingEnableDenoiser = true;
323 CaptureComponent2D->PostProcessSettings.PathTracingSamplesPerPixel = SamplesPerPixel;
324 CaptureComponent2D->PostProcessSettings.PathTracingEnableDenoiser = bEnableDenoiser;
325
326 // SetCamera above loaded the camera profile; cap its exposure range (see
327 // SetRayTracedLensExposure).
329
330 // exposure_mode=manual: deterministic exposure from the profile's physical
331 // camera; needed when the layer is composited against an external render and
332 // the frame content (show-only actors over a black background) would drive
333 // the histogram. exposure_compensation (EV) adds to the profile's bias in
334 // either mode.
335 {
337 "exposure_mode", Variations, TEXT("auto"));
338 auto &PPS = CaptureComponent2D->PostProcessSettings;
339 if (ExposureMode == TEXT("manual"))
340 {
341 PPS.bOverride_AutoExposureMethod = true;
342 PPS.AutoExposureMethod = AEM_Manual;
343 }
344 const float ProfileBias = PPS.bOverride_AutoExposureBias ? PPS.AutoExposureBias : 0.0f;
345 PPS.bOverride_AutoExposureBias = true;
346 PPS.AutoExposureBias = ProfileBias + UActorBlueprintFunctionLibrary::RetrieveActorAttributeToFloat(
347 "exposure_compensation", Variations, 0.0f);
348 }
349}
350
352{
353 Super::UpdatePostProcessConfig(InOutPostProcessConfig);
354 InOutPostProcessConfig.EngineShowFlags.SetPathTracing(true);
355}
356
360
364
365void ASceneCaptureCamera_RayTracedLens::EndPlay(const EEndPlayReason::Type EndPlayReason)
366{
367 // Process-wide override made in PostPhysTick for synchronous mode; a sensor
368 // destroyed while synchronous must not leave it behind (any other live
369 // rt_lens sensor sets it again on its next tick).
371 Super::EndPlay(EndPlayReason);
372}
373
374void ASceneCaptureCamera_RayTracedLens::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaSeconds)
375{
376 TRACE_CPUPROFILER_EVENT_SCOPE(ASceneCaptureCamera_RayTracedLens::PostPhysTick);
377
378 // Reassert the lens configuration every tick. Several code paths replace the
379 // capture component's PostProcessSettings wholesale after Set() ran -- most
380 // notably ApplyPostProcessVolumeToSensor, which copies the map's
381 // PostProcessVolume settings and restores only the standard camera fields
382 // from its cache. Losing the PathTracingLens* fields silently reverts the
383 // camera to an undistorted pinhole and drops the sample/denoiser targets.
384 //
385 // The scene is captured EXACTLY ONCE per tick, inside Super::PostPhysTick.
386 // The path tracer accumulates one sample per rendered frame and, with
387 // bAlwaysPersistRenderingState (set on the base capture component), keeps its
388 // accumulation and spatiotemporal-denoiser history across ticks: a static
389 // camera converges over successive ticks, a moving camera relies on the
390 // spatial denoiser. Never issue extra CaptureScene() calls here -- each one
391 // is a full blocking path-trace on the game thread, and looping them starves
392 // the tick and the RPC server (the sensor and the whole server freeze).
393 if (AreClientsListening() && CaptureComponent2D != nullptr)
394 {
396 // The bOverride_ flags must be reasserted together with the values: the
397 // wholesale PostProcessSettings replacement clears them, and without the
398 // flags the FinalPostProcessSettings blend ignores these fields entirely
399 // (the map's PostProcessVolume then wins -- e.g. 2048 spp -- and the
400 // denoiser gate Iteration+1 == MaxSPP can never fire on a moving camera).
401 CaptureComponent2D->PostProcessSettings.bOverride_PathTracingSamplesPerPixel = true;
402 CaptureComponent2D->PostProcessSettings.bOverride_PathTracingEnableDenoiser = true;
403 CaptureComponent2D->PostProcessSettings.PathTracingSamplesPerPixel = SamplesPerPixel;
404 CaptureComponent2D->PostProcessSettings.PathTracingEnableDenoiser = bEnableDenoiser;
405 }
406
407 TickCaptureAndReadback(World, TickType, DeltaSeconds,
408 [this](bool bNonBlocking, const FSensorCaptureContext &CaptureContext)
409 {
410 auto *RenderTarget = GetCaptureRenderTarget();
411 if (RenderTarget == nullptr)
412 return;
413 // Use the per-sensor recycling readback pool (not a fresh per-frame
414 // FRHIGPUTextureReadback): the async path holds each readback until its
415 // off-thread delivery, so per-call staging buffers would accumulate and
416 // exhaust GPU/host memory within seconds under load.
417 ImageUtil::ReadImageDataAsyncFColor(*RenderTarget, [this, CaptureContext](
418 TArrayView<const FColor> Pixels,
419 FIntPoint Size) -> bool
420 {
421 SendDataToClient(*this, Pixels, CaptureContext);
422 return true;
423 }, bNonBlocking, GetReadbackPool());
424 });
425}
426
428 UWorld *World,
429 ELevelTick TickType,
430 float DeltaSeconds,
431 TFunctionRef<void(bool bNonBlocking, const FSensorCaptureContext &Context)> EnqueueReadback)
432{
433 // SYNCHRONOUS MODE -- capture first, then a BLOCKING readback of what we just
434 // rendered. The client's world.tick() is the frame boundary, so the image
435 // stamped with frame k has to BE tick k's render, and no frame may be
436 // dropped. Recording the copy after CaptureScene() puts it behind this tick's
437 // render commands; ImageUtil batches it and FSensorManager's single per-tick
438 // ImageUtil::FlushBatchedReadbacks() waits for the GPU once for the whole
439 // camera batch and delivers it before the tick ends. That is exactly the path
440 // every raster scene-capture camera takes (see
441 // ASceneCaptureCamera::PostPhysTick -> ImageUtil::ReadSensorImageDataAsyncFColor),
442 // and because the batch sync waits for the copy, a frame cannot be dropped at
443 // any samples_per_pixel. The cost is one pipeline drain per tick shared by
444 // every camera -- not one per camera, and not the per-camera flush +
445 // query-wait that used to deadlock (see ImageUtil::ReadImageDataBegin).
446 //
447 // Completeness is the other half of the same contract: the render of tick k
448 // must contain every actor tick k has, with its real materials. The engine
449 // otherwise renders an actor whose materials are new to the ray tracing
450 // pipeline with a black, untagged fallback shader while that pipeline
451 // compiles in the background (see the adapter for the mechanism and the
452 // measured cost), so synchronous mode asks for blocking pipeline creation
453 // before this tick's capture is enqueued; asynchronous mode, which must never
454 // stall the game thread, restores the engine's non-blocking default.
455 const bool bSynchronousMode = GetEpisode().GetSettings().bSynchronousMode;
456 if (CVarRTLensSyncBlockingPipelineCreation.GetValueOnGameThread() != 0)
457 {
459 }
460
461 if (bSynchronousMode &&
462 CVarRTLensSyncBlockingReadback.GetValueOnGameThread() != 0)
463 {
464 ASceneCaptureSensor::PostPhysTick(World, TickType, DeltaSeconds);
466 {
467 const FSensorCaptureContext Context = MakeCaptureContext(*this);
468 // Keep this current even in sync mode, in case the sensor switches to
469 // async mode later.
470 PendingReadbackContext = Context;
472 EnqueueReadback(/*bNonBlocking=*/false, Context);
473 }
474 return;
475 }
476
477 // ASYNCHRONOUS MODE -- NEVER-FREEZE READBACK + CAPTURE ORDER. Nothing paces
478 // the client here, so the game thread (which also drives the RPC server) must
479 // never block on this sensor's heavy path-traced render.
480 //
481 // 1) Enqueue a NON-BLOCKING readback of the render target produced by the
482 // PREVIOUS tick's capture. bNonBlocking=true records the GPU copy and
483 // returns; it does NOT wait for GPU completion on the render thread (the
484 // default path's RHIGetRenderQueryResult(bWait=true) wait DEADLOCKS the
485 // whole server under load -- render thread blocked mid-command, GPU
486 // submission can't advance, game thread freezes behind it at FFrameEndSync;
487 // proven via gdb). Completion is polled off-thread; frames just drop under
488 // load instead of freezing.
489 // 2) Then CaptureScene() (inside ASceneCaptureSensor::PostPhysTick). Because
490 // the readback was enqueued FIRST, the recorded copy rides this capture's
491 // GPU submission -- which is what makes its readback fence actually signal
492 // -- and captures the previous frame's pixels (they precede this tick's
493 // render). Result: one frame of latency, never a stall.
494 // Use the stored context, not this tick's live state: the render target
495 // still holds the PREVIOUS capture.
497 {
498 EnqueueReadback(/*bNonBlocking=*/true, PendingReadbackContext);
499 }
500
501 // Read once: PostPhysTick below makes this same decision internally.
502 const bool bWillCaptureThisFrame = ShouldCaptureThisFrame();
503
504 ASceneCaptureSensor::PostPhysTick(World, TickType, DeltaSeconds);
505
506 if (bWillCaptureThisFrame)
507 {
510 }
511}
ECameraModel
static TAutoConsoleVariable< int32 > CVarRTLensSyncBlockingReadback(TEXT("carla.RTLens.SyncModeBlockingReadback"), 1, TEXT(" 1: capture then read back through the per-tick batched GPU sync (default)."), ECVF_Default)
static constexpr float GPinholeApertureFstop
static TAutoConsoleVariable< float > CVarRTLensMaxAutoExposureEV(TEXT("carla.RTLens.MaxAutoExposureEV"), 12.0f, TEXT("Upper limit (EV100) of the rt_lens auto exposure range; the lower limit is the camera profile's."), ECVF_Default)
static TAutoConsoleVariable< int32 > CVarRTLensSyncBlockingPipelineCreation(TEXT("carla.RTLens.SyncModeBlockingPipelineCreation"), 1, TEXT(" 1: set r.RayTracing.NonBlockingPipelineCreation 0 while synchronous, restore it when asynchronous (default)."), ECVF_Default)
ASceneCaptureCamera_RayTracedLens(const FObjectInitializer &ObjectInitializer)
void UpdatePostProcessConfig(FPostProcessConfig &InOutPostProcessConfig) override
Forces path-tracing view mode for this sensor's capture.
void EndPlay(const EEndPlayReason::Type EndPlayReason) override
Restores r.RayTracing.NonBlockingPipelineCreation if this sensor left it at 0 (synchronous mode,...
void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaSeconds) override
FLensModelDescriptor LensModel
Resolved lens-model parameters, rebuilt in Set() from the camera_model / distortion_coeffs / lut / fx...
FSensorCaptureContext PendingReadbackContext
Capture metadata for what is currently in the render target (see TickCaptureAndReadback).
void Set(const FActorDescription &ActorDescription) override
void TickCaptureAndReadback(UWorld *World, ELevelTick TickType, float DeltaSeconds, TFunctionRef< void(bool bNonBlocking, const FSensorCaptureContext &Context)> EnqueueReadback)
Runs this tick's capture and this tick's readback in the order the world's synchronization mode requi...
void SetRayTracedLensExposure()
Pins the capture's auto exposure to the daylight histogram window (EV100 10-12, same as the viewport)...
bool ShouldCaptureThisFrame()
Aggregate gate: main stream or any GBuffer stream has listeners, or CVarCarlaCameraForceAllGBuffers f...
UTextureRenderTarget2D * GetCaptureRenderTarget()
TObjectPtr< USceneCaptureComponent2D_CARLA > CaptureComponent2D
Scene capture component.
void SetUseRayTracing(bool Enable)
void SetAperture(float Aperture)
void SetFocalDistance(float Distance)
uint32 GetImageHeight() const
uint32 GetImageWidth() const
FRHIGPUReadbackPoolPtr GetReadbackPool() const
Per-sensor pool of recyclable RHI readback objects.
virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override
static void SendDataToClient(SensorType &&Sensor, TArrayView< ElementType > SensorData, const FSensorCaptureContext &CaptureContext)
static FSensorCaptureContext MakeCaptureContext(const ASensor &Sensor)
Call on the game thread right after CaptureScene().
FEngineShowFlags EngineShowFlags
static int32 RetrieveActorAttributeToInt(const FString &Id, const TMap< FString, FActorAttribute > &Attributes, int32 Default)
static FActorDefinition MakeRayTracedLensCameraDefinition(const FString &Id, bool bEnableModifyingPostProcessEffects=false)
static FString RetrieveActorAttributeToString(const FString &Id, const TMap< FString, FActorAttribute > &Attributes, const FString &Default)
static float RetrieveActorAttributeToFloat(const FString &Id, const TMap< FString, FActorAttribute > &Attributes, float Default)
static bool RetrieveActorAttributeToBool(const FString &Id, const TMap< FString, FActorAttribute > &Attributes, bool Default)
const FEpisodeSettings & GetSettings() const
float SolveRadius(float Theta, TArrayView< const float > Coefficients, int32 Iterations)
float ComputeCameraPolynomial(float Theta, TArrayView< const float > Coefficients)
bool ReadImageDataAsyncFColor(UTextureRenderTarget2D &RenderTarget, ReadImageDataAsyncCallbackFColor &&Callback, bool bNonBlocking, FRHIGPUReadbackPoolPtr Pool)
void SetBlockingRayTracingPipelineCreation(bool bBlocking)
void ApplyLensModel(FPostProcessSettings &PostProcessSettings, const FLensModelDescriptor &Descriptor)
static float RadialAtTheta(ECameraModel Model, float Theta, TArrayView< const float > Coeffs)
static ECameraModel ParseCameraModelName(const FString &Name)
static TArray< float > ParseFloatCSV(const FString &CSV)
A definition of a Carla Actor with all the variation and attributes.
A description of a Carla Actor with all its variation.
TMap< FString, FActorAttribute > Variations
User selected variations of the actor.
TArray< float > LUT
TArray< float > Coeffs
Sensor frame metadata snapshotted at capture time, carried by value through async delivery instead of...