Camera¶
Camera is a component that determines how the scene is displayed on the screen. It defines the viewpoint, projection, and visual parameters. The camera always renders directly to the screen.
Overview¶
The Camera component is the foundation of Thunder Engine’s visual system. It transforms the 3D scene into a 2D image, defining:
Position and orientation — where the camera is looking from and where it’s looking at (defined via the transform component)
Projection — perspective (3D games) or orthographic (2D games, interfaces)
View parameters — field of view, near and far clipping planes
Background color — the color used to fill the screen before rendering
Note
Multiple cameras can exist in a scene, but only one can be active at a time. The active camera is set via Engine::setMainCamera().
Component Properties¶
- fov (float)
Field of View in degrees for perspective projection. Determines how wide an angle the camera covers.
Typical values: 60° — 90°
Narrow angle (< 60°) creates a “telescope” effect
Wide angle (> 90°) creates a “fisheye” effect
Default:
60.0.Note
This property only affects rendering if
orthographic = false.- near (float)
Near clipping plane. Objects closer than this distance are not rendered.
Too small a value may cause depth artifacts (z-fighting)
Too large a value may “cut off” objects that are close to the camera
Default:
0.1.- far (float)
Far clipping plane. Objects beyond this distance are not rendered.
Increasing this value improves visibility of distant objects but may reduce performance and depth buffer precision
Default:
1000.0.- size (float)
Orthographic projection size. Determines how many units of the game world fit vertically.
With a value of
5.0, the visible vertical area will be 10 units (from -5 to +5)Horizontal size depends on the screen’s aspect ratio
Default:
5.0.Note
This property only affects rendering if
orthographic = true.- focalDistance (float)
Camera focus distance. Used for depth of field effects and other post-effects that depend on distance from the camera.
Default:
10.0.- backgroundColor (Vector4)
The color used to fill the screen before rendering the scene. Components: R, G, B, A.
Values range from
0.0to1.0Represented as a Color-picker in the editor
Default:
(0.1, 0.1, 0.15, 1.0)— dark gray.- orthographic (bool)
Determines the projection type:
false— perspective projection. Objects appear smaller with distance. Used in 3D games.true— orthographic projection. Object size does not depend on distance. Used in 2D games, UI, level editors.
Default:
false(perspective).
Usage Examples¶
Creating a Main 3D Camera
// Create an actor for the camera
Actor* cameraActor = scene->createActor("MainCamera");
cameraActor->transform()->setPosition(Vector3(0.0f, 5.0f, -10.0f));
cameraActor->transform()->setRotation(Quaternion::fromEuler(15.0f, 0.0f, 0.0f));
// Add the camera component
Camera* camera = cameraActor->addComponent<Camera>();
camera->setFov(70.0f);
camera->setNear(0.3f);
camera->setFar(500.0f);
camera->setOrthographic(false);
camera->setColor(Vector4(0.2f, 0.3f, 0.4f, 1.0f));
// Make this camera active
Camera::setCurrent(camera);
Creating a 2D Camera
Actor* camera2DActor = scene->createActor("Camera2D");
Camera* camera2D = camera2DActor->addComponent<Camera>();
camera2D->setOrthographic(true);
camera2D->setOrthoSize(5.0f); // 10 units vertically
camera2D->setNear(-100.0f); // Negative values can be used for 2D
camera2D->setFar(100.0f);
camera2D->setColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
// Position the camera
camera2DActor->transform()->setPosition(Vector3(0.0f, 0.0f, 0.0f));
Camera::setCurrent(camera2D);
2D Camera Following the Player
class Camera2DFollow : public Actor {
public:
void start() override {
m_camera = addComponent<Camera>();
m_camera->setOrthographic(true);
m_camera->setOrthoSize(5.0f);
m_camera->setNear(-100.0f);
m_camera->setFar(100.0f);
m_target = scene->findActor("Player");
}
void update(float deltaTime) override {
if (!m_target) return;
// Follow the player with level bounds constraints
Vector3 targetPos = m_target->position();
float x = CLAMP(targetPos.x, m_minX, m_maxX);
float y = CLAMP(targetPos.y, m_minY, m_maxY);
transform()->setPosition(Vector3(x, y, transform()->position().z));
}
private:
Camera* m_camera = nullptr;
Actor* m_target = nullptr;
float m_minX = -10.0f, m_maxX = 10.0f;
float m_minY = -5.0f, m_maxY = 5.0f;
};
Switching Projection Type During Gameplay
// Toggle between first-person view and top-down view
void toggleCameraMode(Camera* camera) {
if (camera->isOrthographic()) {
// Switch to perspective mode (3D)
camera->setOrthographic(false);
camera->setFov(70.0f);
} else {
// Switch to orthographic mode (2D/map)
camera->setOrthographic(true);
camera->setOrthoSize(20.0f);
}
}
Recommendations¶
- Clipping Plane Configuration
Set
nearas large as possible to avoid z-fighting (depth artifacts)Set
faronly to the necessary distance — too large a value reduces depth precision and performanceFor 2D games, negative
nearvalues can be used so objects behind the camera are not clipped
- Choosing Projection
Perspective (
orthographic = false):3D games
Realistic depth perception
“Fisheye” effect with wide FOV
Orthographic (
orthographic = true):2D games (platformers, strategy games)
UI and HUD
Level editors
Mini-maps (via a separate camera)
- focalDistance
Used for post-effects (depth of field, motion blur)
Can be changed dynamically to focus on different objects
Default
10.0is suitable for most scenarios
- Multiple Cameras
Multiple cameras can exist in a scene, but only one is active
Switch cameras using
Camera::setCurrent
- Optimization
For distant views, use a larger
farvalue only when necessaryIn 2D games, use an orthographic camera with precisely tuned
sizeCreate separate cameras for cutscenes and switch them as needed
Complete Example: Simple Third-Person Camera¶
class ThirdPersonCamera : public Actor {
public:
void start() override {
m_camera = addComponent<Camera>();
m_camera->setFov(60.0f);
m_camera->setNear(0.1f);
m_camera->setFar(1000.0f);
m_camera->setColor(Vector4(0.1f, 0.1f, 0.15f, 1.0f));
m_target = scene->findActor("Player")->transform();
// Make this camera active
Camera::setCurrent(m_camera);
}
void update(float deltaTime) override {
if (!m_target) return;
// Get mouse input
Vector4 delta = Input::mouseDelta() * m_sensitivity;
m_yaw += delta.x;
m_pitch -= delta.y;
m_pitch = CLAMP(m_pitch, -30.0f, 60.0f);
// Calculate camera position relative to player
Quaternion rotation = Quaternion::fromEuler(m_pitch, m_yaw, 0.0f);
Vector3 offset = rotation * Vector3(0.0f, 2.0f, -5.0f);
Vector3 desiredPosition = m_target->position() + offset;
// Smooth movement
Vector3 newPosition = MIX(transform()->position(), desiredPosition, deltaTime * m_smoothSpeed);
transform()->setPosition(newPosition);
}
private:
Camera* m_camera = nullptr;
Transform* m_target = nullptr;
float m_yaw = 0.0f;
float m_pitch = 20.0f;
float m_sensitivity = 0.1f;
float m_smoothSpeed = 10.0f;
};