VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
camera.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 05.09.2025.
5//
6#pragma once
7
8#include <array>
9#include <cmath>
10#include <numbers>
11
12#include "constants.h"
13#include "core/math/matrix4.h"
14#include "core/math/vector3.h"
15#include "core/math/vector4.h"
19
20namespace visutwin::canvas
21{
22 enum class ProjectionType
23 {
24 // An orthographic camera projection where the frustum shape is essentially a cuboid
26 // A perspective camera projection where the frustum shape is essentially pyramidal
28 };
29
30 class GraphNode;
31
39 class Camera
40 {
41 public:
42 float fov() const { return _fov; }
43 void setFov(float value) { _fov = value; }
44
45 ProjectionType projection() const { return _projection; }
46 void setProjection(ProjectionType value);
47
48 float aspectRatio() const { return _aspectRatio; }
49 void setAspectRatio(float value);
50 AspectRatioMode aspectRatioMode() const { return _aspectRatioMode; }
51
53
54 float nearClip() const { return _nearClip; }
55 void setNearClip(const float value) { _nearClip = value; _projMatDirty = true; }
56
57 float farClip() const { return _farClip; }
58 void setFarClip(const float value) { _farClip = value; _projMatDirty = true; }
59
60 float orthoHeight() const { return _orthoHeight; }
61 void setOrthoHeight(const float value) { _orthoHeight = value; _projMatDirty = true; }
62
63 bool horizontalFov() const { return _horizontalFov; }
64
66 {
67 evaluateProjectionMatrix();
68 return _projMat;
69 }
71 {
72 evaluateProjectionMatrix();
73 return _projMatSkybox;
74 }
75
76 float jitter() const { return _jitter; }
77 void setJitter(const float value) { _jitter = value; }
78
79 const Matrix4& viewProjectionPrevious() const { return _viewProjPrevious; }
80 const Matrix4& viewProjectionInverse() const { return _viewProjInverse; }
81 const std::array<float, 4>& jitters() const { return _jitters; }
82 void storeShaderMatrices(const Matrix4& viewProjection, float jitterX, float jitterY, int renderVersion);
83
84 const std::vector<std::shared_ptr<RenderPass>>& renderPasses() const { return _renderPasses; };
85
86 const std::shared_ptr<RenderTarget>& renderTarget() const { return _renderTarget; }
87 void setRenderTarget(const std::shared_ptr<RenderTarget>& value) { _renderTarget = value;}
88
89 const Color& clearColor() const { return _clearColor; }
90 void setClearColor(const Color& value) { _clearColor = value; }
91
92 // normalized viewport rectangle (x, y, width, height)
93 // in render target coordinates.
94 const Vector4& rect() const { return _rect; }
95 void setRect(const Vector4& value) { _rect = value; }
96
97 // normalized camera scissor rectangle.
98 // If not explicitly set in a scene, this matches rect usage in renderer path.
99 const Vector4& scissorRect() const { return _scissorRect; }
100 void setScissorRect(const Vector4& value) { _scissorRect = value; }
101
102 const std::unique_ptr<GraphNode>& node() const { return _node; }
103 void setNode(GraphNode* value);
104
105 void setScissorRectClear(bool value) { _scissorRectClear = value; }
106
107 void setClearDepthBuffer(bool value) { _clearDepthBuffer = value; }
108
109 void setClearStencilBuffer(bool value) { _clearStencilBuffer = value; }
110
111 void setClearColorBuffer(bool value) { _clearColorBuffer = value; }
112 bool clearColorBufferEnabled() const { return _clearColorBuffer; }
113 bool clearDepthBufferEnabled() const { return _clearDepthBuffer; }
114 bool clearStencilBufferEnabled() const { return _clearStencilBuffer; }
115
116 const std::shared_ptr<RenderPassColorGrab>& renderPassColorGrab() const { return _renderPassColorGrab; }
117
118 const std::shared_ptr<RenderPass>& renderPassDepthGrab() const { return _renderPassDepthGrab; }
119
120 void _enableRenderPassColorGrab(const std::shared_ptr<GraphicsDevice>& device, bool enable);
121 void _enableRenderPassDepthGrab(const std::shared_ptr<GraphicsDevice>& device, bool enable);
122
123 // Returns 8 frustum corners in camera-local space for the given near/far depth slice.
124 // Points 0-3 are near plane corners (BR, TR, TL, BL), points 4-7 are far plane.
125 // .
126 std::array<Vector3, 8> getFrustumCorners(const float nearDist, const float farDist) const
127 {
128 const float fovRad = _fov * (std::numbers::pi_v<float> / 180.0f);
129 float xNear, yNear, xFar, yFar;
130
131 if (_projection == ProjectionType::Perspective) {
132 if (_horizontalFov) {
133 xNear = nearDist * std::tan(fovRad * 0.5f);
134 yNear = xNear / _aspectRatio;
135 xFar = farDist * std::tan(fovRad * 0.5f);
136 yFar = xFar / _aspectRatio;
137 } else {
138 yNear = nearDist * std::tan(fovRad * 0.5f);
139 xNear = yNear * _aspectRatio;
140 yFar = farDist * std::tan(fovRad * 0.5f);
141 xFar = yFar * _aspectRatio;
142 }
143 } else {
144 yNear = yFar = _orthoHeight;
145 xNear = xFar = _orthoHeight * _aspectRatio;
146 }
147
148 return {{
149 Vector3( xNear, -yNear, -nearDist), // 0: near bottom-right
150 Vector3( xNear, yNear, -nearDist), // 1: near top-right
151 Vector3(-xNear, yNear, -nearDist), // 2: near top-left
152 Vector3(-xNear, -yNear, -nearDist), // 3: near bottom-left
153 Vector3( xFar, -yFar, -farDist), // 4: far bottom-right
154 Vector3( xFar, yFar, -farDist), // 5: far top-right
155 Vector3(-xFar, yFar, -farDist), // 6: far top-left
156 Vector3(-xFar, -yFar, -farDist), // 7: far bottom-left
157 }};
158 }
159 private:
160 void evaluateProjectionMatrix();
161
163
164 float _aspectRatio = 16 / 9.0f;
165
166 float _fov = 45.0f;
167
168 float _nearClip = 0.1f;
169 float _farClip = 1000.0f;
170
171 float _orthoHeight = 10.0f;
172
174
175 bool _horizontalFov = false;
176
177 Matrix4 _projMat;
178 bool _projMatDirty = true;
179
180 Matrix4 _projMatSkybox;
181
182 // camera jitter and matrices used by TAA resolve.
183 float _jitter = 0.0f;
184 int _shaderMatricesVersion = -1;
185 Matrix4 _viewProjInverse = Matrix4::identity();
186 Matrix4 _viewProjCurrent = Matrix4::identity();
187 Matrix4 _viewProjPrevious = Matrix4::identity();
188 std::array<float, 4> _jitters = {0.0f, 0.0f, 0.0f, 0.0f};
189 bool _hasViewProjCurrent = false;
190
191 // Render passes used to render this camera. If empty, the camera will render using the default render pass
192 std::vector<std::shared_ptr<RenderPass>> _renderPasses;
193
194 std::shared_ptr<RenderTarget> _renderTarget;
195
196 Color _clearColor = Color(0.75f, 0.75f, 0.75f, 1.0f);
197 Vector4 _rect = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
198 Vector4 _scissorRect = Vector4(0.0f, 0.0f, 1.0f, 1.0f);
199
200 std::unique_ptr<GraphNode> _node;
201
202 bool _scissorRectClear = false;
203
204 bool _clearDepthBuffer = true;
205
206 bool _clearStencilBuffer = true;
207
208 bool _clearColorBuffer = true;
209
210 std::shared_ptr<RenderPassColorGrab> _renderPassColorGrab;
211
212 std::shared_ptr<RenderPass> _renderPassDepthGrab;
213
214 // when true, the forward shader outputs distance-from-reflection-plane
215 // instead of PBR lighting. Used by the depth camera in blurred planar reflections.
216 // camera.setShaderPass('planar_reflection_depth').
217 bool _planarReflectionDepthPass = false;
218 public:
219 void setPlanarReflectionDepthPass(bool v) { _planarReflectionDepthPass = v; }
220 [[nodiscard]] bool planarReflectionDepthPass() const { return _planarReflectionDepthPass; }
221 };
222}
Perspective or orthographic camera with projection matrix, jitter (TAA), and render target binding.
Definition camera.h:40
float aspectRatio() const
Definition camera.h:48
AspectRatioMode aspectRatioMode() const
Definition camera.h:50
void setProjection(ProjectionType value)
Definition camera.cpp:17
const std::vector< std::shared_ptr< RenderPass > > & renderPasses() const
Definition camera.h:84
const std::shared_ptr< RenderPassColorGrab > & renderPassColorGrab() const
Definition camera.h:116
void setRenderTarget(const std::shared_ptr< RenderTarget > &value)
Definition camera.h:87
float jitter() const
Definition camera.h:76
void setJitter(const float value)
Definition camera.h:77
void setPlanarReflectionDepthPass(bool v)
Definition camera.h:219
const Matrix4 & viewProjectionInverse() const
Definition camera.h:80
float farClip() const
Definition camera.h:57
const Matrix4 & viewProjectionPrevious() const
Definition camera.h:79
std::array< Vector3, 8 > getFrustumCorners(const float nearDist, const float farDist) const
Definition camera.h:126
const Vector4 & rect() const
Definition camera.h:94
void setOrthoHeight(const float value)
Definition camera.h:61
void _enableRenderPassColorGrab(const std::shared_ptr< GraphicsDevice > &device, bool enable)
Definition camera.cpp:77
void setScissorRectClear(bool value)
Definition camera.h:105
const std::shared_ptr< RenderPass > & renderPassDepthGrab() const
Definition camera.h:118
ProjectionType projection() const
Definition camera.h:45
void setFov(float value)
Definition camera.h:43
void setRect(const Vector4 &value)
Definition camera.h:95
void _enableRenderPassDepthGrab(const std::shared_ptr< GraphicsDevice > &device, bool enable)
Definition camera.cpp:88
bool clearDepthBufferEnabled() const
Definition camera.h:113
float nearClip() const
Definition camera.h:54
void setAspectRatio(float value)
Definition camera.cpp:25
void setClearColorBuffer(bool value)
Definition camera.h:111
void setClearStencilBuffer(bool value)
Definition camera.h:109
void setNode(GraphNode *value)
Definition camera.cpp:12
bool horizontalFov() const
Definition camera.h:63
bool planarReflectionDepthPass() const
Definition camera.h:220
const Matrix4 & projectionMatrix()
Definition camera.h:65
const std::unique_ptr< GraphNode > & node() const
Definition camera.h:102
void setScissorRect(const Vector4 &value)
Definition camera.h:100
const std::shared_ptr< RenderTarget > & renderTarget() const
Definition camera.h:86
const Vector4 & scissorRect() const
Definition camera.h:99
bool clearStencilBufferEnabled() const
Definition camera.h:114
const std::array< float, 4 > & jitters() const
Definition camera.h:81
bool clearColorBufferEnabled() const
Definition camera.h:112
float orthoHeight() const
Definition camera.h:60
void setClearColor(const Color &value)
Definition camera.h:90
void setAspectRatioMode(AspectRatioMode value)
Definition camera.cpp:33
const Color & clearColor() const
Definition camera.h:89
float fov() const
Definition camera.h:42
const Matrix4 & projectionMatrixSkybox()
Definition camera.h:70
void setFarClip(const float value)
Definition camera.h:58
void setClearDepthBuffer(bool value)
Definition camera.h:107
void setNearClip(const float value)
Definition camera.h:55
void storeShaderMatrices(const Matrix4 &viewProjection, float jitterX, float jitterY, int renderVersion)
Definition camera.cpp:58
Hierarchical scene graph node with local/world transforms and parent-child relationships.
Definition graphNode.h:28
RGBA color with floating-point components in [0, 1].
Definition color.h:18
4x4 column-major transformation matrix with SIMD acceleration.
Definition matrix4.h:31
static Matrix4 identity()
Definition matrix4.h:108
3D vector for positions, directions, and normals with multi-backend SIMD acceleration.
Definition vector3.h:29
4D vector for homogeneous coordinates, color values, and SIMD operations.
Definition vector4.h:20