CARLA
Loading...
Searching...
No Matches
SceneCaptureCamera_RayTracedLensInstance.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 <util/ue-header-guard-begin.h>
16#include "Components/SceneCaptureComponent2D.h"
17#include "Engine/TextureRenderTarget2D.h"
18#include <util/ue-header-guard-end.h>
19
20// FPostProcessSettings::PathTracingLensAOV values, mirrored from
21// Engine/Shaders/Private/PathTracing/PathTracingCore.ush.
22static constexpr int32 GPathTracingLensAOVTag = 2;
23
25{
26 // Same attribute surface as sensor.camera.rt_lens (camera_model,
27 // distortion_coeffs, fx/fy/cx/cy, theta_max_deg, fov, show_only_*, ...) so a
28 // colour/distance/instance rig can be configured from one dictionary.
29 // Post-process attributes are deliberately absent: this capture never goes
30 // through the post-process chain at all.
31 constexpr bool bEnableModifyingPostProcessEffects = false;
32 FActorDefinition Definition =
34 TEXT("rt_lens_instance"),
35 bEnableModifyingPostProcessEffects);
36
37 // A tag is an exact integer read off the primary hit; extra samples would
38 // only cost time, and there is nothing for a denoiser to do to it.
39 for (auto &Variation : Definition.Variations)
40 {
41 if (Variation.Id == TEXT("samples_per_pixel"))
42 {
43 Variation.RecommendedValues = {TEXT("1")};
44 }
45 else if (Variation.Id == TEXT("enable_denoiser"))
46 {
47 Variation.RecommendedValues = {TEXT("false")};
48 }
49 }
50 return Definition;
51}
52
54 const FObjectInitializer &ObjectInitializer)
55 : Super(ObjectInitializer)
56{
57 // Nothing on this sensor's route touches the post-process chain: the capture
58 // source resolves the path tracer's tag AOV straight into the render target.
59 // Disabling post-processing also forces the render target to linear gamma,
60 // which is what keeps the label/id bytes exact.
63}
64
66{
67 if (CaptureComponent2D == nullptr)
68 {
69 return;
70 }
71 auto &PostProcessSettings = CaptureComponent2D->PostProcessSettings;
72
73 // Per-view AOV selection (Engine/Classes/Engine/Scene.h). Per-view rather
74 // than a cvar so a rig can run colour, distance and instance cameras at once.
75 PostProcessSettings.bOverride_PathTracingLensAOV = true;
76 PostProcessSettings.PathTracingLensAOV = GPathTracingLensAOVTag;
77
78 // One sample is all the AOV needs, and the denoiser must never touch it.
79 // These are the inherited knobs (reasserted by the base's PostPhysTick), so
80 // they have to be written through the base's members, not just the settings.
82 bEnableDenoiser = false;
83 PostProcessSettings.bOverride_PathTracingSamplesPerPixel = true;
84 PostProcessSettings.bOverride_PathTracingEnableDenoiser = true;
85 PostProcessSettings.PathTracingSamplesPerPixel = SamplesPerPixel;
86 PostProcessSettings.PathTracingEnableDenoiser = bEnableDenoiser;
87
88 // Depth of field would scatter the primary ray across the aperture and blend
89 // two actors' ids into one pixel. DepthOfFieldFocalDistance == 0 is what the
90 // path tracer tests for (PathTracing.cpp, PathTracingData.CameraLensRadius).
91 SetFocalDistance(0.0f);
92}
93
95{
96 // Lens model, resolution, fov, show_only_* -- everything is parsed by the
97 // colour sensor's Set(); this class only changes what the capture outputs.
98 Super::Set(Description);
100}
101
103{
104 Super::BeginPlay();
105
106 // ASceneCaptureSensor::BeginPlay ends by forcing SCS_FinalToneCurveHDR; take
107 // the capture source back afterwards. The render target it created is already
108 // what this sensor wants (PF_B8G8R8A8 with linear gamma, because
109 // post-processing is disabled), so unlike the distance sensor there is
110 // nothing to re-initialise.
111 if (CaptureComponent2D != nullptr)
112 {
113 CaptureComponent2D->CaptureSource = ESceneCaptureSource::SCS_PathTracingLensTag;
114 }
116}
117
119 UWorld *World,
120 ELevelTick TickType,
121 float DeltaSeconds)
122{
123 TRACE_CPUPROFILER_EVENT_SCOPE(ASceneCaptureCamera_RayTracedLensInstance::PostPhysTick);
124
125 if (AreClientsListening() && CaptureComponent2D != nullptr)
126 {
127 // Same reason as ASceneCaptureCamera_RayTracedLens::PostPhysTick: code
128 // paths such as ApplyPostProcessVolumeToSensor replace PostProcessSettings
129 // wholesale and would silently turn this back into an undistorted pinhole
130 // colour camera.
133 CaptureComponent2D->CaptureSource = ESceneCaptureSource::SCS_PathTracingLensTag;
134 }
135
136 // Deliberately skips ASceneCaptureCamera_RayTracedLens::PostPhysTick: its body
137 // is the colour readback, which would serialize this frame a second time as
138 // the colour sensor's type. The lens reassertion above reproduces what else it
139 // does, and the capture/readback ORDER -- which is what keeps a colour, a
140 // distance and an instance camera on the same frame -- comes from the base
141 // class's TickCaptureAndReadback so every path-traced lens sensor shares one
142 // policy: blocking readback after the capture in synchronous mode, and
143 // readback-then-capture without ever waiting on the render thread otherwise.
144 TickCaptureAndReadback(World, TickType, DeltaSeconds,
145 [this](bool bNonBlocking, const FSensorCaptureContext &CaptureContext)
146 {
147 UTextureRenderTarget2D *RenderTarget = GetCaptureRenderTarget();
148 if (RenderTarget == nullptr)
149 {
150 return;
151 }
152 ImageUtil::ReadImageDataAsyncFColor(*RenderTarget, [this, CaptureContext](
153 TArrayView<const FColor> Pixels,
154 FIntPoint Size) -> bool
155 {
156 SendDataToClient(*this, Pixels, CaptureContext);
157 return true;
158 }, bNonBlocking, GetReadbackPool());
159 });
160}
static constexpr int32 GPathTracingLensAOVTag
void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaSeconds) override
void ApplyInstanceAOVConfig()
Re-asserts everything that makes this capture a tag AOV rather than a colour render.
ASceneCaptureCamera_RayTracedLensInstance(const FObjectInitializer &ObjectInitializer)
void Set(const FActorDescription &ActorDescription) override
FLensModelDescriptor LensModel
Resolved lens-model parameters, rebuilt in Set() from the camera_model / distortion_coeffs / lut / fx...
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...
UTextureRenderTarget2D * GetCaptureRenderTarget()
TObjectPtr< USceneCaptureComponent2D_CARLA > CaptureComponent2D
Scene capture component.
void EnablePostProcessingEffects(bool Enable=true)
void SetFocalDistance(float Distance)
FRHIGPUReadbackPoolPtr GetReadbackPool() const
Per-sensor pool of recyclable RHI readback objects.
static void SendDataToClient(SensorType &&Sensor, TArrayView< ElementType > SensorData, const FSensorCaptureContext &CaptureContext)
static FActorDefinition MakeRayTracedLensCameraDefinition(const FString &Id, bool bEnableModifyingPostProcessEffects=false)
bool ReadImageDataAsyncFColor(UTextureRenderTarget2D &RenderTarget, ReadImageDataAsyncCallbackFColor &&Callback, bool bNonBlocking, FRHIGPUReadbackPoolPtr Pool)
void ApplyLensModel(FPostProcessSettings &PostProcessSettings, const FLensModelDescriptor &Descriptor)
A definition of a Carla Actor with all the variation and attributes.
TArray< FActorVariation > Variations
Variations represent variables the user can modify to generate variations of the actor.
A description of a Carla Actor with all its variation.
Sensor frame metadata snapshotted at capture time, carried by value through async delivery instead of...