diff --git a/package.json b/package.json
index 2d4d54773..2b6d7335a 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,8 @@
   "dependencies": {
     "htmlparser2": "3.9.0",
     "memoizee": "0.3.10",
-    "promise": "7.1.1"
+    "promise": "7.1.1",
+    "scratch-render-webgl": "git+https://github.com/LLK/scratch-render-webgl.git"
   },
   "devDependencies": {
     "eslint": "2.7.0",
diff --git a/playground/index.html b/playground/index.html
index 82535807b..e11d72c82 100644
--- a/playground/index.html
+++ b/playground/index.html
@@ -13,9 +13,14 @@
         <button id="greenflag">Green flag</button>
         <button id="stopall">Stop</button>
         <p>
+            <a id="renderexplorer-link" href="#">Renderer</a><br />
             <a id="threadexplorer-link" href="#">VM Threads</a><br />
             <a id="blockexplorer-link" href="#">VM Block Representation</a>
         </p>
+        <div id="tab-renderexplorer">
+            Render<br />
+            <canvas id="scratch-stage" style="width: 480px; height: 360px;"></canvas>
+        </div>
         <div id="tab-threadexplorer">
             Thread explorer
             <pre id="threadexplorer"></pre>
@@ -240,6 +245,54 @@
               </value>
             </block>
         </category>
+        <category name="Motion">
+            <block type="motion_movesteps">
+             <value name="STEPS">
+               <shadow type="math_number">
+                 <field name="NUM">10</field>
+               </shadow>
+             </value>
+           </block>
+           <block type="motion_turnright">
+             <value name="DEGREES">
+               <shadow type="math_number">
+                 <field name="NUM">15</field>
+               </shadow>
+             </value>
+           </block>
+           <block type="motion_turnleft">
+             <value name="DEGREES">
+               <shadow type="math_number">
+                 <field name="NUM">15</field>
+               </shadow>
+             </value>
+           </block>
+           <block type="motion_pointindirection">
+             <value name="DIRECTION">
+               <shadow type="math_number">
+                 <field name="NUM">90</field>
+               </shadow>
+             </value>
+           </block>
+           <block type="motion_pointtowards">
+             <value name="TOWARDS">
+               <shadow type="motion_pointtowards_menu">
+               </shadow>
+             </value>
+           </block>
+           <block type="motion_gotoxy">
+             <value name="X">
+               <shadow type="math_number">
+                 <field name="NUM">0</field>
+               </shadow>
+             </value>
+             <value name="Y">
+               <shadow type="math_number">
+                 <field name="NUM">0</field>
+               </shadow>
+             </value>
+           </block>
+        </category>
     </xml>
 
     <!-- Syntax highlighter -->
@@ -249,6 +302,8 @@
     <script src="../node_modules/scratch-blocks/blockly_compressed_vertical.js"></script>
     <script src="../node_modules/scratch-blocks/blocks_compressed.js"></script>
     <script src="../node_modules/scratch-blocks/blocks_compressed_vertical.js"></script>
+    <!-- Renderer -->
+    <script src="../node_modules/scratch-render-webgl/build/render-webgl.js"></script>
     <!-- VM Worker -->
     <script src="../vm.worker.js"></script>
     <!-- Playground -->
diff --git a/playground/playground.css b/playground/playground.css
index 451a7cad5..a15e1d81c 100644
--- a/playground/playground.css
+++ b/playground/playground.css
@@ -32,6 +32,6 @@ a {
     font-size: 10pt;
 }
 
-#tab-blockexplorer {
+#tab-blockexplorer, #tab-threadexplorer {
     display: none;
 }
diff --git a/playground/playground.js b/playground/playground.js
index be683ceb7..220549c9f 100644
--- a/playground/playground.js
+++ b/playground/playground.js
@@ -3,6 +3,10 @@ window.onload = function() {
     var vm = new window.VirtualMachine();
     window.vm = vm;
 
+    var canvas = document.getElementById('scratch-stage');
+    window.renderer = new window.RenderWebGLLocal(canvas);
+    window.renderer.connectWorker(window.vm.vmWorker);
+
     var toolbox = document.getElementById('toolbox');
     var workspace = window.Blockly.inject('blocks', {
         toolbox: toolbox,
@@ -85,16 +89,25 @@ window.onload = function() {
 
     var tabBlockExplorer = document.getElementById('tab-blockexplorer');
     var tabThreadExplorer = document.getElementById('tab-threadexplorer');
+    var tabRenderExplorer = document.getElementById('tab-renderexplorer');
 
     // Handlers to show different explorers.
     document.getElementById('threadexplorer-link').addEventListener('click',
         function () {
             tabBlockExplorer.style.display = 'none';
+            tabRenderExplorer.style.display = 'none';
             tabThreadExplorer.style.display = 'block';
         });
     document.getElementById('blockexplorer-link').addEventListener('click',
         function () {
             tabBlockExplorer.style.display = 'block';
+            tabRenderExplorer.style.display = 'none';
+            tabThreadExplorer.style.display = 'none';
+        });
+    document.getElementById('renderexplorer-link').addEventListener('click',
+        function () {
+            tabBlockExplorer.style.display = 'none';
+            tabRenderExplorer.style.display = 'block';
             tabThreadExplorer.style.display = 'none';
         });
 };
diff --git a/src/blocks/scratch3_motion.js b/src/blocks/scratch3_motion.js
new file mode 100644
index 000000000..4fcc3b056
--- /dev/null
+++ b/src/blocks/scratch3_motion.js
@@ -0,0 +1,31 @@
+function Scratch3MotionBlocks(runtime) {
+    /**
+     * The runtime instantiating this block package.
+     * @type {Runtime}
+     */
+    this.runtime = runtime;
+}
+
+/**
+ * Retrieve the block primitives implemented by this package.
+ * @return {Object.<string, Function>} Mapping of opcode to Function.
+ */
+Scratch3MotionBlocks.prototype.getPrimitives = function() {
+    return {
+        'motion_gotoxy': this.goToXY,
+        'motion_turnright': this.turnRight
+    };
+};
+
+Scratch3MotionBlocks.prototype.goToXY = function (args, util) {
+    util.target.setXY(args.X, args.Y);
+};
+
+Scratch3MotionBlocks.prototype.turnRight = function (args, util) {
+    if (args.DEGREES !== args.DEGREES) {
+        throw "Bad degrees" + args.DEGREES;
+    }
+    util.target.setDirection(args.DEGREES + util.target.direction);
+};
+
+module.exports = Scratch3MotionBlocks;
diff --git a/src/blocks/scratch3_operators.js b/src/blocks/scratch3_operators.js
index 75077061c..86cb50350 100644
--- a/src/blocks/scratch3_operators.js
+++ b/src/blocks/scratch3_operators.js
@@ -31,7 +31,12 @@ Scratch3OperatorsBlocks.prototype.getPrimitives = function() {
 };
 
 Scratch3OperatorsBlocks.prototype.number = function (args) {
-    return Number(args.NUM);
+    var num = Number(args.NUM);
+    if (num !== num) {
+        // NaN
+        return 0;
+    }
+    return num;
 };
 
 Scratch3OperatorsBlocks.prototype.text = function (args) {
diff --git a/src/engine/execute.js b/src/engine/execute.js
index 001178d56..aa413a76b 100644
--- a/src/engine/execute.js
+++ b/src/engine/execute.js
@@ -70,7 +70,8 @@ var execute = function (sequencer, thread) {
         stackFrame: currentStackFrame.executionContext,
         startSubstack: function (substackNum) {
             sequencer.stepToSubstack(thread, substackNum);
-        }
+        },
+        target: target
     });
 
     // Deal with any reported value.
diff --git a/src/engine/runtime.js b/src/engine/runtime.js
index a0db919ae..c51800cdb 100644
--- a/src/engine/runtime.js
+++ b/src/engine/runtime.js
@@ -6,6 +6,7 @@ var util = require('util');
 var defaultBlockPackages = {
     'scratch3_control': require('../blocks/scratch3_control'),
     'scratch3_event': require('../blocks/scratch3_event'),
+    'scratch3_motion': require('../blocks/scratch3_motion'),
     'scratch3_operators': require('../blocks/scratch3_operators')
 };
 
@@ -257,6 +258,9 @@ Runtime.prototype._setInterval = function(fcn, interval) {
 Runtime.prototype.start = function () {
     this._setInterval(function() {
         this._step();
+        if (self.renderer) {
+            self.renderer.draw();
+        }
     }.bind(this), Runtime.THREAD_STEP_INTERVAL);
 };
 
diff --git a/src/index.js b/src/index.js
index 08109c0a9..fff9c52db 100644
--- a/src/index.js
+++ b/src/index.js
@@ -24,6 +24,7 @@ function VirtualMachine () {
     // @todo support multiple targets/sprites.
     // This is just a demo/example.
     var exampleSprite = new Sprite();
+    exampleSprite.createClone();
     var exampleTargets = [exampleSprite.clones[0]];
     instance.exampleSprite = exampleSprite;
     instance.runtime = new Runtime(exampleTargets);
@@ -96,6 +97,10 @@ VirtualMachine.prototype.getPlaygroundData = function () {
  * from a worker environment.
  */
 if (ENV_WORKER) {
+    self.importScripts(
+        './node_modules/scratch-render-webgl/build/render-webgl-worker.js'
+    );
+    self.renderer = new self.RenderWebGLWorker();
     self.vmInstance = new VirtualMachine();
     self.onmessage = function (e) {
         var messageData = e.data;
@@ -123,7 +128,11 @@ if (ENV_WORKER) {
             });
             break;
         default:
-            throw 'Unknown method' + messageData.method;
+            if (e.data.id == 'RendererConnected') {
+                //initRenderWorker();
+            }
+            self.renderer.onmessage(e);
+            break;
         }
     };
     // Bind runtime's emitted events to postmessages.
diff --git a/src/sprites/clone.js b/src/sprites/clone.js
index afbd56f1c..f4f99abbe 100644
--- a/src/sprites/clone.js
+++ b/src/sprites/clone.js
@@ -3,9 +3,19 @@ var Target = require('../engine/target');
 
 function Clone(spriteBlocks) {
     Target.call(this, spriteBlocks);
+    this.drawableID = null;
+    this.initDrawable();
 }
 util.inherits(Clone, Target);
 
+Clone.prototype.initDrawable = function () {
+    var createPromise = self.renderer.createDrawable();
+    var instance = this;
+    createPromise.then(function (id) {
+        instance.drawableID = id;
+    });
+};
+
 // Clone-level properties
 Clone.prototype.x = 0;
 
@@ -13,4 +23,19 @@ Clone.prototype.y = 0;
 
 Clone.prototype.direction = 90;
 
+Clone.prototype.setXY = function (x, y) {
+    this.x = x;
+    this.y = y;
+    self.renderer.updateDrawableProperties(this.drawableID, {
+        position: [this.x, this.y]
+    });
+};
+
+Clone.prototype.setDirection = function (direction) {
+    this.direction = direction;
+    self.renderer.updateDrawableProperties(this.drawableID, {
+        direction: this.direction
+    });
+};
+
 module.exports = Clone;
diff --git a/src/sprites/sprite.js b/src/sprites/sprite.js
index 1608b0571..1ec25b3ba 100644
--- a/src/sprites/sprite.js
+++ b/src/sprites/sprite.js
@@ -9,9 +9,12 @@ function Sprite (blocks) {
     }
     this.blocks = blocks;
     this.clones = [];
-
-    // Initial single clone with the shared blocks.
-    this.clones.push(new Clone(this.blocks));
 }
 
+Sprite.prototype.createClone = function () {
+    var newClone = new Clone(this.blocks);
+    this.clones.push(newClone);
+    return newClone;
+};
+
 module.exports = Sprite;