diff --git a/package-lock.json b/package-lock.json
index e0ce8a7104c0c2831c0d2f0726b4aecad7820596..ba0d8e8601174f88ca60c365fe21061240abaab6 100644
Binary files a/package-lock.json and b/package-lock.json differ
diff --git a/package.json b/package.json
index 37d12c7353147f3050a9e9ec73f8272ccf8de6dd..b4ce18b111a4ddd77fe460be17c1669086e15042 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,8 @@
       "js"
     ],
     "transform": {
-      "\\.ts$": "ts-jest"
+      "\\.ts$": "ts-jest",
+      "\\.(glsl|frag|vert)$": "jest-raw-loader"
     },
     "moduleDirectories": [
       "node_modules",
@@ -67,6 +68,7 @@
     "glslify-import": "^3.1.0",
     "glslify-loader": "^1.0.2",
     "jest": "^22.4.3",
+    "jest-raw-loader": "^1.0.1",
     "raw-loader": "^0.5.1",
     "regl": "git+https://github.com/regl-project/regl.git#45c6ec570232420fca21567499c9c5a2a054432e",
     "ts-jest": "^22.4.2",
diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts
index c0c55ba4b384d8203a32c18275051c41b80b7a3e..155e8ed5cadc0b970332728f0afca49026acdf8b 100644
--- a/src/mol-gl/_spec/renderer.spec.ts
+++ b/src/mol-gl/_spec/renderer.spec.ts
@@ -4,11 +4,76 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-// import createGl = require('gl');
+import createGl = require('gl');
 
-// import Renderer from '../renderer';
+import { PerspectiveCamera } from 'mol-view/camera/perspective';
+import { Vec3, Mat4 } from 'mol-math/linear-algebra';
+import { ValueCell } from 'mol-util';
 
-// describe('renderer', () => {
-//     const gl = createGl(256, 256)
-//     const renderer = Renderer.create(gl, {} as any)
-// })
\ No newline at end of file
+import Renderer from '../renderer';
+import { createPointRenderObject } from '../scene';
+import { fillSerial } from '../renderable/util';
+import { createUniformColor } from 'mol-geo/color/data';
+import { createUniformSize } from 'mol-geo/size/data';
+
+function writeImage(gl: WebGLRenderingContext, width: number, height: number) {
+    const pixels = new Uint8Array(width * height * 4)
+    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
+    process.stdout.write(['P3\n# gl.ppm\n', width, ' ', height, '\n255\n'].join(''))
+    for (let i = 0; i<pixels.length; i+=4) {
+        for (let j = 0; j<3; ++j) {
+            process.stdout.write(pixels[i+j] + ' ')
+        }
+    }
+}
+
+function createRenderer(gl: WebGLRenderingContext) {
+    const camera = PerspectiveCamera.create({
+        near: 0.01,
+        far: 10000,
+        position: Vec3.create(0, 0, 50)
+    })
+    return Renderer.create(gl, camera)
+}
+
+function createPoints() {
+    const position = ValueCell.create(new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0]))
+    const id = ValueCell.create(fillSerial(new Float32Array(3)))
+    const color = createUniformColor({ value: 0xFF0000 })
+    const size = createUniformSize({ value: 1 })
+
+    const transform = ValueCell.create(new Float32Array(16))
+    const m4 = Mat4.identity()
+    Mat4.toArray(m4, transform.ref.value, 0)
+
+    return createPointRenderObject({
+        objectId: 0,
+
+        position,
+        id,
+        color,
+        size,
+        transform,
+
+        instanceCount: 1,
+        elementCount: 3,
+        positionCount: 3
+    })
+}
+
+// TODO not working
+// - headless-gl does not support 'OES_element_index_uint'
+// - shaders not transformed via glslify
+describe.skip('renderer', () => {
+    it('basic', () => {
+        const [ width, height ] = [ 32, 32 ]
+        const gl = createGl(width, height, { preserveDrawingBuffer: true })
+        const renderer = createRenderer(gl)
+        const points = createPoints()
+
+        renderer.add(points)
+        renderer.draw()
+
+        writeImage(gl, width, height)
+    })
+})
\ No newline at end of file
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index 874f029d21b83b7109d2ec85f04ffc236aa1c456..2d2afd56f84808ad6b2534b4b42086b8027b4cec 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -44,8 +44,8 @@ function getPixelRatio() {
 }
 
 namespace Renderer {
-    export function create(canvas: HTMLCanvasElement, camera: Camera): Renderer {
-        const regl = glContext.create({ canvas, extensions, optionalExtensions, profile: false })
+    export function create(gl: WebGLRenderingContext, camera: Camera): Renderer {
+        const regl = glContext.create({ gl, extensions, optionalExtensions, profile: false })
         const scene = Scene.create(regl)
 
         const baseContext = regl({
diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts
index d7e59cd11623e95b6acb35ca9da32f1c88149ac0..667a0d0353bdb63da9c2b5a131d65f0dae95c5b6 100644
--- a/src/mol-view/viewer.ts
+++ b/src/mol-view/viewer.ts
@@ -29,6 +29,17 @@ interface Viewer {
     dispose: () => void
 }
 
+function getWebGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes) {
+    function getContext(contextId: 'webgl' | 'experimental-webgl') {
+        try {
+            return canvas.getContext(contextId, contextAttributes)
+        } catch (e) {
+            return null
+        }
+    }
+    return getContext('webgl') || getContext('experimental-webgl')
+}
+
 namespace Viewer {
     export function create(canvas: HTMLCanvasElement, container: Element): Viewer {
         const input = InputObserver.create(canvas)
@@ -44,7 +55,10 @@ namespace Viewer {
 
         })
 
-        const renderer = Renderer.create(canvas, camera)
+        const gl = getWebGLContext(canvas)
+        if (gl === null) throw new Error('Could not create a WebGL rendering context')
+
+        const renderer = Renderer.create(gl, camera)
 
         let drawPending = false