diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts
index 0950c4ced563b65fe1efd695d65de4bd84dbef0f..75e995aac8d784997a3ef2ac9ddf3572b40f6835 100644
--- a/src/mol-canvas3d/canvas3d.ts
+++ b/src/mol-canvas3d/canvas3d.ts
@@ -93,10 +93,11 @@ namespace Canvas3D {
 
     export function fromCanvas(canvas: HTMLCanvasElement, props: Partial<Canvas3DProps> = {}, runTask = DefaultRunTask) {
         const gl = getGLContext(canvas, {
-            alpha: false,
+            alpha: true,
             antialias: true,
             depth: true,
-            preserveDrawingBuffer: true
+            preserveDrawingBuffer: true,
+            premultipliedAlpha: false,
         })
         if (gl === null) throw new Error('Could not create a WebGL rendering context')
         const input = InputObserver.fromElement(canvas)
diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts
index da4a273a98f6dede4ad3441d82bebf1ab8955fa0..24ab5c36d0bca2f2d710bb059c6d7ca3f041c232 100644
--- a/src/mol-gl/renderable/schema.ts
+++ b/src/mol-gl/renderable/schema.ts
@@ -168,6 +168,7 @@ export const GlobalUniformSchema = {
     uFogFar: UniformSpec('f'),
     uFogColor: UniformSpec('v3'),
 
+    uTransparentBackground: UniformSpec('i'),
     uPickingAlphaThreshold: UniformSpec('f'),
     uInteriorDarkening: UniformSpec('f'),
 }
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index a4ba67c8838305a8eb63e259d19a06b3554e7eba..db06d23bd21387015f46c989a0b705b474dbf099 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -46,6 +46,7 @@ interface Renderer {
 
 export const RendererParams = {
     backgroundColor: PD.Color(Color(0x000000), { description: 'Background color of the 3D canvas' }),
+    transparentBackground: PD.Boolean(false, { description: 'Background opacity of the 3D canvas' }),
     pickingAlphaThreshold: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }, { description: 'The minimum opacity value needed for an object to be pickable.' }),
     interiorDarkening: PD.Numeric(0.5, { min: 0.0, max: 1.0, step: 0.01 }),
 
@@ -107,6 +108,7 @@ namespace Renderer {
             uFogFar: ValueCell.create(camera.fogFar),
             uFogColor: ValueCell.create(bgColor),
 
+            uTransparentBackground: ValueCell.create(p.transparentBackground ? 1 : 0),
             uPickingAlphaThreshold: ValueCell.create(p.pickingAlphaThreshold),
             uInteriorDarkening: ValueCell.create(p.interiorDarkening),
         }
@@ -191,7 +193,7 @@ namespace Renderer {
 
             if (clear) {
                 if (variant === 'color') {
-                    state.clearColor(bgColor[0], bgColor[1], bgColor[2], 1.0)
+                    state.clearColor(bgColor[0], bgColor[1], bgColor[2], p.transparentBackground ? 0 : 1)
                 } else {
                     state.clearColor(1, 1, 1, 1)
                 }
@@ -204,7 +206,7 @@ namespace Renderer {
                     if (r.state.opaque) renderObject(r, variant)
                 }
 
-                state.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
+                state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE)
                 state.enable(gl.BLEND)
                 for (let i = 0, il = renderables.length; i < il; ++i) {
                     const r = renderables[i]
@@ -224,7 +226,7 @@ namespace Renderer {
             clear: () => {
                 state.depthMask(true)
                 state.colorMask(true, true, true, true)
-                state.clearColor(bgColor[0], bgColor[1], bgColor[2], 1.0)
+                state.clearColor(bgColor[0], bgColor[1], bgColor[2], p.transparentBackground ? 0 : 1)
                 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
             },
             render,
@@ -243,6 +245,10 @@ namespace Renderer {
                     Color.toVec3Normalized(bgColor, p.backgroundColor)
                     ValueCell.update(globalUniforms.uFogColor, Vec3.copy(globalUniforms.uFogColor.ref.value, bgColor))
                 }
+                if (props.transparentBackground !== undefined && props.transparentBackground !== p.transparentBackground) {
+                    p.transparentBackground = props.transparentBackground
+                    ValueCell.update(globalUniforms.uTransparentBackground, p.transparentBackground ? 1 : 0)
+                }
                 if (props.lightIntensity !== undefined && props.lightIntensity !== p.lightIntensity) {
                     p.lightIntensity = props.lightIntensity
                     ValueCell.update(globalUniforms.uLightIntensity, p.lightIntensity)
diff --git a/src/mol-gl/shader/chunks/apply-fog.glsl.ts b/src/mol-gl/shader/chunks/apply-fog.glsl.ts
index d7308351b7c2d98ecdfac9cd73554cc12c252262..2bfd2cd87b334cb9d77d8be7e0c9ce734d723f78 100644
--- a/src/mol-gl/shader/chunks/apply-fog.glsl.ts
+++ b/src/mol-gl/shader/chunks/apply-fog.glsl.ts
@@ -2,10 +2,11 @@ export default `
 #ifdef dUseFog
 	float depth = length(vViewPosition);
     float fogFactor = smoothstep(uFogNear, uFogFar, depth);
-	gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
-    float fogAlpha = (1.0 - fogFactor) * gl_FragColor.a;
-    if (fogAlpha < 0.01)
-        discard;
-    gl_FragColor = vec4(gl_FragColor.rgb, fogAlpha);
+    if (uTransparentBackground == 0) {
+	    gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
+    } else {
+        float fogAlpha = (1.0 - fogFactor) * gl_FragColor.a;
+        gl_FragColor.a = fogAlpha;
+    }
 #endif
 `
\ No newline at end of file
diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts
index 6ee029edb1a3bcfda5866b7be472485185404ba4..28d04173c777ac782cfea172149e2df5c2a948b2 100644
--- a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts
+++ b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts
@@ -22,6 +22,7 @@ uniform vec3 uFogColor;
 uniform float uAlpha;
 uniform float uPickingAlphaThreshold;
 uniform int uPickable;
+uniform int uTransparentBackground;
 
 uniform float uInteriorDarkening;
 `
\ No newline at end of file
diff --git a/src/mol-plugin/skin/base/components/viewport.scss b/src/mol-plugin/skin/base/components/viewport.scss
index b77e628d4ea8d97ca5e521501db3b53797263596..54472ba0c377a49525e6616379445420c84cbe57 100644
--- a/src/mol-plugin/skin/base/components/viewport.scss
+++ b/src/mol-plugin/skin/base/components/viewport.scss
@@ -27,6 +27,14 @@
     -webkit-tap-highlight-color: rgba(0,0,0,0);
     -webkit-touch-callout: none;
     touch-action: manipulation;
+
+    > canvas {
+        background-color: $default-background;
+        background-image: linear-gradient(45deg, lightgrey 25%, transparent 25%, transparent 75%, lightgrey 75%, lightgrey),
+        linear-gradient(45deg, lightgrey 25%, transparent 25%, transparent 75%, lightgrey 75%, lightgrey);
+        background-size: 60px 60px;
+        background-position: 0 0, 30px 30px;
+    }
 }
 
 .msp-viewport-controls {