Skip to main content

Viewport.ixx File

Defines the Viewport class, which represents a rectangular area for rendering within a RenderTarget. More...

Included Headers

Namespaces Index

namespacehelios
namespacerendering

Graphics rendering infrastructure. More...

Classes Index

structViewportKey

A passkey used to establish a parent-child relationship between a RenderTarget and a Viewport. More...

classViewport

Represents a rectangular area within a RenderTarget where a scene is rendered. More...

Macro Definitions Index

#defineHELIOS_LOG_SCOPE   "helios::rendering::Viewport"

Description

Defines the Viewport class, which represents a rectangular area for rendering within a RenderTarget.

Macro Definitions

HELIOS_LOG_SCOPE

#define HELIOS_LOG_SCOPE   "helios::rendering::Viewport"

Definition at line 26 of file Viewport.ixx.

26#define HELIOS_LOG_SCOPE "helios::rendering::Viewport"

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file Viewport.ixx
3 *
4 * @brief Defines the Viewport class, which represents a rectangular area for rendering within a RenderTarget.
5 */
6module;
7
8#include <cassert>
9#include <format>
10#include <memory>
11
12
13export module helios.rendering.Viewport;
14
15import helios.rendering.ViewportSnapshot;
16
17import helios.rendering.ClearFlags;
18import helios.core.types;
19import helios.engine.core.data.ViewportId;
20import helios.math.types;
21import helios.scene.CameraSceneNode;
22import :RenderTargetFwd;
23import helios.util.log.LogManager;
24import helios.util.log.Logger;
25
26#define HELIOS_LOG_SCOPE "helios::rendering::Viewport"
27export namespace helios::rendering {
28
29
30
31
32 /**
33 * @brief A passkey used to establish a parent-child relationship between a RenderTarget and a Viewport.
34 *
35 * This struct uses the passkey idiom to restrict the calling of `Viewport::setRenderTarget` to
36 * friend classes (specifically `helios::rendering::RenderTarget`), ensuring that the ownership
37 * hierarchy is managed correctly.
38 *
39 * @see `Viewport::setRenderTarget`
40 * @see https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2893r3.html#passkey-idiom
41 */
42 struct ViewportKey {
43 private:
45 ViewportKey() = default;
46 };
47
48 /**
49 * @brief Represents a rectangular area within a RenderTarget where a scene is rendered.
50 *
51 * A Viewport defines the 2D rectangle into which a 3D scene is projected. Its dimensions are specified
52 * in normalized coordinates relative to its parent `RenderTarget`. It is associated with a `CameraSceneNode`,
53 * which provides the view and projection matrices. The viewport automatically updates the CameraSceneNode
54 * associated camera's aspect ratio when its parent `RenderTarget` is resized.
55 *
56 * Since a Viewport only stores normalized values for its location and dimensions relative to the owning RenderTarget,
57 * rendering APIs should query the size of the RenderTarget when a viewport is about to be
58 * rendered, allowing them to compute the final screen coordinates and dimensions correctly.
59 *
60 * @see helios::rendering::RenderTarget
61 * @see helios::scene::CameraSceneNode
62 * @see https://registry.khronos.org/OpenGL-Refpages/gl4/html/glViewport.xhtml
63 */
64 class Viewport {
66
67 private:
68 /**
69 * @brief Pointer to the parent RenderTarget.
70 */
71 const helios::rendering::RenderTarget* renderTarget_ = nullptr;
72
73 /**
74 * @brief Bitmask of buffers to clear.
75 *
76 * Defaults to ClearFlags::Color.
77 */
78 int clearFlags_ = std::to_underlying(ClearFlags::Color);
79
80 /**
81 * @brief Color used when clearing the color buffer. Defaults to "black", i.e. no color at all.
82 */
83 helios::math::vec4f clearColor_ = helios::math::vec4f(0.0f, 0.0f, 0.0f, 1.0f);
84
85 /**
86 * @brief The x-offset of the viewport, normalized to [0, 1].
87 */
88 float x_ = 0.0f;
89 /**
90 * @brief The y-offset of the viewport, normalized to [0, 1].
91 */
92 float y_ = 0.0f;
93
94 /**
95 * @brief The width of the viewport, normalized to [0, 1].
96 */
97 float width_ = 1.0f;
98 /**
99 * @brief The height of the viewport, normalized to [0, 1].
100 */
101 float height_ = 1.0f;
102
103 /**
104 * @brief Size of the parent RenderTarget in pixels.
105 */
106 helios::math::vec2ui renderTargetSize_{};
107
108 /**
109 * @brief The cameraSceneNode associated as the main camera with this viewport.
110 */
111 helios::scene::CameraSceneNode* cameraSceneNode_ = nullptr;
112
113 /**
114 * @brief Flag indicating if cached dimensions are dirty.
115 */
116 mutable bool needsUpdate_ = true;
117
118 /**
119 * @brief Cached dimensions [x, y, width, height].
120 */
121 mutable helios::math::vec4f bounds_;
122
123 /**
124 * @brief The z-index for this viewport.
125 *
126 * The z-index represents the order the Viewport gets rendered.
127 * A higher z-index means that the viewport gets rendered after viewports with a lower z-index
128 * are rendered.
129 */
130 int zIndex_ = 0;
131
132 /**
133 * @brief Unique identifier for this viewport.
134 */
136
137 /**
138 * @brief Cached absolute bounds [x, y, width, height] in pixels.
139 */
140 mutable helios::math::vec4f absoluteBounds_{};
141
142 /**
143 * @brief Updates the cached dimensions vector if it is dirty.
144 */
145 void updateCache() const noexcept {
146
147 if (!needsUpdate_) {
148 return;
149 }
150
151 bounds_[0] = x_;
152 bounds_[1] = y_;
153 bounds_[2] = width_;
154 bounds_[3] = height_;
155
156 absoluteBounds_ = {
157 bounds_[0] * renderTargetSize_[0],
158 bounds_[1] * renderTargetSize_[1],
159 bounds_[2] * renderTargetSize_[0],
160 bounds_[3] * renderTargetSize_[1]
161 };
162
163 snapshot_ = {viewportId_, bounds_, absoluteBounds_};
164
165 needsUpdate_ = false;
166 }
167
168 /**
169 * @brief Cached viewport snapshot for efficient access.
170 */
171 mutable ViewportSnapshot snapshot_{};
172
173 /**
174 * @brief Updates this Viewport's CameraSceneNode and its associated Camera based on the dimension of the RenderTarget.
175 *
176 * @param width The new width of the RenderTarget in pixels.
177 * @param height The new height of the RenderTarget in pixels.
178 *
179 * This method should be called internally whenever the dimensions of the owning
180 * RenderTarget change.
181 */
182 void updateCamera(unsigned int renderTargetWidth, unsigned int renderTargetHeight) noexcept {
183 assert(renderTarget_ && "No RenderTarget available for updateCamera()");
184
185 if (!cameraSceneNode_) {
186 logger_.warn("updateCamera: Viewport was not configured with a CameraSceneNode, nothing to do here.");
187 return;
188 }
189
190 cameraSceneNode_->camera().onResize(
191 static_cast<float>(renderTargetWidth) * width_,
192 static_cast<float>(renderTargetHeight) * height_
193 );
194 }
195
196 public:
197 /**
198 * @brief Constructs a Viewport with normalized bounds set to (0.0f, 0.0f, 1.0f, 1.0f) and z-index 0
199 */
200 Viewport() noexcept : x_(0.0f), y_(0.0f), width_(1.0f), height_(1.0f), zIndex_(0) {
201 needsUpdate_ = true;
202 }
203
204 /**
205 * @brief Constructs a Viewport with specified normalized dimensions.
206 *
207 * @param x The normalized horizontal offset [0, 1].
208 * @param y The normalized vertical offset [0, 1].
209 * @param width The normalized width [0, 1].
210 * @param height The normalized height [0, 1].
211 * @param zIndex The z-index that determines the rendering order.
212 */
213 explicit Viewport(
214 float x, float y, float width, float height,
216 const int zIndex = 0
217 ) noexcept
218 :
219 viewportId_(viewportId),
220 zIndex_(zIndex) {
221 setBounds(x, y, width, height);
222 }
223
224 /**
225 * @brief Gets the parent RenderTarget.
226 *
227 * If the returned value is a nullptr, this Viewport is not owned by any RenderTarget.
228 *
229 * @return A const pointer to the parent RenderTarget, or `nullptr` if not set.
230 */
231 [[nodiscard]] const helios::rendering::RenderTarget* renderTarget() const noexcept {
232 return renderTarget_;
233 }
234
235 /**
236 * @brief Returns the unique identifier for this viewport.
237 *
238 * @return The ViewportId assigned to this viewport.
239 */
240 [[nodiscard]] helios::engine::core::data::ViewportId viewportId() const noexcept {
241 return viewportId_;
242 }
243
244 /**
245 * @brief Assigns a camera scene node to this viewport.
246 *
247 * The viewport uses the associated camera's projection matrix and the node's
248 * computed view matrix for rendering. The camera's aspect ratio is automatically
249 * updated when the parent RenderTarget is resized.
250 *
251 * @param cameraSceneNode A non-owning raw pointer to the `CameraSceneNode`.
252 * Must remain valid for the lifetime of this viewport.
253 *
254 * @return A reference to this viewport to allow fluent chaining.
255 */
257 cameraSceneNode_ = cameraSceneNode;
258 return *this;
259 }
260
261 /**
262 * @brief Gets the camera scene node associated with this viewport.
263 *
264 * @return A const pointer to the associated `CameraSceneNode`, or `nullptr` if none is set.
265 */
266 [[nodiscard]] const helios::scene::CameraSceneNode* cameraSceneNode() const noexcept {
267 return cameraSceneNode_;
268 }
269
270 /**
271 * @brief Sets the parent RenderTarget for this viewport.
272 *
273 * This function can only be called by classes that can construct a `ViewportKey`,
274 * effectively restricting its use to the `RenderTarget` class.
275 *
276 * @param renderTarget A pointer to the parent RenderTarget.
277 * @param key A `ViewportKey` instance, required for authorization.
278 *
279 * @return A reference to this viewport to allow fluent chaining.
280 *
281 * @see updateCamera()
282 *
283 * @todo The Viewport should observe the RenderTarget for state changes (e.g., resize).
284 */
286 renderTarget_ = renderTarget;
287 return *this;
288 }
289
290 /**
291 * @brief Gets the cached dimensions of the viewport.
292 *
293 * @return A const reference to a vec4f containing [x, y, width, height].
294 */
295 [[nodiscard]] const helios::math::vec4f& bounds() const noexcept {
296 updateCache();
297 return bounds_;
298 }
299
300 /**
301 * @brief Gets the cached absolute bounds of the viewport in pixels.
302 *
303 * @return A const reference to a vec4f containing [x, y, width, height] in pixels.
304 */
305 [[nodiscard]] const helios::math::vec4f& absoluteBounds() const noexcept {
306 updateCache();
307 return absoluteBounds_;
308 }
309
310 /**
311 * @brief Returns an immutable snapshot of this viewport's current state.
312 *
313 * The snapshot contains the viewport ID and both normalized and absolute bounds.
314 * Useful for passing viewport state to rendering systems without exposing the
315 * mutable Viewport object.
316 *
317 * @return A ViewportSnapshot containing the current viewport state.
318 */
319 [[nodiscard]] ViewportSnapshot snapshot() const noexcept {
320 updateCache();
321 return snapshot_;
322 }
323
324
325 /**
326 * @brief Sets the normalized bounds of the viewport.
327 *
328 * @param x The normalized horizontal offset [0, 1].
329 * @param y The normalized vertical offset [0, 1].
330 * @param width The normalized width [0, 1].
331 * @param height The normalized height [0, 1].
332 */
334 float x, float y, float width, float height
335 ) noexcept {
336 x_ = x;
337 y_ = y;
338 width_ = width;
339 height_ = height;
340
341 needsUpdate_ = true;
342
343 assert((x_ >= 0.0f && x_ <= 1.0f) && "setBounds received unexpected value for x");
344 assert((y_ >= 0.0f && y_ <= 1.0f) && "setBounds received unexpected value for y");
345 assert((width_ >= 0.0f && width_ <= 1.0f) && "setBounds received unexpected value for width");
346 assert((height_ >= 0.0f && height_ <= 1.0f) && "setBounds received unexpected value for height");
347 }
348
349 /**
350 * @brief Gets the clear flags for this viewport.
351 *
352 * @return An integer bitmask representing the `ClearFlags`.
353 */
354 [[nodiscard]] int clearFlags() const noexcept {
355 return clearFlags_;
356 }
357
358 /**
359 * @brief Gets the color used for clearing the color buffer.
360 *
361 * @return A const reference to the clear color.
362 */
363 [[nodiscard]] const helios::math::vec4f& clearColor() const noexcept {
364 return clearColor_;
365 }
366
367 /**
368 * @brief Sets the clear flags for this viewport.
369 *
370 * @param clearFlags An integer bitmask created from `ClearFlags` enum values.
371 *
372 * @return A reference to this viewport to allow fluent chaining.
373 */
375 clearFlags_ = clearFlags;
376 return *this;
377 }
378
379 /**
380 * @brief Specifies the RGBA values used when clearing color buffers.
381 *
382 * Values are automatically clamped to the range [0, 1].
383 *
384 * @param color The color to use for clearing.
385 *
386 * @return A reference to this viewport to allow fluent chaining.
387 */
388 Viewport& setClearColor(const helios::math::vec4f& color) noexcept {
389 clearColor_ = color;
390 return *this;
391 }
392
393 /**
394 * @brief Sets the z-index that controls rendering order relative to sibling viewports.
395 *
396 * @param zIndex The new z-index value; higher values are rendered later.
397 *
398 * @return A reference to this viewport to allow fluent chaining.
399 */
400 Viewport& setZIndex(int zIndex) noexcept {
401 zIndex_ = zIndex;
402 return *this;
403 }
404
405
406 /**
407 * @brief Notifies the viewport of a change in the parent RenderTarget's dimensions.
408 *
409 * This method is called by the parent `RenderTarget` when it is resized. The viewport
410 * uses the new dimensions to calculate the correct aspect ratio for its associated camera.
411 *
412 * @param width The new width of the RenderTarget in pixels.
413 * @param height The new height of the RenderTarget in pixels.
414 *
415 * @see updateCamera()
416 */
417 void onRenderTargetResize(const unsigned int width, const unsigned int height) noexcept {
418 renderTargetSize_ = {width, height};
419 needsUpdate_ = true;
420 updateCamera(width, height);
421 }
422 };
423} // namespace helios::rendering

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.