diff --git a/src/RenderWebGL.js b/src/RenderWebGL.js
index 56c7c49d..09cfc2e1 100644
--- a/src/RenderWebGL.js
+++ b/src/RenderWebGL.js
@@ -133,6 +133,13 @@ class RenderWebGL extends EventEmitter {
             throw new Error('Could not get WebGL context: this browser or environment may not support WebGL.');
         }
 
+        this._mystery = {
+            modeActive: false,
+            mouseMoveListener: null,
+            bufferInfo: null,
+            mouseCoords: [0, 0]
+        };
+
         /** @type {RenderWebGL.UseGpuModes} */
         this._useGpuMode = RenderWebGL.UseGpuModes.Automatic;
 
@@ -223,6 +230,12 @@ class RenderWebGL extends EventEmitter {
         const pixelRatio = window.devicePixelRatio || 1;
         this._gl.canvas.width = pixelsWide * pixelRatio;
         this._gl.canvas.height = pixelsTall * pixelRatio;
+
+        if (this._mystery.modeActive && this._mystery.bufferInfo) {
+            twgl.resizeFramebufferInfo(this._gl, this._mystery.bufferInfo, [
+                {format: this._gl.RGBA}
+            ], pixelsWide * pixelRatio, pixelsTall * pixelRatio);
+        }
     }
 
     /**
@@ -615,7 +628,43 @@ class RenderWebGL extends EventEmitter {
         gl.clearColor.apply(gl, this._backgroundColor);
         gl.clear(gl.COLOR_BUFFER_BIT);
 
-        this._drawThese(this._drawList, ShaderManager.DRAW_MODE.default, this._projection);
+        let drawList = this._drawList;
+        if (this._mystery.modeActive) {
+            drawList = drawList.slice(1);
+            twgl.bindFramebufferInfo(gl, this._mystery.bufferInfo);
+            gl.clearColor(0, 0, 0, 0);
+            gl.clear(gl.COLOR_BUFFER_BIT);
+        }
+        this._drawThese(drawList, ShaderManager.DRAW_MODE.default, this._projection);
+
+        if (this._mystery.modeActive) {
+            // draw all layers except for the bottom layer onto the mystery buffer
+            twgl.bindFramebufferInfo(gl, null);
+            gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
+            this._drawThese([this._drawList[0]], ShaderManager.DRAW_MODE.default, this._projection);
+
+            this._doExitDrawRegion();
+            const newShader = this._shaderManager.getShader(ShaderManager.DRAW_MODE.mystery, 0);
+            this._regionId = newShader;
+
+            // draw mystery buffer to main buffer
+            gl.useProgram(newShader.program);
+            twgl.setBuffersAndAttributes(gl, newShader, this._bufferInfo);
+            const uniforms = {
+                u_projectionMatrix: this._projection,
+                u_modelMatrix: twgl.m4.identity(),
+                u_skin: this._mystery.bufferInfo.attachments[0],
+                u_mousePosition: this._mystery.mouseCoords
+            };
+
+            twgl.setTextureParameters(
+                gl, uniforms.u_skin, {minMag: gl.LINEAR}
+            );
+
+            twgl.setUniforms(newShader, uniforms);
+            twgl.drawBufferInfo(gl, this._bufferInfo, gl.TRIANGLES);
+        }
+
         if (this._snapshotCallbacks.length > 0) {
             const snapshot = gl.canvas.toDataURL();
             this._snapshotCallbacks.forEach(cb => cb(snapshot));
@@ -1909,6 +1958,32 @@ class RenderWebGL extends EventEmitter {
         return dst;
     }
 
+    setMysteryMode (enableMysteryMode) {
+        this._mystery.modeActive = enableMysteryMode;
+
+        if (enableMysteryMode) {
+            this._mystery.bufferInfo = twgl.createFramebufferInfo(
+                this._gl,
+                [{format: this._gl.RGBA}],
+                this._gl.drawingBufferWidth,
+                this._gl.drawingBufferHeight
+            );
+
+            this._mystery.mouseMoveListener = event => {
+                const rect = this.canvas.getBoundingClientRect();
+                this._mystery.mouseCoords[0] = (event.clientX - rect.left) / rect.width;
+                this._mystery.mouseCoords[1] = (event.clientY - rect.top) / rect.height;
+            };
+
+            document.addEventListener('mousemove', this._mystery.mouseMoveListener);
+        } else {
+            if (this._mystery.bufferInfo) {
+                this._gl.deleteFramebuffer(this._mystery.bufferInfo.framebuffer);
+            }
+            document.removeEventListener('mousemove', this._mystery.mouseMoveListener);
+        }
+    }
+
     /**
      * @callback RenderWebGL#snapshotCallback
      * @param {string} dataURI Data URI of the snapshot of the renderer
diff --git a/src/ShaderManager.js b/src/ShaderManager.js
index a71ef2d2..22cd236f 100644
--- a/src/ShaderManager.js
+++ b/src/ShaderManager.js
@@ -171,7 +171,9 @@ ShaderManager.DRAW_MODE = {
     /**
      * Sample a "texture" to draw a line with caps.
      */
-    lineSample: 'lineSample'
+    lineSample: 'lineSample',
+
+    mystery: 'mystery'
 };
 
 module.exports = ShaderManager;
diff --git a/src/shaders/sprite.frag b/src/shaders/sprite.frag
index 13fe19de..b4b1d6ce 100644
--- a/src/shaders/sprite.frag
+++ b/src/shaders/sprite.frag
@@ -39,6 +39,10 @@ uniform float u_capScale;
 uniform float u_aliasAmount;
 #endif // DRAW_MODE_lineSample
 
+#ifdef DRAW_MODE_mystery
+uniform vec2 u_mousePosition;
+#endif
+
 uniform sampler2D u_skin;
 
 varying vec2 v_texCoord;
@@ -112,6 +116,15 @@ void main()
 	#ifndef DRAW_MODE_lineSample
 	vec2 texcoord0 = v_texCoord;
 
+	#ifdef DRAW_MODE_mystery
+	vec2 mysteryCoord = texcoord0;
+	vec2 offset = vec2(u_mousePosition.x, 1.0 - u_mousePosition.y);
+	mysteryCoord -= offset;
+	const float SCALE_FACTOR = 0.85;
+	mysteryCoord *= vec2(SCALE_FACTOR, SCALE_FACTOR);
+	mysteryCoord += offset;
+	#endif
+
 	#ifdef ENABLE_mosaic
 	texcoord0 = fract(u_mosaic * texcoord0);
 	#endif // ENABLE_mosaic
@@ -155,6 +168,21 @@ void main()
 
 	gl_FragColor = texture2D(u_skin, texcoord0);
 
+	#ifdef DRAW_MODE_mystery
+	const vec4 SHADOW_COLOR = vec4(0.0, 0.0, 0.0, 0.5);
+	const float SHADOW_BLUR = 0.0025;
+
+	float shadowSample1 = texture2D(u_skin, mysteryCoord + vec2(SHADOW_BLUR, SHADOW_BLUR)).a;
+	float shadowSample2 = texture2D(u_skin, mysteryCoord + vec2(-SHADOW_BLUR, SHADOW_BLUR)).a;
+	float shadowSample3 = texture2D(u_skin, mysteryCoord + vec2(SHADOW_BLUR, -SHADOW_BLUR)).a;
+	float shadowSample4 = texture2D(u_skin, mysteryCoord + vec2(-SHADOW_BLUR, -SHADOW_BLUR)).a;
+
+	float shadowAlpha = (shadowSample1 + shadowSample2 + shadowSample3 + shadowSample4) * 0.25;
+
+	vec4 shadow = SHADOW_COLOR * shadowAlpha;
+	gl_FragColor = gl_FragColor + (shadow * (1.0 - gl_FragColor.a));
+	#endif
+
 	#if defined(ENABLE_color) || defined(ENABLE_brightness)
 	// Divide premultiplied alpha values for proper color processing
 	// Add epsilon to avoid dividing by 0 for fully transparent pixels
diff --git a/src/shaders/sprite.vert b/src/shaders/sprite.vert
index a9bbe150..8bb133cf 100644
--- a/src/shaders/sprite.vert
+++ b/src/shaders/sprite.vert
@@ -15,7 +15,9 @@ void main() {
     vec2 position = a_position;
     position.y = clamp(position.y * u_positionScalar, -0.5, 0.5);
     gl_Position = u_projectionMatrix * u_modelMatrix * vec4(position, 0, 1);
-    #else
+    #elif defined(DRAW_MODE_mystery)
+	gl_Position = vec4(a_position * vec2(-2.0, 2.0), 0.0, 1.0);
+	#else
     gl_Position = u_projectionMatrix * u_modelMatrix * vec4(a_position, 0, 1);
     #endif
     v_texCoord = a_texCoord;