CARLA
Loading...
Searching...
No Matches
SceneCaptureSensor_WideAngleLens.h
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
7#pragma once
8
16
17#include <util/ue-header-guard-begin.h>
18#include "Misc/App.h"
19#if __has_include("GBufferView.h")
20#define CARLA_HAS_GBUFFER_API
21#include "GBufferView.h"
22#endif
23#include <util/ue-header-guard-end.h>
24
25#include "SceneCaptureSensor_WideAngleLens.generated.h"
26
27
28
29UCLASS()
31{
32 GENERATED_BODY()
33
34 friend class ACarlaGameModeBase;
35 friend class FPixelReader;
36
37public:
38
39 ASceneCaptureSensor_WideAngleLens(const FObjectInitializer &ObjectInitializer);
40
41 void Set(const FActorDescription &ActorDescription) override;
42
43 UFUNCTION(BlueprintCallable)
44 void SetImageSize(int32 Width, int32 Height);
45
46 void SetImageSize(uint32 Width, uint32 Height);
47
48 /// Side length in pixels of the six cube-face render targets. 0 (default)
49 /// uses max(ImageWidth, ImageHeight). Smaller faces cost less GPU memory
50 /// (each face carries a full scene view); a 120 deg lens at 1920 px is
51 /// sampled at ~16 px/deg in the centre, which a 1280 px face still meets.
52 UFUNCTION(BlueprintCallable)
53 void SetFaceSize(int32 Side)
54 {
55 FaceSize = FMath::Max(Side, 0);
56 }
57
58 UFUNCTION(BlueprintCallable, BlueprintPure)
59 int32 GetFaceSize() const
60 {
61 return FaceSize;
62 }
63
64 uint32 GetImageWidth() const
65 {
66 return ImageWidth;
67 }
68
69 uint32 GetImageHeight() const
70 {
71 return ImageHeight;
72 }
73
74 UFUNCTION(BlueprintCallable, BlueprintPure)
75 FIntPoint GetImageSize() const
76 {
77 return FIntPoint(GetImageWidth(), GetImageHeight());
78 }
79
80 UFUNCTION(BlueprintCallable)
81 void EnablePostProcessingEffects(bool Enable = true)
82 {
83 bEnablePostProcessingEffects = Enable;
84 }
85
86 UFUNCTION(BlueprintCallable, BlueprintPure)
87 ECameraModel GetCameraModel() const;
88
89 UFUNCTION(BlueprintCallable)
90 void SetCameraModel(ECameraModel NewCameraModel);
91
92 UFUNCTION(BlueprintCallable, BlueprintPure)
93 float GetFOVAngle() const;
94
95 UFUNCTION(BlueprintCallable, BlueprintPure)
96 float GetFOVAngleY() const;
97
98 UFUNCTION(BlueprintCallable, BlueprintPure)
99 float GetFOVAngleX() const;
100
101 UFUNCTION(BlueprintCallable)
102 void SetFOVAngle(float NewFOV);
103
104 UFUNCTION(BlueprintCallable, BlueprintPure)
105 float GetFocalLength() const;
106
107 UFUNCTION(BlueprintCallable)
108 void SetFocalLength(float NewFocalLength);
109
110 void SetCameraCoefficients(TArrayView<const float> Coefficients);
111
112 UFUNCTION(BlueprintCallable)
113 void SetCameraCoefficients(const TArray<float>& Coefficients);
114
115 UFUNCTION(BlueprintCallable, BlueprintPure)
116 const TArray<float>& GetCameraCoefficients() const;
117
118 /// LUT1D camera model: R(Theta) samples, uniformly spaced over
119 /// [0, ThetaMaxRadians], monotonically non-decreasing, in the normalized
120 /// units of the lens intrinsics (pixel = c + f * R, see SetLensIntrinsics).
121 UFUNCTION(BlueprintCallable)
122 void SetLensLUT(const TArray<float>& Samples, float ThetaMaxRadians);
123
124 UFUNCTION(BlueprintCallable, BlueprintPure)
125 const TArray<float>& GetLensLUT() const
126 {
127 return LensLUT;
128 }
129
130 UFUNCTION(BlueprintCallable, BlueprintPure)
131 float GetLensThetaMax() const
132 {
133 return LensThetaMax;
134 }
135
136 /// Explicit intrinsics in normalized viewport units, the same convention as
137 /// sensor.camera.rt_lens: x_px = (Cx + Fx * R * cos(phi)) * Width,
138 /// y_px = (Cy + Fy * R * sin(phi)) * Height. Fx <= 0 disables the override
139 /// and the projection falls back to the fov / focal_length attributes with
140 /// the principal point at the image centre.
141 UFUNCTION(BlueprintCallable)
142 void SetLensIntrinsics(float Fx, float Fy, float Cx, float Cy);
143
144 UFUNCTION(BlueprintCallable, BlueprintPure)
145 bool HasExplicitLensIntrinsics() const
146 {
147 return bExplicitIntrinsics;
148 }
149
150 UFUNCTION(BlueprintCallable, BlueprintPure)
151 UTextureRenderTarget2D* GetCaptureRenderTarget();
152
153 UFUNCTION(BlueprintCallable, BlueprintPure)
154 float GetTargetGamma() const;
155
156 UFUNCTION(BlueprintCallable)
157 void SetTargetGamma(float Gamma);
158
159 UFUNCTION(BlueprintCallable)
160 void SetRenderPerspective(bool bEnable);
161
162 UFUNCTION(BlueprintCallable, BlueprintPure)
163 bool GetRenderPerspective() const;
164
165 UFUNCTION(BlueprintCallable)
166 void SetRenderEquirectangular(bool bEnable);
167
168 UFUNCTION(BlueprintCallable, BlueprintPure)
169 bool GetRenderEquirectangular() const;
170
171 UFUNCTION(BlueprintCallable)
172 void SetFOVMaskEnable(bool bEnable);
173
174 UFUNCTION(BlueprintCallable, BlueprintPure)
175 bool GetFOVMaskEnable() const;
176
177 UFUNCTION(BlueprintCallable)
178 void SetFOVFadeSize(float NewFOVFadeSize);
179
180 UFUNCTION(BlueprintCallable, BlueprintPure)
181 float GetFOVFadeSize() const;
182
183 UFUNCTION(BlueprintCallable)
184 void SetRenderEquirectangularLongitudeOffset(float Shift);
185
186 UFUNCTION(BlueprintCallable, BlueprintPure)
187 float GetRenderEquirectangularLongitudeOffset() const;
188
189 void SetCubemapSampler(FRHISamplerState* NewCubemapSampler)
190 {
191 CubemapSampler = NewCubemapSampler;
192 }
193
194 const FRHISamplerState* GetCubemapSampler() const
195 {
196 return CubemapSampler;
197 }
198
199 /// Recycling pool of GPU readback staging buffers for the projected image
200 /// (created in BeginPlay, dropped in EndPlay), as ASceneCaptureSensor owns
201 /// one for the pinhole cameras; without it every frame allocated a fresh
202 /// staging buffer.
203 FRHIGPUReadbackPoolPtr GetReadbackPool() const { return ReadbackPool; }
204
205 UFUNCTION(BlueprintCallable)
206 void SetUseRayTracing(bool Enable);
207
208 UFUNCTION(BlueprintCallable, BlueprintPure)
209 bool GetUseRayTracing() const
210 {
211 return bUseRayTracing;
212 }
213
214 /// Show-only render mode (see FCarlaShowOnlyFilter); applied to all six
215 /// face captures.
216 UFUNCTION(BlueprintCallable)
217 void SetShowOnlyTags(const FString &CommaSeparatedLabels)
218 {
219 ShowOnlyFilter.SetShowOnlyTags(CommaSeparatedLabels);
220 }
221
222 UFUNCTION(BlueprintCallable)
223 void SetShadowCatcherTags(const FString &CommaSeparatedLabels)
224 {
225 ShowOnlyFilter.SetShadowCatcherTags(CommaSeparatedLabels);
226 }
227
228 UFUNCTION(BlueprintCallable)
229 void SetShowOnlyActorIds(const FString &CommaSeparatedIds)
230 {
231 ShowOnlyFilter.SetShowOnlyActorIds(CommaSeparatedIds);
232 }
233
234 UFUNCTION(BlueprintCallable, BlueprintPure)
235 bool IsShowOnlyEnabled() const
236 {
237 return ShowOnlyFilter.IsEnabled();
238 }
239
241 {
242 return ShowOnlyFilter;
243 }
244
245 /// Immediate enqueues render commands of the scene at the current time.
246 void EnqueueRenderSceneImmediate();
247
248 /// Capture the six faces, project them into the lens, and deliver the
249 /// image through ImageUtil's per-tick batched readback -- the same path as
250 /// every raster camera (ASceneCaptureCamera::PostPhysTick). The previous
251 /// FPixelReader::SendPixelsInRenderThread path locked the GPU readback on a
252 /// worker thread, which asserts IsInRenderingThread() on UE 5.8.
253 template <typename TSensor>
254 static void CaptureAndSendToClient(TSensor& Sensor)
255 {
256 // This path does not go through ASceneCaptureSensor::ShouldCaptureThisFrame(),
257 // so it needs its own check for a process without an RHI (-nullrhi).
258 if (!Sensor.AreClientsListening() || !FApp::CanEverRender())
259 {
260 return;
261 }
262 Sensor.EnqueueRenderSceneImmediate();
263 const auto CaptureContext = ASensor::MakeCaptureContext(Sensor);
265 *Sensor.GetCaptureRenderTarget(),
266 [&Sensor, CaptureContext](TArrayView<const FColor> Pixels, FIntPoint) -> bool
267 {
268 if (!IsValid(&Sensor))
269 return false;
270 ASensor::SendDataToClient(Sensor, Pixels, CaptureContext);
271 return true;
272 },
273 /*bNonBlocking=*/false,
274 Sensor.GetReadbackPool()); // recycle staging buffers, as the pinhole cameras do
275 }
276
277 /// Blocks until the render thread has finished all its tasks.
279 {
281 FlushRenderingCommands();
282 }
283
284 TArrayView<USceneCaptureComponent2D_CARLA*> GetCaptureComponents2D();
285
286protected:
287
288 UFUNCTION(BlueprintCallable, BlueprintPure)
289 float VerticalToHorizontal(float Value) const;
290
291 UFUNCTION(BlueprintCallable, BlueprintPure)
292 uint8 FindFaceIndex(FVector2D UV) const;
293
294 UFUNCTION(BlueprintCallable, BlueprintPure)
295 uint8 ComputeCubemapRenderMask() const;
296
297 void CaptureSceneExtended();
298
299 virtual void BeginPlay() override;
300
301 virtual void PrePhysTick(float DeltaSeconds) override;
302 virtual void PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaTime) override;
303
304 virtual void SetUpSceneCaptureComponents(TArrayView<USceneCaptureComponent2D_CARLA*> SceneCaptures) {}
305
306 /// Colour written to pixels the lens maps no ray to (LUT1D beyond its last
307 /// sample). Black for colour and label sensors; the depth sensor overrides
308 /// it with white, which decodes to the far plane.
309 virtual FLinearColor GetInvalidPixelColor() const
310 {
311 return FLinearColor(0.0F, 0.0F, 0.0F, 1.0F);
312 }
313
314 virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
315
316 UPROPERTY(EditAnywhere)
317 TArray<USceneCaptureComponent2D_CARLA*> FaceCaptures;
318
319 UPROPERTY(EditAnywhere)
320 TArray<UTextureRenderTarget2D*> FaceRenderTargets;
321
323
324 UPROPERTY(EditAnywhere)
325 UTextureRenderTarget2D* CaptureRenderTarget;
326
327 UPROPERTY(EditAnywhere)
328 float TargetGamma;
329
330 UPROPERTY(EditAnywhere)
331 uint32 ImageWidth;
332
333 UPROPERTY(EditAnywhere)
334 uint32 ImageHeight;
335
336 UPROPERTY(EditAnywhere)
337 ECameraModel CameraModel;
338
339 UPROPERTY(EditAnywhere)
340 TArray<float> KannalaBrandtCameraCoefficients;
341
342 UPROPERTY(EditAnywhere)
343 TArray<float> LensLUT;
344
345 UPROPERTY(EditAnywhere)
346 float LensThetaMax;
347
348 // Normalized (fx, fy, cx, cy), see SetLensIntrinsics.
349 UPROPERTY(EditAnywhere)
350 FVector4f LensIntrinsics;
351
352 UPROPERTY(EditAnywhere)
353 float YFOVAngle;
354
355 UPROPERTY(EditAnywhere)
356 float XFOVAngle;
357
358 // Cube-face render target side, 0 = max(ImageWidth, ImageHeight).
359 UPROPERTY(EditAnywhere)
360 int32 FaceSize = 0;
361
362 /// Captures rendered as camera cuts since BeginPlay (carla.Camera.SpawnCameraCuts).
363 int32 NumCaptures = 0;
364
365 UPROPERTY(EditAnywhere)
366 float YFocalLength;
367
368 UPROPERTY(EditAnywhere)
369 float LongitudeOffset;
370
371 UPROPERTY(EditAnywhere)
372 float FOVFadeSize;
373
374 uint8 CubemapRenderMask;
375
376 FRHISamplerState* CubemapSampler;
377
378 /// Show-only actor filter, applied to every face capture right before the
379 /// faces are captured (see FCarlaShowOnlyFilter).
380 FCarlaShowOnlyFilter ShowOnlyFilter;
381
382 bool bUseRayTracing : 1;
383 bool bEnablePostProcessingEffects : 1;
384 bool bEnable16BitFormat : 1;
385 bool bRenderPerspective : 1;
386 bool bRenderEquirectangular : 1;
387 bool bFOVMaskEnable : 1;
388 bool bExplicitIntrinsics : 1;
389};
ECameraModel
TSharedPtr< FRHIGPUReadbackPool, ESPMode::ThreadSafe > FRHIGPUReadbackPoolPtr
Base class for the CARLA Game Mode.
virtual void SetUpSceneCaptureComponents(TArrayView< USceneCaptureComponent2D_CARLA * > SceneCaptures)
void SetCubemapSampler(FRHISamplerState *NewCubemapSampler)
static void CaptureAndSendToClient(TSensor &Sensor)
Capture the six faces, project them into the lens, and deliver the image through ImageUtil's per-tick...
void WaitForRenderThreadToFinish()
Blocks until the render thread has finished all its tasks.
virtual FLinearColor GetInvalidPixelColor() const
Colour written to pixels the lens maps no ray to (LUT1D beyond its last sample).
FRHIGPUReadbackPoolPtr GetReadbackPool() const
Recycling pool of GPU readback staging buffers for the projected image (created in BeginPlay,...
const FCarlaShowOnlyFilter & GetShowOnlyFilter() const
const FRHISamplerState * GetCubemapSampler() const
static FSensorCaptureContext MakeCaptureContext(const ASensor &Sensor)
Call on the game thread right after CaptureScene().
Utils for reading pixels from UTextureRenderTarget2D.
Definition PixelReader.h:42
bool ReadImageDataAsyncFColor(UTextureRenderTarget2D &RenderTarget, ReadImageDataAsyncCallbackFColor &&Callback, bool bNonBlocking, FRHIGPUReadbackPoolPtr Pool)
A description of a Carla Actor with all its variation.
Show-only ("render layer") filter shared by every scene-capture camera.