Camera
Cameras control what part of the world you see and how it maps to the screen. Mibo.Raylib provides Camera2D for 2D games and Camera3D for 3D games. Both support single-camera, split-screen, and overlay patterns.
What and Why
- Scroll and zoom — A 2D camera lets your game world be larger than the screen. Pan, zoom, and follow a player.
- Perspective — A 3D camera defines where you look from and where you look at.
- Coordinate conversion — Convert between screen pixels and world positions for mouse picking, UI placement, and debug tools.
- Multi-camera — Split-screen multiplayer, picture-in-picture minimaps, and HUD overlays on top of the game world.
When to use
Situation |
Use |
|---|---|
2D game with scrolling world |
|
2D game with split-screen or HUD |
|
3D game |
|
3D split-screen or overlay |
|
Mouse picking in 3D |
|
Culling off-screen objects |
|
2D cameras
Creating a camera
Camera2D.create centers the camera on a world position:
let camera = Camera2D.create (Vector2(400f, 300f)) 1.0f viewportSize
position— world position to center onzoom— zoom factor (1.0f= no zoom)viewportSize— screen size in pixels (used to compute the offset)
Using in a view
Wrap your world-space draw commands between beginCamera and endCamera. The layer parameter controls draw order — camera and content must share the same layer range.
buffer
|> Draw.beginCamera 0<RenderLayer> camera
|> Draw.fillRect (0<RenderLayer>, Color.Green) groundRect
|> Draw.fillCircle (0<RenderLayer>, Color.Red) (playerPos, 16f)
|> Draw.endCamera 999<RenderLayer>
|> Draw.text (1000<RenderLayer>, Color.White) hudTextState
_TIP_: Put UI draws after
endCameraon a higher layer so they render in screen space, not world space.
Camera movement
Use smoothFollow to lerp the camera toward a target. Use clampTarget to keep the camera within world bounds. Both take the camera by reference.
let mutable cam = Camera2D.create startPos 1.0f viewportSize
// In your update function, each frame:
Camera2D.smoothFollow &cam playerPos 0.1f
Camera2D.clampTarget &cam 0f 0f worldWidth worldHeight
Coordinate conversion
Convert between screen pixels and world positions:
// Mouse click in world space
let worldPos = Camera2D.screenToWorld camera mousePos
// Where does a world object appear on screen?
let screenPos = Camera2D.worldToScreen camera enemyPos
Use viewportBounds to get the visible world rectangle — useful for culling off-screen objects:
let visible = Camera2D.viewportBounds camera screenWidth screenHeight
2D multi-camera
Camera2DConfig lets you control viewport, clear color, and rendering behavior per camera. Build one with Camera2D.render and chain with* modifiers.
Config modifiers
Modifier |
Description |
|---|---|
|
Viewport in normalized screen coordinates (0–1) |
|
Clear with this color before rendering |
Using a config in a view
let config =
Camera2D.render worldCamera
|> Camera2D.withClear Color.CornflowerBlue
buffer
|> Draw.beginCameraWith 0<RenderLayer> config
|> // ... world content ...
|> Draw.endCamera 999<RenderLayer>
Split-screen
Pre-built helpers for two-player split-screen. Each clears with the given color.
let left = Camera2D.splitScreenLeft player1Camera Color.CornflowerBlue
let right = Camera2D.splitScreenRight player2Camera Color.DarkGreen
buffer
|> Draw.beginCameraWith 0<RenderLayer> left
|> // ... player 1 content ...
|> Draw.endCamera 99<RenderLayer>
|> Draw.beginCameraWith 100<RenderLayer> right
|> // ... player 2 content ...
|> Draw.endCamera 199<RenderLayer>
|> Draw.text (200<RenderLayer>, Color.White) hudState
Available split-screen helpers:
Helper |
Viewport |
|---|---|
|
Left half (0, 0, 0.5, 1) |
|
Right half (0.5, 0, 0.5, 1) |
|
Top half (0, 0, 1, 0.5) |
|
Bottom half (0, 0.5, 1, 0.5) |
Overlay
Picture-in-picture overlay. Clears with black by default.
let minimapRect = Rectangle(0.75f, 0.0f, 0.25f, 0.25f)
let minimap = Camera2D.overlay topDownCamera minimapRect
buffer
|> Draw.beginCameraWith 0<RenderLayer> worldConfig
|> // ... main game ...
|> Draw.endCamera 99<RenderLayer>
|> Draw.beginCameraWith 100<RenderLayer> minimap
|> // ... minimap content ...
|> Draw.endCamera 199<RenderLayer>
3D cameras
Creating a camera
For 3D rendering, create a Camera3D (raylib struct) directly. This is what Draw3D.beginCamera and Camera3D.render expect:
let camera = Camera3D(
Vector3(0f, 10f, 20f), // position
Vector3.Zero, // target
Vector3.UnitY, // up
45.0f, // FOV in degrees
CameraProjection.Perspective
)
For third-person or inspection cameras, use Camera3D.orbit which returns a Camera3D via spherical coordinates:
let orbitCam = Camera3D.orbit target yaw pitch radius fov aspect near far
_NOTE_:
Camera3D.lookAtandCamera3D.orbitreturn aCamerastruct (view + projection matrices). This is useful for ray casting (Camera3D.screenPointToRay) but not for rendering. For rendering, createCamera3Ddirectly or useCamera3D.renderto build a config.
Using in a view
buffer
|> Draw3D.beginCamera camera
|> Draw3D.drawModel playerModel playerTransform
|> Draw3D.addPointLight { Position = torchPos; Color = Color.White; Intensity = 1f; Radius = 10f; CastsShadows = false; ShadowBias = ValueNone }
|> Draw3D.endCamera
|> Draw3D.drop
3D config modifiers
Camera3DConfig controls viewport, clear color, and post-processing. Build with Camera3D.render and chain modifiers:
Modifier |
Description |
|---|---|
|
Viewport in normalized screen coordinates (0–1) |
|
Clear with this color before rendering |
|
Use only specific post-process pass indices |
|
Disable post-processing for this camera |
let config =
Camera3D.render mainCamera
|> Camera3D.withClear Color.SkyBlue
|> Camera3D.withoutPostProcess
buffer
|> Draw3D.beginCameraWith config
|> Draw3D.drawModel sceneModel sceneTransform
|> Draw3D.endCamera
|> Draw3D.drop
Split-screen (3D)
let left = Camera3D.splitScreenLeft player1Camera Color.SkyBlue
let right = Camera3D.splitScreenRight player2Camera Color.SkyBlue
buffer
|> Draw3D.beginCameraWith left
|> // ... player 1 scene ...
|> Draw3D.endCamera
|> Draw3D.beginCameraWith right
|> // ... player 2 scene ...
|> Draw3D.endCamera
|> Draw3D.drop
Overlay (3D)
let minimapRect = Rectangle(0.75f, 0.0f, 0.25f, 0.25f)
let minimap = Camera3D.overlay topDownCamera minimapRect
buffer
|> Draw3D.beginCameraWith mainConfig
|> // ... main scene ...
|> Draw3D.endCamera
|> Draw3D.beginCameraWith minimap
|> // ... minimap scene ...
|> Draw3D.endCamera
|> Draw3D.drop
_TIP_:
Camera3D.overlaydisables post-processing by default. Re-enable it withCamera3D.withPostProcessif needed.
Mouse picking
Cast a ray from a screen position into the 3D scene:
let ray = Camera3D.screenPointToRay camera mousePos viewportWidth viewportHeight
// ray.Position — origin point
// ray.Direction — normalized direction into the scene
See also: 2D Rendering Overview, 3D Rendering, Lighting & Shadows
Mibo.Raylib