Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Improved webgl_worker_offscreencanvas example.
  • Loading branch information
mrdoob committed Dec 1, 2018
1 parent f1d7a14 commit d58d00b
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 113 deletions.
38 changes: 38 additions & 0 deletions examples/js/offscreen/jank.js
@@ -0,0 +1,38 @@
var interval = null;

var button = document.getElementById( 'button' );
button.addEventListener( 'click', function () {

if ( interval === null ) {

interval = setInterval( jank, 1000 / 60 );

button.textContent = 'STOP JANK';

} else {

clearInterval( interval );
interval = null;

button.textContent = 'START JANK';
result.textContent = '';

}

} );

var result = document.getElementById( 'result' );

function jank() {

var number = 0;

for ( var i = 0; i < 10000000; i ++ ) {

number += Math.random();

}

result.textContent = number;

}
9 changes: 9 additions & 0 deletions examples/js/offscreen/offscreen.js
@@ -0,0 +1,9 @@
self.importScripts( '../../../build/three.js' );
self.importScripts( './scene.js' );

self.onmessage = function ( message ) {

var data = message.data;
init( data.drawingSurface, data.width, data.height, data.pixelRatio, data.path );

};
77 changes: 77 additions & 0 deletions examples/js/offscreen/scene.js
@@ -0,0 +1,77 @@
var camera, scene, renderer, group;

function init( canvas, width, height, pixelRatio, path ) {

camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 );
camera.position.z = 200;

scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x444466, 100, 400 );
scene.background = new THREE.Color( 0x444466 );

group = new THREE.Group();
scene.add( group );

// we don't use ImageLoader since it has a DOM dependency (HTML5 image element)

var loader = new THREE.ImageBitmapLoader().setPath( path );
loader.load( 'textures/matcaps/matcap-porcelain-white.jpg', function ( imageBitmap ) {

var texture = new THREE.CanvasTexture( imageBitmap );

var geometry = new THREE.IcosahedronBufferGeometry( 5, 3 );
var materials = [
new THREE.MeshMatcapMaterial( { color: 0xaa24df, matcap: texture } ),
new THREE.MeshMatcapMaterial( { color: 0x605d90, matcap: texture } ),
new THREE.MeshMatcapMaterial( { color: 0xe04a3f, matcap: texture } ),
new THREE.MeshMatcapMaterial( { color: 0xe30456, matcap: texture } )
];

for ( var i = 0; i < 100; i ++ ) {

var material = materials[ i % materials.length ];
var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = random() * 200 - 100;
mesh.position.y = random() * 200 - 100;
mesh.position.z = random() * 200 - 100;
mesh.scale.setScalar( random() + 1 );
group.add( mesh );

}

renderer = new THREE.WebGLRenderer( { antialias: true, canvas: canvas } );
renderer.setPixelRatio( pixelRatio );
renderer.setSize( width, height, false );

animate();

} );

}

function animate() {

// group.rotation.x = Date.now() / 4000;
group.rotation.y = - Date.now() / 4000;

renderer.render( scene, camera );

if ( self.requestAnimationFrame ) {

self.requestAnimationFrame( animate );

} else {

// Firefox

}

}

// PRNG

var seed = 1;
function random() {
var x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
76 changes: 0 additions & 76 deletions examples/js/workers/OffscreenCanvas.js

This file was deleted.

99 changes: 62 additions & 37 deletions examples/webgl_worker_offscreencanvas.html
Expand Up @@ -5,76 +5,101 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
html, body {
height: 100%;
}

body {
background:#000000;
padding:0;
margin:0;
font-weight: bold;
overflow:hidden;
background: #ffffff;
padding: 0;
margin: 0;
font-family: Monospace;
font-size: 13px;
overflow: hidden;
}

#info {
position: absolute;
top: 0px;
width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
color: #000000;
margin: 6px 0px;
text-align: center;
}

#message {
color: #ff0000;
font-size:14px;
display: none;
}

#message > a {
color: #ff0000;
}

a { color: #ffffff; }
#container {
width: 100%;
height: calc(100% - 80px);
}

#ui {
margin-top: 8px;
height: 80px;
text-align: center;
}
#button {
border: 0;
padding: 4px 6px;
background: #dddddd;
outline: none;
}
</style>
<script src="js/WebGL.js"></script>
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> offscreen canvas<br/><br/>
three.js runs in a worker and produces asynchronously frames for the canvas element in the main thread. <br/>
This is an <a href="https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas" target="_blank" rel="noopener noreferrer"> experimental feature</a>!
<a href="https://threejs.org" target="_blank" rel="noopener noreferrer">three.js</a> - offscreen canvas (<a href="https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas" target="_blank" rel="noopener noreferrer">about</a>)<br/>
<p id="message">Your browser does not support OffscreenCanvas. Check the browser support <a href="https://caniuse.com/#feat=offscreencanvas" target="_blank" rel="noopener noreferrer">here</a></p>
</div>

<canvas id="canvas" style="width: 100%; height: 100%"></canvas>
</body>
<script>
<div id="container">
<canvas id="canvas1" style="width: 50%; height: 100%"></canvas><canvas id="canvas2" style="width: 50%; height: 100%"></canvas>
</div>
<div id="ui">
<button id="button">START JANK</button><br/>
<span id="result"></span>
</div>

if ( WEBGL.isWebGLAvailable() === false ) {
<script src="../build/three.js"></script>
<script src="js/offscreen/scene.js"></script>
<script src="js/offscreen/jank.js"></script>
<script>

document.body.appendChild( WEBGL.getWebGLErrorMessage() );
// onscreen

}
var width = canvas1.clientWidth;
var height = canvas1.clientHeight;
var pixelRatio = window.devicePixelRatio;

var canvas = document.getElementById( 'canvas' );
init( canvas1, width, height, pixelRatio, './' );

if ( canvas.transferControlToOffscreen !== undefined ) {
// offscreen

var offscreen = canvas.transferControlToOffscreen();
var worker = new Worker( 'js/workers/OffscreenCanvas.js' );
if ( 'transferControlToOffscreen' in canvas2 ) {

worker.postMessage( {
drawingSurface: offscreen,
width: window.innerWidth,
height: window.innerHeight,
pixelRatio: window.devicePixelRatio
}, [ offscreen ] ); // transfer
var offscreen = canvas2.transferControlToOffscreen();
var worker = new Worker( 'js/offscreen/offscreen.js' );
worker.postMessage( {
drawingSurface: offscreen,
width: canvas2.clientWidth,
height: canvas2.clientHeight,
pixelRatio: window.devicePixelRatio,
path: '../../'
}, [ offscreen ] );

} else {
} else {

document.getElementById( 'message' ).style.display = 'block';
document.getElementById( 'message' ).style.display = 'block';

}
}

</script>
</script>
</body>
</html>

2 comments on commit d58d00b

@Mugen87
Copy link
Collaborator

@Mugen87 Mugen87 commented on d58d00b Dec 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new "jank" feature is really cool! Clearly demonstrates the advantages of rendering within a worker 👍

@mrdoob
Copy link
Owner Author

@mrdoob mrdoob commented on d58d00b Dec 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it for Chrome Dev Summit's keynote 🤓
https://www.youtube.com/watch?v=zPHyxvPT0gg&t=958

Please sign in to comment.