Three.js - Multiple Views

Subscribe Send me a message home page tags


#three.js  #multiple views  #multiple camera 

It's quite easy to set up multiple views/displays and there are different ways to achieve this. The Three.js website provides an example of multiple views. If we inspect the page source code, we can see that only one canvas is used. So it's an efficient solution.

Another way to achieve the same effect is to use multiple canvas. Suppose we want to create two independent displays. We will need

Here is the demo:

HTML File:

1
2
3
4
5
6
7
8
9
10
11
<script type="module">
    import {main} from "/<path-to-js-file>/demo_multi_divs.js";
    main();
</script>

<div id="demo_multi_divs">
    <div style="height: 5vh"></div>
    <div id="demo_multi_divs_display_1" style="margin:auto;text-align:center;"></div>
    <div style="height: 5vh"></div>
    <div id="demo_multi_divs_display_2" style="margin:auto;text-align:center;"></div>
</div>

Javascript File:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

import * as THREE from "/three/build/three.module.js";
import { OrbitControls } from "/three/examples/jsm/controls/OrbitControls.js";


function rand(min, max) {
    if (max === undefined) {
        max = min;
        min = 0;
    }
    return min + (max - min) * Math.random();
}

function randomColor() {
    return <code>hsl(${rand(360) | 0}, ${rand(50, 100) | 0}%, 50%)</code>;
}


function createDefaultRender(elementId) {
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth / 4, window.innerHeight / 4 );
    document.getElementById(elementId).appendChild(renderer.domElement);
    renderer.domElement.style.border = "1px solid orange";
    renderer.domElement.style.margin = "auto";
    return renderer;
}

function createDefaultCamera() {
    const fov = 75;
    const aspect = window.innerWidth / window.innerHeight;
    const near = 0.1;
    const far = 200;
    return new THREE.PerspectiveCamera(fov, aspect, near, far);
}


function main() {
    const renderer1 = createDefaultRender("demo_multi_divs_display_1");
    const camera1 = createDefaultCamera();
    camera1.position.z = 30;

    const renderer2 = createDefaultRender("demo_multi_divs_display_2");
    const camera2 = createDefaultCamera();
    camera2.position.z = 30;



    // Create an orbit control.
    const controls1 = new OrbitControls( camera1, renderer1.domElement );
    const controls2 = new OrbitControls( camera2, renderer2.domElement );


    // Create the scene
    const scene = new THREE.Scene();
    scene.background = new THREE.Color('white');

    // Create a camera pole
    const cameraPole1 = new THREE.Object3D();
    const cameraPole2 = new THREE.Object3D();

    scene.add(cameraPole1);
    scene.add(cameraPole2);

    cameraPole1.add(camera1);
    cameraPole2.add(camera2);


    // Add a light source to the camera
    const color = 0xFFFFFF;
    const intensity = 1;
    const light1 = new THREE.DirectionalLight(color, intensity);
    const light2 = new THREE.DirectionalLight(color, intensity);
    light1.position.set(0, 0, 0);
    light2.position.set(0, 0, 0);
    camera1.add(light1);
    camera2.add(light2);

    // Define the geometry of the displayed boxes.
    const boxWidth = 1;
    const boxHeight = 1;
    const boxDepth = 1;
    const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);

    function makeInstance(geometry, color) {
        const material = new THREE.MeshPhongMaterial({color});

        const cube = new THREE.Mesh(geometry, material);
        scene.add(cube);

        cube.position.set(rand(-20, 20), rand(-20, 20), rand(-20, 20));
        cube.rotation.set(rand(Math.PI), rand(Math.PI), 0);
        cube.scale.set(rand(3, 6), rand(3, 6), rand(3, 6));

        return cube;
    }

    // Create a list of cubes
    const N = 10;
    const cubes = [];

    for (var i = 0; i < N; ++i) {
        makeInstance(geometry, randomColor());
    }

    function updateAll(scene, renderer, camera, controls) {

        const canvas = renderer.domElement;
        camera.aspect = canvas.clientWidth / canvas.clientHeight;
        camera.updateProjectionMatrix();

        controls.update();
        renderer.render(scene, camera);
    }

    function render(time) {
        time *= 0.001;

        // Rotate the camera pold. Recall that the camera is attached to the cameral pole and there is a light source
        // attached to the camera.
        cameraPole1.rotation.y = time * 0.5;
        cameraPole2.rotation.y = time * -0.5;

        cubes.forEach((cube, ndx) => {
                const speed = 1 + ndx * .1;
                const rot = time * speed;
                cube.rotation.x = rot;
                cube.rotation.y = rot;
                });

        updateAll(scene, renderer1, camera1, controls1);
        updateAll(scene, renderer2, camera2, controls2);
        requestAnimationFrame(render);
    }

    requestAnimationFrame(render);
}

export {
    main
}

----- END -----

Welcome to join reddit self-learning community.
Send me a message Subscribe to blog updates

Want some fun stuff?

/static/shopping_demo.png