Skip to content
This repository has been archived by the owner on Jun 12, 2023. It is now read-only.
/ rendercam Public archive
forked from rgrams/rendercam

A universal render script & camera package for all the common camera types. (for Defold)

License

Notifications You must be signed in to change notification settings

lukas-kasticky/rendercam

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rendercam

A universal render script & camera package for all the common camera types: perspective or orthographic, fixed aspect ratio or unfixed aspect ratio, plus four options for how the view changes for different resolutions and window sizes, and more. Also does screen-to-world and world-to-screen transforms for any camera type; camera switching, zooming, panning, shaking, recoil, and lerped following.

Note: This fork is intended for everyone that wants to use the new rendercam features without waiting for the official 2.0 release and is based on commit de7c43d from the original dev branch.

Added features:

  • Debug mode defaults to false
  • Toggleable debug mode in properties pane
  • Set camera boundaries from properties pane

Installation

Install Rendercam in your project by adding it as a library dependency. Open your game.project file and in the "Dependencies" field under "Project", add:

https://github.com/lukas-kasticky/rendercam/archive/v2.0-pre3.zip

Then open the "Project" menu of the editor and click "Fetch Libraries". You should see the "rendercam" folder appear in your assets panel after a few moments.

Basic Setup

After installation, it just takes two simple steps to get Rendercam up and running.

  1. Select the Rendercam render script in your game.project file. Under "bootstrap", edit the "Render" field and select "/rendercam/rendercam.render".
  2. Add a Rendercam camera to your scene. Add "camera.go" from the rendercam folder to your main collection. It can be a child of another game object, or not, but make sure it's z-position is zero (this is for the default camera settings only).

Note: the "shared_state" setting must also be enabled in your game.project file for Rendercam to work, but it is enabled by default.

Camera Name Conflicts

Rendercam identifies cameras by their URL "path" or "ID". Normally this means you don't have to worry about name collisions. However, if you use collection proxies, it's possible to have two cameras with identical IDs, so you will need to rename one of them. If you have a camera named "camera" in your main collection, and another, also named "camera", in a collection you load via proxy, this will cause a name conflict with Rendercam.

If either of the cameras is inside a secondary collection with a different name, there will be no conflict, it's only an issue if they are both in the base level of their collections (or in identically-named sub-collections).

Camera Settings

To change your camera settings, expand the camera game object in the outline and select it's script component. In the properties panel you will have a bunch of different options.

Debug Bounds bool

If checked, the camera draws boundaries.

Debug Camera Name bool

If checked, the name of the current camera will appear on the top left.

Active bool

Whether the camera is initially active or not. If you have multiple cameras you will want to uncheck this property on your secondary cameras to make sure the right camera is used. If you have no active camera a fallback camera will be used for rendering and you will see a message in the console.

Orthographic bool

Leave checked for an orthographic camera, uncheck for a perspective camera. Some other options below are only used if the camera is of one type or the other. For example: FOV is only used by perspective cameras, and Ortho Scale is only used by orthographic cameras.

Near Z number

The distance in front of the camera where rendering will start, relative to the camera's position. This can be any value for orthographic cameras, but must be greater than zero for perspective cameras. -1 is the default for orthographic cameras, 1 is a decent value for perspective cameras.

Far Z number

The distance in front of the camera where rendering will end, relative to the camera's position. Should be greater than Near Z. 1 is the default for orthographic cameras, 1000 is a reasonable value for perspective cameras.

View Distance number

The distance in front of the camera where the game world is located. This is usually 0 for orthographic cameras, or the z position of a perspective camera for 2.5D games (if the game world is at Z=0). For most perspective cameras (non-fixed-FOV), this is the distance at which the view area is measured. The View Distance is subtracted from the camera Z position on init to get the world Z position used for screen-to-world position transforms.

FOV (field of view) number

The field of view for perspective cameras, in degrees. This property is generally unused (and should be left at -1), as the FOV will be calculated based on other settings. If you want a camera with a fixed FOV, make sure "Use View Area" is un-checked, select the "Fixed Height" scale mode, and set FOV to your desired angle. The aspect ratio can be fixed or not.

Zoom number

Zoom factor for orthographic cameras. Higher values are for zooming "in", lower values for zooming "out". A zoom of 2 means objects will appear twice as large on-screen, etc. I recommend you do not change this value in the editor, instead, see the "View Area" property below to set the initial view area of your camera. Use rendercam.zoom_in(), rendercam.get_zoom(), and rendercam.set_zoom() to change camera zoom at runtime, or go.animate the "zoom" property of the camera's script component. This property is for orthographic cameras only, for perspective cameras, simply alter the camera's Z position to zoom.

Fixed Aspect Ratio bool

If checked, black bars will be added to the top and bottom or sides of the viewport as necessary so it will always match the aspect ratio you specify via the "Aspect Ratio" property.

Aspect Ratio vector3

The aspect ratio to be used if "Fixed Aspect Ratio" is checked. Use X and Y to enter your desired proportion---i.e. X=16, Y=9 for a 16:9 aspect. A vector is used to enter the ratio so it can be an accurate fraction. The numbers themselves don't matter, just the proportion between them. You can use 1280, 1024 instead of 5, 4, and so on.

Use View Area bool

If checked, the "View Area" setting will be used to calculate the initial area of the world that the camera will show. If not checked, the window resolution specified in your game.project file will be used, unless you're using a perspective camera and have set "FOV" greater than zero, in which case the camera will start with that FOV instead of calculating a specific area of world.

View Area vector3

The dimensions in world space that the camera will show, if "Use View Area" is checked. They will be measured at "2d World Z" (usually 0). If using a fixed aspect ratio, the view area Y value will be overwritten based on the X value if they don't match the specified aspect ratio.

View Scale Modes:

The next four checkbox settings determine the scale mode used to calculate how the view changes anytime the window resolution is changed (including on init if your camera settings don't match your display settings in game.project). Only the first mode checked will be used (and a default is used if none are checked). Note that Fixed Area, Fixed Width, and Fixed Height all work exactly the same if you're using a fixed aspect ratio (since the aspect ratio locks the viewport dimensions together).

Expand View bool

The view area will expand and contract with the window size, keeping the world at the same size on-screen. If you set your camera view area to 800x600, but your game starts with a window size of 1600x900 (as set in game.project), then the view will expand to fill the window and show a 1600x900 area of the world. Likewise if the window size is smaller---the camera will simply show less of the world.

Fixed Area bool

The camera will zoom in or out to show exactly the same area of the game world. This works great for a wide range of window or display proportions, if you don't need either dimension to be exactly the same for everyone.

Fixed Width bool

The camera will always show the same width of game world, the height is adjusted to fit. If the window is stretched vertically, it will show more space on top and bottom.

Fixed Height bool

Like "Fixed Width", but switched. The camera will always show the same height of the game world, and the width will vary with the window proportion. If you make the window tall and skinny, you'll see the same distance up and down, but very little side to side.

Camera bounds:

Use Camera Bounds bool

If checked, limits for the camera's position in its local X/Y are set. The camera will not be allowed to move outside the specified rectangle bounds (except movement due to camera shake and recoil).

Camera Bounds {Left, Right, Top, Bottom} number

Sets the boundaries of the limit rectangle, in coordinates local to the camera.

Camera Functions & Messages

To use the other features of Rendercam you need to call module functions from a script. First, require the rendercam module in your script:

local rendercam = require "rendercam.rendercam"

A lot of Rendercam's functions have optional arguments. These are listed in brackets, [like_this]. For example, most of the camera functions have an optional [cam_id] argument. You can leave this out and the functions will operate on the current camera.

With Rendercam's camera following feature, the delayed nature of messages can be useful, so you can also send a "follow" message to a camera instead of calling rendercam.follow(). See below for details.

rendercam.activate_camera(cam_id)

Activate a different camera. If you have multiple cameras, use this to switch between them, otherwise you don't need it. Cameras with "Active" checked will activate themselves on init.

PARAMETERS

  • cam_id hash - ID of the camera game object.

rendercam.zoom_in(z, [cam_id])

Zoom the camera in or out. If the camera is orthographic, this adds z * rendercam.ortho_zoom_speed to the camera's ortho scale. If the camera is perspective, this moves the camera forward by z. You can set rendercam.ortho_zoom_speed to adjust the global ortho zoom speed, or use rendercam.get_zoom and rendercam.set_zoom for full control.

PARAMETERS

  • z number - Amount to zoom in by. (use a negative value to zoom out)
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.get_zoom([cam_id])

Gets the current zoom of the camera. (orthographic cameras only)

PARAMETERS

  • cam_id hash - ID of the camera game object. Uses the current camera by default.

RETURNS

  • z number - The camera's zoom factor.

rendercam.set_zoom(z, [cam_id])

Sets the zoom of the camera. (orthographic cameras only)

PARAMETERS

  • z number - Zoom factor.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.pan(dx, dy, [cam_id])

Moves the camera in it's local X/Y plane.

PARAMETERS

  • dx number - Distance to move the camera along its local X axis.
  • dy number - Distance to move the camera along its local Y axis.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.set_bounds(left, right, top, bottom, [cam_id])

Sets limits on the camera's position in its local X/Y plane. The camera will not be allowed to move outside the specified rectangle bounds (except movement due to camera shake and recoil). Call again with all nil arguments (just leave them out unless you are specifying a cam_id) to clear the camera's bounds.

PARAMETERS

  • left, right, top, bottom number | nil - The boundaries of the limit rectangle, in coordinates local to the camera.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.shake(dist, dur, [cam_id])

Shakes the camera in its local X/Y plane. The intensity of the shake will fall off linearly over its duration.

PARAMETERS

  • dist number - Radius of the shake.
  • dur number - Duration of the shake in seconds.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.recoil(vec, dur, [cam_id])

Recoils the camera by the supplied vector, local to the camera's rotation. The recoil will fall off quadratically (t^2) over its duration.

PARAMETERS

  • vec vector3 - Initial vector to offset the camera by, local to the camera's rotation.
  • dur number - Duration of the recoil in seconds.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.stop_shaking([cam_id])

Cancels all current shakes and recoils for this camera.

PARAMETERS

  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.follow(target_id, [allowMultiFollow], [cam_id])

Makes the camera follow a game object. Lerps by default (see rendercam.follow_lerp_func below). If you want the camera to rigidly follow a game object it is better to just make the camera a child of that object. Set rendercam.follow_lerp_speed to adjust the global camera follow speed (default: 3). You can tell a camera to follow multiple game objects, in which case it will move toward the average of their positions. Note that the camera follow function only affects the camera's X and Y coordinates, so it only makes sense for 2D-oriented games. For this feature to work as expected, the camera should not be the child of a game object that is scaled, rotated, or translated.

PARAMETERS

  • target_id hash - ID of the game object to follow.
  • allowMultiFollow bool - If true, will add target_id to the list of objects to follow instead of replacing all previous targets.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

"follow", { target_id=..., allowMultiFollow=... }

The message equivalent of rendercam.follow(). If you want a camera to follow a game object as soon as the collection it is in has loaded (on init), send this message to it instead of using rendercam.follow(). This is because the order in which init functions are called in a collection is semi-random, but the camera must have run its init function before rendercam.follow() will work on it. The message is guaranteed to be received after all init functions have run.

FIELDS

  • target_id hash - ID of the game object to follow.
  • allowMultiFollow bool - If true, will add target_id to the list of objects to follow instead of replacing all previous targets.

rendercam.unfollow([target_id], [cam_id])

Makes the camera stop following a game object. If the camera was following multiple objects, this will remove target_id from the list, otherwise it will stop the camera from following anything.

PARAMETERS

  • target_id hash - ID of the object to unfollow. If the camera is only following one object, you can leave out this argument.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

rendercam.follow_lerp_func(curPos, targetPos, dt)

function M.follow_lerp_func(curPos, targetPos, dt)
    return vmath.lerp(0.5^(dt * M.follow_lerp_speed), targetPos, curPos)
end

This is the default follow lerp function used by all cameras. Feel free to overwrite it if you need different behavior. If you need more complex control or different behavior for each camera, you should ignore Rendercam's follow feature and move your cameras directly, as you would any other game object.

PARAMETERS

  • curPos vector3 - The camera's current position, local to its parent.
  • targetPos vector3 - The average position of all follow targets---the exact position of the target if there is only one.
  • dt number - Delta time for this frame.

rendercam.set_follow_deadzone(left, right, top, bottom, [cam_id])

Set a deadzone for the camera's following: it will only change position of the followed object moves outside this area. To disable an existing deadzone, call this function with left, right, top, and bottom values of 0.

PARAMETERS

  • left, right, top, bottom number - The boundaries of the deadzone rectangle, in coordinates local to the camera.
  • cam_id hash - ID of the camera game object. Uses the current camera by default.

Window Update Listeners

Sometimes you may have scripts or shaders that need to be updated when the window or camera is changed. The following module functions let you add and remove items from a list of URLs that will be sent the following message whenever the window is resized or the camera is switched:

window_update

FIELDS

  • window vector3 - The same as rendercam.window. The new size of the window.
  • viewport table - The same as rendercam.viewport. Contains:
    • x number - The viewport X offset (black bar width) for fixed aspect ratio cameras.
    • y number - The viewport Y offset (black bar height) for fixed aspect ratio cameras.
    • width number - The viewport width.
    • height number - The viewport height.
  • aspect number - The aspect ratio of the camera.
  • fov number - The field of view of the camera in radians. Should be -1 for orthographic cameras.

rendercam.add_window_listener(url)

Register a URL to be sent a message when the window is updated.

Example:

function init(self)
	self.url = msg.url()
	rendercam.add_window_listener(self.url)
end

PARAMETERS

  • url string | url - The URL. Note: If using a string, this must be an absolute URL including the socket.

rendercam.remove_window_listener(url)

Remove a URL from the list of window update listeners. If you added a listener, make sure you remove it before the script is destroyed.

To continue the above example:

function final(self)
	rendercam.remove_window_listener(self.url)
end

PARAMETERS

  • url string | url - The URL. This must be the same address and type that you passed to 'add_window_listener'. If you added a string, you must remove a string.

Transform Functions

rendercam.screen_to_viewport(x, y, [delta])

Transforms x and y from screen coordinates to viewport coordinates. This only does something when you are using a fixed aspect ratio camera. Otherwise the viewport and the window are the same size. Called internally by rendercam.screen_to_world_ray and rendercam.screen_to_world_2d.

PARAMETERS

  • x number - Screen X.
  • y number - Screen Y.
  • delta bool - If x and y are for a delta (change in) screen position, rather than an absolute screen position.

RETURNS

  • x number - Viewport X.
  • y number - Viewport Y.

rendercam.screen_to_world_2d(x, y, [delta], [worldz])

Transforms x and y from screen coordinates to world coordinates at a certain Z position—either a specified worldz or by default the current camera's "2d World Z". This function returns a position on a plane perpendicular to the camera angle, so it's only accurate for 2D-oriented cameras (facing along the Z axis). It works for 2D-oriented perspective cameras, but will have some small imprecision based on the size of the view depth (farZ - nearZ). For 3D cameras, use rendercam.screen_to_world_plane or rendercam.screen_to_world_ray.

PARAMETERS

  • x number - Screen X
  • y number - Screen Y
  • delta bool - If x and y are for a delta (change in) screen position, rather than an absolute screen position.
  • worlds number - World Z position to find the X and Y coordinates at. Defaults to the current camera's "2d World Z" setting.

RETURNS

  • pos vector3 - World position.

rendercam.screen_to_world_ray(x, y)

Takes x and y screen coordinates and returns two points describing the start and end of a ray from the camera's near plane to its far plane, through that point on the screen. You can use these points to cast a ray to check for collisions "underneath" the mouse cursor, or any other screen point.

PARAMETERS

  • x number - Screen X
  • y number - Screen Y

RETURNS

  • start vector3 - Start point on the camera near plane, in world coordinates.
  • end vector3 - End point on the camera far plane, in world coordinates.

rendercam.screen_to_world_plane(x, y, planeNormal, pointOnPlane)

Gets the screen-to-world ray and intersects it with a world-space plane. The equivalent of rendercam.screen_to_world_2d for 3D cameras. Note: this will return nil if the camera angle is exactly parallel to the plane (perpendicular to the normal).

PARAMETERS

  • x number - Screen X
  • y number - Screen Y
  • planeNormal vector3 - Normal vector of the plane
  • pointOnPlane vector3 - A point on the plane

RETURNS

  • pos vector3 | nil - World position or nil if the camera angle is parallel to the plane.

rendercam.screen_to_gui(x, y, adjust, [isSize])

Transforms x and y from screen coordinates to GUI coordinates. If the window size has changed and your GUI has "Adjust Reference" set to "Per Node", GUI coordinates will no longer match screen coordinates, and they will be different for each adjust mode.

PARAMETERS

  • x number - Screen X
  • y number - Screen Y
  • adjust constant - GUI adjust mode to use for calculation.
    • You can use
      • gui.ADJUST_FIT
      • gui.ADJUST_ZOOM
      • gui.ADJUST_STRETCH
    • Or
      • rendercam.GUI_ADJUST_FIT
      • rendercam.GUI_ADJUST_ZOOM
      • rendercam.GUI_ADJUST_STRETCH
    • Or
      • The result of gui.get_adjust_mode
  • isSize bool - Optional argument. If the coordinates to be transformed are a node size rather than a position. False by default.

RETURNS

  • x number - GUI X
  • y number - GUI Y

rendercam.screen_to_gui_pick(x, y)

Transforms screen coordinates to coordinates that will work accurately with gui.pick_node. If the window size has changed, the coordinate system used by gui.pick_node will not match the screen coordinate system. If you are only picking nodes underneath a touch or the mouse cursor, you don't need this function, just use action.x and action.y in your on_input function. You will need this function to use gui.pick_node with an arbitrary point on the screen (if the window has been changed from it's initial setting). The adjust mode of the GUI node does not matter.

PARAMETERS

  • x number - Screen X
  • y number - Screen Y

RETURNS

  • x number - X
  • y number - Y

rendercam.world_to_screen(pos, [adjust])

Transforms the supplied world position into screen (viewport) coordinates. Can take an optional adjust parameter to calculate an accurate screen coordinate for a gui node with any adjust mode: Fit, Zoom, or Stretch.

PARAMETERS

  • pos vector3 - World position.
  • adjust constant - GUI adjust mode to use for calculation.
    • You can use
      • gui.ADJUST_FIT
      • gui.ADJUST_ZOOM
      • gui.ADJUST_STRETCH
    • Or
      • rendercam.GUI_ADJUST_FIT
      • rendercam.GUI_ADJUST_ZOOM
      • rendercam.GUI_ADJUST_STRETCH
    • Or
      • The result of gui.get_adjust_mode

RETURNS

  • pos vector3 - Screen position

Custom Render Scripts

For a lot of projects you will want to write your own custom render script, to mess with material predicates, use render targets, etc. You can definitely do that with Rendercam. Just copy the "rendercam.render_script" out of the rendercam folder, hook it up, and change whatever you want in it. The Rendercam render script is not very complicated, all the real work is done in the rendercam module. As long as you don't change the view, projection, or viewport stuff, you should be able to do whatever you want without interfering with Rendercam.

GUI and Fixed Aspect Ratios

If you're using a fixed aspect ratio camera, presumably at some point your viewport will be smaller than the actual window (you will have black bars). Unfortunately, if you want your GUI to stay inside the viewport, Defold's nice system of anchors and adjust modes aren't really set up to deal with that. All the automatic GUI adjustments are based on the size of the full window. The best option I've found is to set your game.project display resolution to match your aspect ratio and build your gui inside the guide box that the editor shows you, leaving all the nodes' X and Y anchors set to "None" (i.e. Center). This way, however the display size changes, the GUI nodes should stay at the correct positions inside the viewport.

Error Messages

If you try to do something that Rendercam doesn't support, you will hopefully get a reasonably clear error message in the console. See below for further explanation of a few of them. If you get errors with Rendercam that you don't understand, please report them in the forum thread or a Github issue so I can help you out and improve Rendercam.

"NOTE: rendercam - No active camera found this frame...using fallback camera. There will be no more warnings about this."

This is not really an error message, just a notification to make sure you know what's going on. It means that for at least one frame you have left Rendercam without an active camera, so it's using the default fallback camera to render with. This will happen if your game content is all loaded through collection proxes (such as if you are using Monarch) because it takes a few frames to load the proxies. It will also happen if you forgot to put a camera in your collection, if you un-checked "active" on your camera's properties, or if you deactivated or deleted all your cameras from a script. This message will only print once, the first time it happens, so it won't spam your console if it's the intended behavior.

"WARNING: rendercam.activate_camera() - camera [cam_id] not found. "

This means you called rendercam.activate_camera(cam_id) with an ID that doesn't match any existing camera. Make sure you are using go.get_id with the correct path to get the camera's ID.

"ERROR: rendercam.camera_init() - Camera name conflict with ID: [cam_id]". New camera will overwrite the old! Your cameras must have unique IDs."

This means you have two cameras with identical IDs, you just need to rename one of them. This should only happen if you are using collection proxies, see the section on "Camera Name Conflicts" near the top of this readme.

"rendercam - get_target_worldViewSize() - camera: [cam_id], scale mode not found."

Hopefully no one will ever get this message. It means something is broken and your camera has an invalid scale mode set. Please let me know if this happens.

About

A universal render script & camera package for all the common camera types. (for Defold)

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Lua 86.6%
  • Go 11.4%
  • GLSL 2.0%