javascript - Is it possible to enable unbounded number of renderers in THREE.js? -
in order avoid xy problem, let me explain i'm coming from. plot large number of waveforms stacked on top of each other using same time axis, using three.js. waveforms three.line's , implementing zoom/pan/scaling of these waveforms modifying view bounds of orthographic camera.
my initial attempt @ accomplishing lead me create multiple canvas elements fixed height, stacked on top of each other, , attach three.webglrenderer each canvas. worked perfectly, until tried scaling past 15 or waveforms, three.js gave me warning "too many active webgl contexts", , started deleting old contexts.
i feel decent practice, considering it's same technique applied here: http://threejs.org/examples/#webgl_multiple_canvases_grid
in example, 4 webglrenderers created, 1 each canvas.
so, possible override warning somehow, , create unbounded number of canvas elements, each own renderer?
aside:
i have considered using 1 scene , positioning waveforms accordingly within it, , using multiple cameras approach similar http://threejs.org/examples/#webgl_multiple_views.
the problems two-fold:
(1) lose ability dom-manipulate , attach key , mouse listeners on per-waveform basis.
(2) solution doesn't seem scale either. once renderer's height passes somewhere around 6000px height, starts enter type of corrupt state , part of scene doesn't appear, rest of content appearing stretched compensate.
thanks can help!
you can use 1 non-scrolling full window size canvas, , place holders divs wave forms. 1 renderer have 1 scene per waveform , call renderer.setviewport , renderer.setscissor location of each div before rendering each scene.
effectively this
renderer.enablescissortest( true ); scenes.foreach( function( scene ) { // element place holder want // draw scene var viewelement = scene.viewelement; // position relative page's viewport var rect = viewelement.getboundingclientrect(); // check if it's offscreen. if skip if ( rect.bottom < 0 || rect.top > renderer.domelement.clientheight || rect.right < 0 || rect.left > renderer.domelement.clientwidth ) { return; // it's off screen } // set viewport var width = rect.right - rect.left; var height = rect.bottom - rect.top; var left = rect.left; var bottom = renderer.domelement.clientheight - rect.bottom - 1; camera.aspect = width / height; camera.updateprojectionmatrix(); renderer.setviewport( left, bottom, width, height ); renderer.setscissor( left, bottom, width, height ); renderer.render( scene, camera ); } ); renderer.enablescissortest( false );
example:
var canvas; var scenes = [], camera, renderer, emptyscene; init(); animate(); function init() { canvas = document.getelementbyid( "c" ); camera = new three.perspectivecamera( 75, 1, 0.1, 100 ); camera.position.z = 1.5; var geometries = [ new three.boxgeometry( 1, 1, 1 ), new three.spheregeometry( 0.5, 12, 12 ), new three.dodecahedrongeometry( 0.5 ), new three.cylindergeometry( 0.5, 0.5, 1, 12 ), ]; var template = document.getelementbyid("template").text; var content = document.getelementbyid("content"); var emptyscene = new three.scene(); var numscenes = 100; ( var ii = 0; ii < numscenes; ++ii ) { var scene = new three.scene(); // make list item. var element = document.createelement( "div" ); element.innerhtml = template; element.classname = "list-item"; // element represents area // want render scene scene.element = element.queryselector(".scene"); content.appendchild(element); // add 1 random mesh each scene var geometry = geometries[ geometries.length * math.random() | 0 ]; var material = new three.meshlambertmaterial( { color: randcolor() } ); scene.add( new three.mesh( geometry, material ) ); light = new three.directionallight( 0xffffff ); light.position.set( 0.5, 0.8, 1 ); scene.add( light ); light = new three.directionallight( 0xffffff ); light.position.set( -0.5, -0.8, -1 ); scene.add( light ); scenes.push( scene ); } renderer = new three.webglrenderer( { canvas: canvas, antialias: true } ); renderer.setclearcolor( 0xffffff ); } function updatesize() { var width = canvas.clientwidth; var height = canvas.clientheight; if ( canvas.width !== width || canvas.height != height ) { renderer.setsize ( width, height, false ); } } function animate() { render(); requestanimationframe( animate ); } function render() { updatesize(); renderer.setclearcolor( 0xffffff ); renderer.clear( true ); renderer.setclearcolor( 0xe0e0e0 ); renderer.enablescissortest( true ); scenes.foreach( function( scene ) { // moves scene.children[0].rotation.x = date.now() * 0.00111; scene.children[0].rotation.z = date.now() * 0.001; // element place holder want // draw scene var element = scene.element; // position relative page's viewport var rect = element.getboundingclientrect(); // check if it's offscreen. if skip if ( rect.bottom < 0 || rect.top > renderer.domelement.clientheight || rect.right < 0 || rect.left > renderer.domelement.clientwidth ) { return; // it's off screen } // set viewport var width = rect.right - rect.left; var height = rect.bottom - rect.top; var left = rect.left; var bottom = renderer.domelement.clientheight - rect.bottom; camera.aspect = width / height; camera.updateprojectionmatrix(); renderer.setviewport( left, bottom, width, height ); renderer.setscissor( left, bottom, width, height ); renderer.render( scene, camera ); } ); renderer.enablescissortest( false ); } function rand( min, max ) { if ( max == undefined ) { max = min; min = 0; } return math.random() * ( max - min ) + min; } function randcolor() { var colors = [ rand( 256 ), rand ( 256 ), rand( 256 ) ]; colors[ math.random() * 3 | 0 ] = 255; return ( colors[0] << 16 ) | ( colors[1] << 8 ) | ( colors[2] << 0 ) ; }
* { box-sizing: border-box; -moz-box-sizing: border-box; } body { color: #000; font-family:monospace; font-size:13px; background-color: #fff; margin: 0px; } #content { position: absolute; top: 0px; width: 100%; z-index: 1; padding: 2em; } #c { position: fixed; left: 0px; width: 100%; height: 100%; } .list-item { margin: 1em; padding: 2em; display: -webkit-flex; display: flex; flex-direction: row; -webkit-flex-direction: row; } .list-item .scene { width: 200px; height: 200px; flex: 0 0 auto; -webkit-flex: 0 0 auto; } .list-item .description { font-family: sans-serif; font-size: large; padding-left: 2em; flex: 1 1 auto; -webkit-flex: 1 1 auto; } @media screen , (max-width : 600px) { #content { width: 100%; } .list-item { margin: 0.5em; padding: 0.5em; flex-direction: column; -webkit-flex-direction: column; } .list-item .description { padding-left: 0em; } }
<canvas id="c"></canvas> <div id="content"> </div> <script id="template" type="notjs"> <div class="scene"></div> <div class="description">some random text object, scene, whatever</div> </script> <script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
Comments
Post a Comment