diff --git a/src/apps/viewer/extensions/jolecule.ts b/src/apps/viewer/extensions/jolecule.ts
index de4f1733f7fc8a4dbfee4c0b5a5c555a9d5f813e..a546c3056053685d10d9c656ab63ed1f8282ea52 100644
--- a/src/apps/viewer/extensions/jolecule.ts
+++ b/src/apps/viewer/extensions/jolecule.ts
@@ -138,24 +138,19 @@ function buildSnapshot(plugin: PluginContext, template: { tree: StateTree, struc
 }
 
 function getCameraSnapshot(e: JoleculeSnapshot['camera']): Camera.Snapshot {
-    const direction = Vec3.sub(Vec3.zero(), e.pos, e.in);
+    const direction = Vec3.sub(Vec3(), e.pos, e.in);
     Vec3.normalize(direction, direction);
-    const up = Vec3.sub(Vec3.zero(), e.pos, e.up);
+    const up = Vec3.sub(Vec3(), e.pos, e.up);
     Vec3.normalize(up, up);
 
     const s: Camera.Snapshot = {
         mode: 'perspective',
-        position: Vec3.scaleAndAdd(Vec3.zero(), e.pos, direction, e.slab.zoom),
+        fov: Math.PI / 4,
+        position: Vec3.scaleAndAdd(Vec3(), e.pos, direction, e.slab.zoom),
         target: e.pos,
-        radius: e.slab.zoom,
-        direction,
+        radius: (e.slab.z_back - e.slab.z_front) / 2,
+        fog: 50,
         up,
-        near: e.slab.zoom + e.slab.z_front,
-        far: e.slab.zoom + e.slab.z_back,
-        fogNear: e.slab.zoom + e.slab.z_front,
-        fogFar: e.slab.zoom + e.slab.z_back,
-        fov: Math.PI / 4,
-        zoom: 1
     };
     return s;
 }
diff --git a/src/mol-canvas3d/camera.ts b/src/mol-canvas3d/camera.ts
index f0731c873267ed7efc05ea0a6aa1ff80f952b5b5..4b8aa2d7f1b7cb2cead4d84f0941a58bbe54f7af 100644
--- a/src/mol-canvas3d/camera.ts
+++ b/src/mol-canvas3d/camera.ts
@@ -6,17 +6,12 @@
  */
 
 import { Mat4, Vec3, Vec4, EPSILON } from '../mol-math/linear-algebra'
-import { Viewport, cameraProject, cameraUnproject, cameraSetClipping } from './camera/util';
-import { Object3D } from '../mol-gl/object3d';
-import { BehaviorSubject } from 'rxjs';
+import { Viewport, cameraProject, cameraUnproject } from './camera/util';
 import { CameraTransitionManager } from './camera/transition';
-import { Canvas3DProps } from './canvas3d';
 
 export { Camera }
 
-class Camera implements Object3D {
-    readonly updatedViewProjection = new BehaviorSubject<Camera>(this);
-
+class Camera {
     readonly view: Mat4 = Mat4.identity();
     readonly projection: Mat4 = Mat4.identity();
     readonly projectionView: Mat4 = Mat4.identity();
@@ -31,14 +26,17 @@ class Camera implements Object3D {
         width: 1, height: 1
     }
 
+    near = 1
+    far = 10000
+    fogNear = 5000
+    fogFar = 10000
+    zoom = 1
+
     readonly transition: CameraTransitionManager = new CameraTransitionManager(this);
 
     get position() { return this.state.position; }
     set position(v: Vec3) { Vec3.copy(this.state.position, v); }
 
-    get direction() { return this.state.direction; }
-    set direction(v: Vec3) { Vec3.copy(this.state.direction, v); }
-
     get up() { return this.state.up; }
     set up(v: Vec3) { Vec3.copy(this.state.up, v); }
 
@@ -50,12 +48,12 @@ class Camera implements Object3D {
     private deltaDirection = Vec3.zero();
     private newPosition = Vec3.zero();
 
-    updateMatrices() {
+    update() {
         const snapshot = this.state as Camera.Snapshot;
         const height = 2 * Math.tan(snapshot.fov / 2) * Vec3.distance(snapshot.position, snapshot.target);
-        snapshot.zoom = this.viewport.height / height;
+        this.zoom = this.viewport.height / height;
 
-        cameraSetClipping(snapshot, this.canvasProps);
+        updateClip(this);
 
         switch (this.state.mode) {
             case 'orthographic': updateOrtho(this); break;
@@ -65,17 +63,12 @@ class Camera implements Object3D {
 
         const changed = !Mat4.areEqual(this.projection, this.prevProjection, EPSILON) || !Mat4.areEqual(this.view, this.prevView, EPSILON);
 
-        Mat4.mul(this.projectionView, this.projection, this.view)
-        Mat4.invert(this.inverseProjectionView, this.projectionView)
-
-
         if (changed) {
             Mat4.mul(this.projectionView, this.projection, this.view)
             Mat4.invert(this.inverseProjectionView, this.projectionView)
 
             Mat4.copy(this.prevView, this.view);
             Mat4.copy(this.prevProjection, this.projection);
-            this.updatedViewProjection.next(this);
         }
 
         return changed;
@@ -98,7 +91,8 @@ class Camera implements Object3D {
         const aspectFactor = (height < width ? 1 : aspect)
         const targetDistance = Math.abs((radius / aspectFactor) / Math.sin(fov / 2))
 
-        Vec3.setMagnitude(this.deltaDirection, this.state.direction, targetDistance)
+        Vec3.sub(this.deltaDirection, this.target, this.position)
+        Vec3.setMagnitude(this.deltaDirection, this.deltaDirection, targetDistance)
         Vec3.sub(this.newPosition, target, this.deltaDirection)
 
         const state = Camera.copySnapshot(Camera.createDefaultSnapshot(), this.state)
@@ -113,15 +107,6 @@ class Camera implements Object3D {
         if (radius > 0) this.setState(this.getFocus(target, radius), durationMs);
     }
 
-    // lookAt(target: Vec3) {
-    //     cameraLookAt(this.position, this.up, this.direction, target);
-    // }
-
-    // translate(v: Vec3) {
-    //     Vec3.add(this.position, this.position, v);
-    //     cameraLookAt(this.position, this.up, this.direction, this.target);
-    // }
-
     project(out: Vec4, point: Vec3) {
         return cameraProject(out, point, this.viewport, this.projectionView)
     }
@@ -130,11 +115,7 @@ class Camera implements Object3D {
         return cameraUnproject(out, point, this.viewport, this.inverseProjectionView)
     }
 
-    dispose() {
-        this.updatedViewProjection.complete();
-    }
-
-    constructor(private canvasProps: Canvas3DProps, state?: Partial<Camera.Snapshot>, viewport = Viewport.create(-1, -1, 1, 1)) {
+    constructor(state?: Partial<Camera.Snapshot>, viewport = Viewport.create(-1, -1, 1, 1)) {
         this.viewport = viewport;
         Camera.copySnapshot(this.state, state);
     }
@@ -144,13 +125,6 @@ class Camera implements Object3D {
 namespace Camera {
     export type Mode = 'perspective' | 'orthographic'
 
-    export interface ClippingInfo {
-        near: number,
-        far: number,
-        fogNear: number,
-        fogFar: number
-    }
-
     /**
      * Sets an offseted view in a larger frustum. This is useful for
      * - multi-window or multi-monitor/multi-machine setups
@@ -178,71 +152,48 @@ namespace Camera {
     export function createDefaultSnapshot(): Snapshot {
         return {
             mode: 'perspective',
+            fov: Math.PI / 4,
 
             position: Vec3.create(0, 0, 100),
-            direction: Vec3.create(0, 0, 1),
             up: Vec3.create(0, 1, 0),
-
             target: Vec3.create(0, 0, 0),
-            radius: 10,
-
-            near: 1,
-            far: 10000,
-            fogNear: 1,
-            fogFar: 10000,
 
-            fov: Math.PI / 4,
-            zoom: 1,
+            radius: 10,
+            fog: 50,
         };
     }
 
     export interface Snapshot {
-        mode: Mode,
+        mode: Mode
+        fov: number
 
-        position: Vec3,
-        // Normalized camera direction, from Target to Position, for some reason?
-        direction: Vec3,
-        up: Vec3,
+        position: Vec3
+        up: Vec3
+        target: Vec3
 
-        target: Vec3,
         radius: number
-
-        near: number,
-        far: number,
-        fogNear: number,
-        fogFar: number,
-
-        fov: number,
-        zoom: number,
+        fog: number
     }
 
     export function copySnapshot(out: Snapshot, source?: Partial<Snapshot>) {
         if (!source) return out;
 
         if (typeof source.mode !== 'undefined') out.mode = source.mode;
+        if (typeof source.fov !== 'undefined') out.fov = source.fov;
 
         if (typeof source.position !== 'undefined') Vec3.copy(out.position, source.position);
-        if (typeof source.direction !== 'undefined') Vec3.copy(out.direction, source.direction);
         if (typeof source.up !== 'undefined') Vec3.copy(out.up, source.up);
-
         if (typeof source.target !== 'undefined') Vec3.copy(out.target, source.target);
-        if (typeof source.radius !== 'undefined') out.radius = source.radius;
-
-        if (typeof source.near !== 'undefined') out.near = source.near;
-        if (typeof source.far !== 'undefined') out.far = source.far;
-        if (typeof source.fogNear !== 'undefined') out.fogNear = source.fogNear;
-        if (typeof source.fogFar !== 'undefined') out.fogFar = source.fogFar;
 
-        if (typeof source.fov !== 'undefined') out.fov = source.fov;
-        if (typeof source.zoom !== 'undefined') out.zoom = source.zoom;
+        if (typeof source.radius !== 'undefined') out.radius = source.radius;
+        if (typeof source.fog !== 'undefined') out.fog = source.fog;
 
         return out;
     }
 }
 
-const _center = Vec3.zero();
 function updateOrtho(camera: Camera) {
-    const { viewport, state: { zoom, near, far }, viewOffset } = camera
+    const { viewport, zoom, near, far, viewOffset } = camera
 
     const fullLeft = -(viewport.width - viewport.x) / 2
     const fullRight = (viewport.width - viewport.x) / 2
@@ -274,16 +225,15 @@ function updateOrtho(camera: Camera) {
     Mat4.ortho(camera.projection, left, right, top, bottom, near, far)
 
     // build view matrix
-    Vec3.add(_center, camera.position, camera.direction)
-    Mat4.lookAt(camera.view, camera.position, _center, camera.up)
+    Mat4.lookAt(camera.view, camera.position, camera.target, camera.up)
 }
 
 function updatePers(camera: Camera) {
     const aspect = camera.viewport.width / camera.viewport.height
 
-    const { state: { fov, near, far }, viewOffset } = camera
+    const { near, far, viewOffset } = camera
 
-    let top = near * Math.tan(0.5 * fov)
+    let top = near * Math.tan(0.5 * camera.state.fov)
     let height = 2 * top
     let width = aspect * height
     let left = -0.5 * width
@@ -299,6 +249,30 @@ function updatePers(camera: Camera) {
     Mat4.perspective(camera.projection, left, left + width, top, top - height, near, far)
 
     // build view matrix
-    Vec3.add(_center, camera.position, camera.direction)
-    Mat4.lookAt(camera.view, camera.position, _center, camera.up)
+    Mat4.lookAt(camera.view, camera.position, camera.target, camera.up)
+}
+
+function updateClip(camera: Camera) {
+    const { radius, mode, fog } = camera.state
+
+    const cDist = Vec3.distance(camera.position, camera.target)
+    const bRadius = Math.max(1, radius)
+
+    let near = cDist - bRadius
+    let far = cDist + bRadius
+
+    const fogNearFactor = -(50 - fog) / 50
+    let fogNear = cDist - (bRadius * fogNearFactor)
+    let fogFar = cDist + bRadius
+
+    if (mode === 'perspective') {
+        // set at least to 5 to avoid slow sphere impostor rendering
+        near = Math.max(5, near)
+        far = Math.max(5, far)
+    }
+
+    camera.near = near;
+    camera.far = far;
+    camera.fogNear = fogNear;
+    camera.fogFar = fogFar;
 }
\ No newline at end of file
diff --git a/src/mol-canvas3d/camera/transition.ts b/src/mol-canvas3d/camera/transition.ts
index 4a012dac31611663a21a1fa845d4d4d176d315fc..67ee4e890a8805bcc35479ca5f9feec849608266 100644
--- a/src/mol-canvas3d/camera/transition.ts
+++ b/src/mol-canvas3d/camera/transition.ts
@@ -68,34 +68,21 @@ class CameraTransitionManager {
 namespace CameraTransitionManager {
     export type TransitionFunc = (out: Camera.Snapshot, t: number, source: Camera.Snapshot, target: Camera.Snapshot) => void
 
+    const _rot = Quat.identity();
     export function defaultTransition(out: Camera.Snapshot, t: number, source: Camera.Snapshot, target: Camera.Snapshot): void {
         Camera.copySnapshot(out, target);
 
-        // Rotate direction
-        const rot = Quat.identity();
-        Quat.slerp(rot, rot, Quat.rotationTo(Quat.zero(), source.direction, target.direction), t);
-        Vec3.transformQuat(out.direction, source.direction, rot);
-
         // Rotate up
-        Quat.setIdentity(rot);
-        Quat.slerp(rot, rot, Quat.rotationTo(Quat.zero(), source.up, target.up), t);
-        Vec3.transformQuat(out.up, source.up, rot);
+        Quat.slerp(_rot, Quat.Identity, Quat.rotationTo(_rot, source.up, target.up), t);
+        Vec3.transformQuat(out.up, source.up, _rot);
 
-        // Lerp target & radius
+        // Lerp target, position & radius
         Vec3.lerp(out.target, source.target, target.target, t);
+        Vec3.lerp(out.position, source.position, target.position, t);
         out.radius = lerp(source.radius, target.radius, t);
 
-        // Update position
-        const dist = -lerp(Vec3.distance(source.position, source.target), Vec3.distance(target.position, target.target), t);
-        Vec3.scale(out.position, out.direction, dist);
-        Vec3.add(out.position, out.position, out.target);
-
-        // Lerp other props
-        out.zoom = lerp(source.zoom, target.zoom, t);
+        // Lerp fov & fog
         out.fov = lerp(source.fov, target.fov, t);
-        out.near = lerp(source.near, target.near, t);
-        out.far = lerp(source.far, target.far, t);
-        out.fogNear = lerp(source.fogNear, target.fogNear, t);
-        out.fogFar = lerp(source.fogFar, target.fogFar, t);
+        out.fog = lerp(source.fog, target.fog, t);
     }
 }
\ No newline at end of file
diff --git a/src/mol-canvas3d/camera/util.ts b/src/mol-canvas3d/camera/util.ts
index 29d5233105f94d56d45bd40c4c67631d977e4ef2..2dc02fcce6f0704dffae3b41e57171cb7ee68213 100644
--- a/src/mol-canvas3d/camera/util.ts
+++ b/src/mol-canvas3d/camera/util.ts
@@ -4,9 +4,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Mat4, Vec3, Vec4, EPSILON } from '../../mol-math/linear-algebra'
-import { Camera } from '../camera'
-import { Canvas3DProps } from '../canvas3d'
+import { Mat4, Vec3, Vec4 } from '../../mol-math/linear-algebra'
 
 export { Viewport }
 
@@ -57,63 +55,6 @@ namespace Viewport {
 
 //
 
-const tmpVec3 = Vec3()
-
-/** Modifies the direction & up vectors in place, both are normalized */
-export function cameraLookAt(position: Vec3, up: Vec3, direction: Vec3, target: Vec3) {
-    Vec3.sub(tmpVec3, target, position)
-    Vec3.normalize(tmpVec3, tmpVec3)
-
-    if (!Vec3.isZero(tmpVec3)) {
-        // change direction vector to look at target
-        const d = Vec3.dot(tmpVec3, up)
-        if (Math.abs(d - 1) < EPSILON) { // parallel
-            Vec3.scale(up, direction, -1)
-        } else if (Math.abs(d + 1) < EPSILON) { // anti parallel
-            Vec3.copy(up, direction)
-        }
-        Vec3.copy(direction, tmpVec3)
-
-        // normalize up vector
-        Vec3.cross(tmpVec3, direction, up)
-        Vec3.normalize(tmpVec3, tmpVec3)
-        Vec3.cross(up, tmpVec3, direction)
-        Vec3.normalize(up, up)
-    }
-}
-
-export function cameraSetClipping(state: Camera.Snapshot, p: Canvas3DProps) {
-    const cDist = Vec3.distance(state.position, state.target)
-    const bRadius = Math.max(1, state.radius)
-
-    const nearFactor = (50 - p.clip[0]) / 50
-    const farFactor = -(50 - p.clip[1]) / 50
-    let near = cDist - (bRadius * nearFactor)
-    let far = cDist + (bRadius * farFactor)
-
-    const fogNearFactor = (50 - p.fog[0]) / 50
-    const fogFarFactor = -(50 - p.fog[1]) / 50
-    let fogNear = cDist - (bRadius * fogNearFactor)
-    let fogFar = cDist + (bRadius * fogFarFactor)
-
-    if (state.mode === 'perspective') {
-        // set at least to 5 to avoid slow sphere impostor rendering
-        near = Math.max(5, p.cameraClipDistance, near)
-        far = Math.max(5, far)
-        fogNear = Math.max(5, fogNear)
-        fogFar = Math.max(5, fogFar)
-    } else if (state.mode === 'orthographic') {
-        if (p.cameraClipDistance > 0) {
-            near = Math.max(p.cameraClipDistance, near)
-        }
-    }
-
-    state.near = near;
-    state.far = far;
-    state.fogNear = fogNear;
-    state.fogFar = fogFar;
-}
-
 const NEAR_RANGE = 0
 const FAR_RANGE = 1
 
diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts
index 4f0b9d7eea665952a9d496bf1fbcee9ff3b1ff30..99838ccdef859a9757fd565285aea2449ea6bea4 100644
--- a/src/mol-canvas3d/canvas3d.ts
+++ b/src/mol-canvas3d/canvas3d.ts
@@ -34,13 +34,9 @@ import { PickPass } from './passes/pick';
 import { Task } from '../mol-task';
 
 export const Canvas3DParams = {
-    // TODO: FPS cap?
-    // maxFps: PD.Numeric(30),
     cameraMode: PD.Select('perspective', [['perspective', 'Perspective'], ['orthographic', 'Orthographic']]),
-    cameraClipDistance: PD.Numeric(0, { min: 0.0, max: 50.0, step: 0.1 }, { description: 'The distance between camera and scene at which to clip regardless of near clipping plane.' }),
+    cameraFog: PD.Numeric(50, { min: 1, max: 100, step: 1 }),
     cameraResetDurationMs: PD.Numeric(250, { min: 0, max: 1000, step: 1 }, { description: 'The time it takes to reset the camera.' }),
-    clip: PD.Interval([1, 100], { min: 1, max: 100, step: 1 }),
-    fog: PD.Interval([50, 100], { min: 1, max: 100, step: 1 }),
 
     multiSample: PD.Group(MultiSampleParams),
     postprocessing: PD.Group(PostprocessingParams),
@@ -124,9 +120,10 @@ namespace Canvas3D {
 
         const scene = Scene.create(webgl)
 
-        const camera = new Camera(p, {
+        const camera = new Camera({
             position: Vec3.create(0, 0, 100),
-            mode: p.cameraMode
+            mode: p.cameraMode,
+            fog: p.cameraFog
         })
 
         const controls = TrackballControls.create(input, camera, p.trackball)
@@ -177,7 +174,7 @@ namespace Canvas3D {
 
             let didRender = false
             controls.update(currentTime)
-            const cameraChanged = camera.updateMatrices()
+            const cameraChanged = camera.update()
             multiSample.update(force || cameraChanged, currentTime)
 
             if (force || cameraChanged || multiSample.enabled) {
@@ -336,10 +333,10 @@ namespace Canvas3D {
                 if (props.cameraMode !== undefined && props.cameraMode !== camera.state.mode) {
                     camera.setState({ mode: props.cameraMode })
                 }
-                if (props.cameraClipDistance !== undefined) p.cameraClipDistance = props.cameraClipDistance
+                if (props.cameraFog !== undefined && props.cameraFog !== camera.state.fog) {
+                    camera.setState({ fog: props.cameraFog })
+                }
                 if (props.cameraResetDurationMs !== undefined) p.cameraResetDurationMs = props.cameraResetDurationMs
-                if (props.clip !== undefined) p.clip = [props.clip[0], props.clip[1]]
-                if (props.fog !== undefined) p.fog = [props.fog[0], props.fog[1]]
 
                 if (props.postprocessing) postprocessing.setProps(props.postprocessing)
                 if (props.multiSample) multiSample.setProps(props.multiSample)
@@ -352,10 +349,8 @@ namespace Canvas3D {
             get props() {
                 return {
                     cameraMode: camera.state.mode,
-                    cameraClipDistance: p.cameraClipDistance,
+                    cameraFog: camera.state.fog,
                     cameraResetDurationMs: p.cameraResetDurationMs,
-                    clip: p.clip,
-                    fog: p.fog,
 
                     postprocessing: { ...postprocessing.props },
                     multiSample: { ...multiSample.props },
@@ -379,7 +374,6 @@ namespace Canvas3D {
                 input.dispose()
                 controls.dispose()
                 renderer.dispose()
-                camera.dispose()
                 interactionHelper.dispose()
             }
         }
diff --git a/src/mol-canvas3d/controls/trackball.ts b/src/mol-canvas3d/controls/trackball.ts
index 49d3ff91eb7913e27db574e934f322f5e1b340b2..f67b6ed569afdd486372561357bcccb81126dbb2 100644
--- a/src/mol-canvas3d/controls/trackball.ts
+++ b/src/mol-canvas3d/controls/trackball.ts
@@ -9,7 +9,7 @@
  */
 
 import { Quat, Vec2, Vec3, EPSILON } from '../../mol-math/linear-algebra';
-import { cameraLookAt, Viewport } from '../camera/util';
+import { Viewport } from '../camera/util';
 import InputObserver, { DragInput, WheelInput, PinchInput } from '../../mol-util/input/input-observer';
 import { ParamDefinition as PD } from '../../mol-util/param-definition';
 import { Camera } from '../camera';
@@ -244,7 +244,6 @@ namespace TrackballControls {
 
             Vec3.add(camera.position, camera.target, _eye)
             checkDistances()
-            cameraLookAt(camera.position, camera.up, camera.direction, camera.target)
 
             if (Vec3.squaredDistance(lastPosition, camera.position) > EPSILON) {
                 Vec3.copy(lastPosition, camera.position)
@@ -260,7 +259,6 @@ namespace TrackballControls {
             Vec3.copy(camera.up, up0)
 
             Vec3.sub(_eye, camera.position, camera.target)
-            cameraLookAt(camera.position, camera.up, camera.direction, camera.target)
             Vec3.copy(lastPosition, camera.position)
         }
 
diff --git a/src/mol-canvas3d/passes/multi-sample.ts b/src/mol-canvas3d/passes/multi-sample.ts
index 4f2ea9524789c56adf556ac7a5c1e25a2fe69b39..ba907667123e1fb403a6b4c64b500e7af57e37b6 100644
--- a/src/mol-canvas3d/passes/multi-sample.ts
+++ b/src/mol-canvas3d/passes/multi-sample.ts
@@ -135,7 +135,7 @@ export class MultiSamplePass {
         for (let i = 0; i < offsetList.length; ++i) {
             const offset = offsetList[i]
             Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height)
-            camera.updateMatrices()
+            camera.update()
 
             // the theory is that equal weights for each sample lead to an accumulation of rounding
             // errors. The following equation varies the sampleWeight per sample so that it is uniformly
@@ -174,7 +174,7 @@ export class MultiSamplePass {
         compose.render()
 
         camera.viewOffset.enabled = false
-        camera.updateMatrices()
+        camera.update()
     }
 
     private renderTemporalMultiSample() {
@@ -223,7 +223,7 @@ export class MultiSamplePass {
         for (let i = 0; i < numSamplesPerFrame; ++i) {
             const offset = offsetList[this.sampleIndex]
             Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height)
-            camera.updateMatrices()
+            camera.update()
 
             // render scene and optionally postprocess
             drawPass.render(false)
@@ -269,7 +269,7 @@ export class MultiSamplePass {
         }
 
         camera.viewOffset.enabled = false
-        camera.updateMatrices()
+        camera.update()
         if (this.sampleIndex >= offsetList.length) this.sampleIndex = -1
     }
 }
diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts
index 80d2b1058e2e615e6468a2c3e79d0d6dc6856d41..0dee8714a31d7030c64f34e081ad45471b53f586 100644
--- a/src/mol-canvas3d/passes/postprocessing.ts
+++ b/src/mol-canvas3d/passes/postprocessing.ts
@@ -160,10 +160,10 @@ export class PostprocessingPass {
     }
 
     render(toDrawingBuffer: boolean) {
-        ValueCell.update(this.renderable.values.uFar, this.camera.state.far)
-        ValueCell.update(this.renderable.values.uNear, this.camera.state.near)
-        ValueCell.update(this.renderable.values.uFogFar, this.camera.state.fogFar)
-        ValueCell.update(this.renderable.values.uFogNear, this.camera.state.fogNear)
+        ValueCell.update(this.renderable.values.uFar, this.camera.far)
+        ValueCell.update(this.renderable.values.uNear, this.camera.near)
+        ValueCell.update(this.renderable.values.uFogFar, this.camera.fogFar)
+        ValueCell.update(this.renderable.values.uFogNear, this.camera.fogNear)
         ValueCell.update(this.renderable.values.dOrthographic, this.camera.state.mode === 'orthographic' ? 1 : 0)
 
         const { gl, state } = this.webgl
diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts
index 36c843ff1c673b20c5e4f14c7519d600ffcbb5fa..c632c17ccb82882123c6b1d8f25aa2dd4dcf5ddf 100644
--- a/src/mol-gl/_spec/renderer.spec.ts
+++ b/src/mol-gl/_spec/renderer.spec.ts
@@ -24,13 +24,10 @@ import { Color } from '../../mol-util/color';
 import { Sphere3D } from '../../mol-math/geometry';
 import { createEmptyOverpaint } from '../../mol-geo/geometry/overpaint-data';
 import { createEmptyTransparency } from '../../mol-geo/geometry/transparency-data';
-import { DefaultCanvas3DParams } from '../../mol-canvas3d/canvas3d';
 
 function createRenderer(gl: WebGLRenderingContext) {
     const ctx = createContext(gl)
-    const camera = new Camera(DefaultCanvas3DParams, {
-        near: 0.01,
-        far: 10000,
+    const camera = new Camera({
         position: Vec3.create(0, 0, 50)
     })
     const renderer = Renderer.create(ctx, camera)
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index 673b8854db3fa4c8d51dbf9e7eca0c5eff2e7fa3..e661ad68671b5f36025b3e280ef21de121547a9e 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -101,10 +101,10 @@ namespace Renderer {
             uReflectivity: ValueCell.create(p.reflectivity),
 
             uCameraPosition: ValueCell.create(Vec3.clone(camera.state.position)),
-            uNear: ValueCell.create(camera.state.near),
-            uFar: ValueCell.create(camera.state.far),
-            uFogNear: ValueCell.create(camera.state.fogNear),
-            uFogFar: ValueCell.create(camera.state.fogFar),
+            uNear: ValueCell.create(camera.near),
+            uFar: ValueCell.create(camera.far),
+            uFogNear: ValueCell.create(camera.fogNear),
+            uFogFar: ValueCell.create(camera.fogFar),
             uFogColor: ValueCell.create(bgColor),
 
             uPickingAlphaThreshold: ValueCell.create(p.pickingAlphaThreshold),
@@ -173,10 +173,10 @@ namespace Renderer {
             ValueCell.update(globalUniforms.uViewOffset, camera.viewOffset.enabled ? Vec2.set(viewOffset, camera.viewOffset.offsetX * 16, camera.viewOffset.offsetY * 16) : Vec2.set(viewOffset, 0, 0))
 
             ValueCell.update(globalUniforms.uCameraPosition, camera.state.position)
-            ValueCell.update(globalUniforms.uFar, camera.state.far)
-            ValueCell.update(globalUniforms.uNear, camera.state.near)
-            ValueCell.update(globalUniforms.uFogFar, camera.state.fogFar)
-            ValueCell.update(globalUniforms.uFogNear, camera.state.fogNear)
+            ValueCell.update(globalUniforms.uFar, camera.far)
+            ValueCell.update(globalUniforms.uNear, camera.near)
+            ValueCell.update(globalUniforms.uFogFar, camera.fogFar)
+            ValueCell.update(globalUniforms.uFogNear, camera.fogNear)
 
             globalUniformsNeedUpdate = true
             state.currentRenderItemId = -1
diff --git a/src/mol-math/linear-algebra/3d/quat.ts b/src/mol-math/linear-algebra/3d/quat.ts
index 3b9844d0f340143718e365543490454bac2375f5..574f88abebfe609b2523c6f519c76a0dedba295c 100644
--- a/src/mol-math/linear-algebra/3d/quat.ts
+++ b/src/mol-math/linear-algebra/3d/quat.ts
@@ -28,6 +28,7 @@ import { EPSILON } from './common';
 import { NumberArray } from '../../../mol-util/type-helpers';
 
 interface Quat extends Array<number> { [d: number]: number, '@type': 'quat', length: 4 }
+interface ReadonlyQuat extends Array<number> { readonly [d: number]: number, '@type': 'quat', length: 4 }
 
 function Quat() {
     return Quat.zero();
@@ -440,6 +441,8 @@ namespace Quat {
     export function toString(a: Quat, precision?: number) {
         return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)}  ${a[3].toPrecision(precision)}]`;
     }
+
+    export const Identity: ReadonlyQuat = identity()
 }
 
 export default Quat
\ No newline at end of file