Skip to content

CVR Cameras

TL;DR: CVR.CVRCamera is the abstract base exposing per-camera settings (clip planes, HDR, depth texture, culling mask, clear flags, background colour, per-eye pose). Two concrete statics — CVRCamera.PlayerCamera (the active rendering camera) and CVRCamera.PortableCamera (the user’s handheld camera prop) — are what you read or configure from scripts. Binder links exist for all three types; the API is world-gated for mutations.

Source: CVR.CCK.Wasm/Scripting/Links/APIs/CCKStubs/CVRCameraCCK.cs.

namespace CVR
{
public abstract class CVRCamera
{
public static CVRPlayerCamera PlayerCamera { get; internal set; }
public static CVRPortableCamera PortableCamera { get; internal set; }
public Camera GetCamera();
// Read / write per-camera state
public virtual float GetNearClipPlane();
public virtual void SetNearClipPlane(float v);
public virtual float GetFarClipPlane();
public virtual void SetFarClipPlane(float v);
public virtual bool GetAllowHDR();
public virtual void SetAllowHDR(bool v);
public virtual DepthTextureMode GetDepthTextureMode();
public virtual void SetDepthTextureMode(DepthTextureMode v);
public virtual bool GetUseOcclusionCulling();
public virtual void SetUseOcclusionCulling(bool v);
public virtual bool GetAllowMSAA();
public virtual void SetAllowMSAA(bool v);
public virtual LayerMask GetCullingMask();
public virtual void SetCullingMask(LayerMask v);
public virtual CameraClearFlags GetClearFlags();
public virtual void SetClearFlags(CameraClearFlags v);
public virtual Color GetBackgroundColor();
public virtual void SetBackgroundColor(Color v);
public virtual bool GetLayerCullSpherical();
public virtual void SetLayerCullSpherical(bool v);
public virtual float[] GetLayerCullDistances();
public virtual void SetLayerCullDistances(float[] arr);
// Batched operations
public virtual void CopyFrom(Camera source);
public virtual void ResetToDefault();
public virtual void CopyPostProcessing(Camera sourceCamera);
public virtual void ClearPostProcessing();
// Stereo
public Vector3 GetEyePosition(Camera.StereoscopicEye eye);
public Quaternion GetEyeRotation(Camera.StereoscopicEye eye);
}
public enum CVRCameraRenderingMode
{
Normal, // Desktop & VR: normal rendering
FakeMultiPass, // VR: one camera per eye (hidden cameras emulate multi-pass)
MockHMD // Desktop: main camera is rendering SPI / mock HMD
}
public sealed class CVRPlayerCamera : CVRCamera
{
public CVRCameraRenderingMode GetRenderingMode();
}
public sealed class CVRPortableCamera : CVRCamera
{
public bool IsActive();
}
}
CVRPlayerCamera cam = CVRCamera.PlayerCamera;
if (cam != null)
{
float near = cam.GetNearClipPlane();
float far = cam.GetFarClipPlane();
Vector3 leftEye = cam.GetEyePosition(Camera.StereoscopicEye.Left);
Vector3 rightEye = cam.GetEyePosition(Camera.StereoscopicEye.Right);
CVRCameraRenderingMode mode = cam.GetRenderingMode();
// ...
}
if (CVRCamera.PortableCamera.IsActive()) { /* user is holding their portable camera */ }
void ConfigureSceneCamera()
{
CVRPlayerCamera cam = CVRCamera.PlayerCamera;
if (cam == null) return;
cam.SetFarClipPlane(500f);
cam.SetBackgroundColor(new Color(0.02f, 0.02f, 0.05f));
cam.SetClearFlags(CameraClearFlags.SolidColor);
cam.SetCullingMask(myCameraMask);
}

To restore defaults after a scripted scene:

CVRCamera.PlayerCamera.ResetToDefault();

CVRPlayerCamera.GetRenderingMode() returns:

  • Normal — standard Unity rendering path (single camera). Desktop and VR when single-pass stereo is selected by the engine.
  • FakeMultiPass — VR emulated multi-pass: CVR uses hidden per-eye cameras for certain effects. Some shaders/post-effects behave differently here; guard effect code with this check.
  • MockHMD — Desktop mode that simulates HMD rendering (single-pass instanced). Rare; mostly only relevant to effects that hand-roll eye index lookups.

Most scripts don’t need to branch on this. It’s exposed so effect-level world scripts can disable or adjust incompatible post-processing paths.

The portable camera is the photo / video capture prop every player has access to. CVRCamera.PortableCamera.IsActive() tells you whether the user currently has it drawn. Useful for:

  • Pausing expensive volumetric effects during a capture (respect the capture settings the user chose).
  • Triggering diegetic behaviour when the user is about to take a photo.
  • All getters — (Any, Any, Any). Anyone can read camera state.
  • Setters — per binder link, typically (Any, Any, Self) or (World, Any, —). The camera belongs to the local user, so scope matters:
    • World scripts driving the player camera: permitted for the world’s own VM.
    • Avatar scripts: can read, generally cannot mutate the player camera (scope check fails since the camera isn’t a child of the avatar).
  • Portable camera: same rules. An avatar script cannot override its settings.

When in doubt, try the write and catch WasmAccessDeniedException; the message identifies the axis.

CVRCamera.PlayerCamera and PortableCamera statics are null-safe: if CVR hasn’t assigned them yet (very early Awake, before input is ready), they can be null. Null-check every access in Awake; by Start they should be populated for the active local context.

CopyPostProcessing(Camera sourceCamera) copies all post-processing settings from a Camera you hold a reference to (e.g. a disabled child GameObject you pre-configured in the inspector) onto the CVR camera. ClearPostProcessing() removes them.

This is the easiest way to apply custom bloom / vignette / colour grading to the player camera from a world script without implementing the stack yourself.

  • CVR Host Functions — the underlying binder links (CVRCameraLink, CVRPlayerCameraLink, CVRPortableCameraLink, CVRCameraRenderingModeLink).
  • Permissions — why some setters fail from non-world contexts.
  • Performance — prefer CopyFrom over many scalar setters.