Split screen

Two cameras render the scene directly into separate halves of the window using viewports. Split screen can also be composed by rendering each view to a surface first, but viewports make this simple case more direct and immediate.


    
main.lua
local natiny = require("natiny")

if not natiny.backend.init(arg and arg[1] or natiny.backend.AUTO) then
    os.exit(1)
end

local window = natiny.window.create("Natiny - Split screen cameras", 960, 640)
natiny.window.set_scale_mode(window, natiny.window.SCALE_MODE_STRETCH)

local BG = { 21 / 255, 30 / 255, 44 / 255 } -- #151E2C

local function load_mesh(path)
    local resource = natiny.resource.load(path)
    local mesh = natiny.mesh.load(resource)
    natiny.resource.destroy(resource)
    return mesh
end

-- Two models stand next to each other around the centre of the scene.
local platform_mesh = load_mesh("data/common/models/platform.glb")
local barrel_mesh = load_mesh("data/common/models/barrel.glb")
local box_mesh = load_mesh("data/common/models/box_01.glb")

local platform = natiny.model.create(platform_mesh)
local barrel = natiny.model.create(barrel_mesh)
local box = natiny.model.create(box_mesh)
natiny.entity.set_position(barrel, natiny.entity.SPACE_WORLD, -0.45, 0.0, 0.0)
natiny.entity.set_position(box, natiny.entity.SPACE_WORLD, 0.45, 0.25, 0.0)

-- The pivot is the centre of the orbit. The camera is its child, so rotating
-- only the pivot moves the camera around both models.
local pivot = natiny.pivot.create()
natiny.entity.set_position(pivot, natiny.entity.SPACE_WORLD, 0.0, 0.4, 0.0)

-- Left viewport: the original elevated side view.
local side_camera = natiny.camera.create()
natiny.entity.set_parent(side_camera, pivot)
natiny.entity.set_position(side_camera, natiny.entity.SPACE_LOCAL, 0.0, 2.0, 3.0)
natiny.entity.look_at(side_camera, 0.0, 0.4, 0.0)
natiny.camera.set_fov(side_camera, 55.0)
natiny.camera.set_clip(side_camera, 0.1, 100.0)

-- Right viewport: a view straight down. Its position does not move around the
-- pivot's Y axis, but its orientation rotates together with the side camera.
local top_camera = natiny.camera.create()
natiny.entity.set_parent(top_camera, pivot)
natiny.entity.set_position(top_camera, natiny.entity.SPACE_LOCAL, 0.0, 4.0, 0.0)
natiny.entity.set_rotation(top_camera, natiny.entity.SPACE_LOCAL, -90.0, 0.0, 0.0)
natiny.camera.set_fov(top_camera, 55.0)
natiny.camera.set_clip(top_camera, 0.1, 100.0)

local ORBIT_SPEED = 25.0 -- degrees per second

natiny.backend.loop(function(dt)
    natiny.entity.rotate(
        pivot,
        natiny.entity.SPACE_LOCAL,
        0.0,
        ORBIT_SPEED * dt,
        0.0
    )

    natiny.window.bind(window, function()
        natiny.render.clear(BG[1], BG[2], BG[3], 1.0)

        local width = natiny.window.get_width(window)
        local height = natiny.window.get_height(window)
        local left_width = math.floor(width / 2)
        local right_width = width - left_width

        natiny.render.viewport_begin(0, 0, left_width, height, function()
            natiny.camera.bind(side_camera, function()
                natiny.render.tag("model")
            end)
        end)

        natiny.render.viewport_begin(left_width, 0, right_width, height, function()
            natiny.camera.bind(top_camera, function()
                natiny.render.tag("model")
            end)
        end)
    end)
end)

natiny.backend.shutdown()