Как сделать два canvas для одной сцены в three.js?

Ссылка скопирована
1 ответ

Собственно сабж. Есть одна сцена, которую нужно показывать в двух разных местах dom. Рендер привязан к событию change orbitcontrols, т.е. рендерит при повороте камеры вокруг объекта. Выводится все в указанный WebGLRenderer канвас.
Точно такая же сцена требуется в другом месте, и не хотелось бы дублировать код и создавать ту же сцену для другого канвас.
Какие есть способы дублировать всё на два канвас? Первое что пришло в голову простое дублирование канвас drawImage, а рендерить сцену посредством слушателя канвас mousemove при зажатой ЛКМ.

Но может есть какой то встроенный функционал в threejs или более правильные и производительные варианты?

Дополнительно:

А не пробовал просто два рендерера создавать и в них передавать те же данные?

  • Kentavr16, нет не пробовал, думал найти решение чтобы просто выводить кадры в нужный канвас без доп сцен и рендеров. Просто доп рендер скорее всего даст доп нагрузку, а этого не хотелось бы. Сцена то по сути одна ничего не меняется просто нужно выводить на два канваса, и пробросить слушатели для орбитконтролс.
  • Kentavr16, спасибо за вариант если ничего лучшего не найду буду использовать его.
  • Ответы:

    Точно такая же сцена требуется в другом месте, и не хотелось бы дублировать код и создавать ту же сцену для другого канвас

    Сцену дублировать не обязательно. WebGLRenderer не умеет рендерить в несколько мест одновременно, но можно иметь одну сцену и много рендереров, каждый из которых будет рендерить ее в свой канвас. Это работает.

    Если посмотреть с другой стороны, то возможно, что вам не нужны два канваса. Это может звучать странно, но тем не менее. Пользователь же все равно видит только один экран информации. Можно иметь один канвас на весь экран, и в нем рендерить сцены в какие-то его участки. Там есть такой функционал у рендерера, называется "ножницы" (scissor). Его можно использовать как раз для таких задач. Есть хороший пример в документации.

    Но если делать именно 100% дублирование, то оба этих варианта будут не самыми толковыми с точки зрения производительности. В лоб скопировать уже готовое содержимое канваса в другой через drawImage должно быть проще, чем рендерить всю сцену еще раз. Поэтому решение, которое пришло вам в голову - очень даже ничего в текущем контексте. Хотя и выглядит топорно.

    • да доки видел там канвас на весь экран, тут ситуация такая что нужны два отдельных канваса на разных страницах onepage сервиса. Гугл выдает зачастую тоже самое что в доках, поэтому пока идея такая: сделать два орбитконтролс для двух канвас и дублировать основной канвас в слушателе change вторичного канвас при помощи drawImage.
      Просто думал может я что то упустил и есть способ транслировать рендер в два канвас из коробки или не задокументированным способом, но видимо нет.
      Спасибо за ответ!
    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Стас DB Ответ

    Для создания двух canvas для одной сцены в three.js необходимо использовать два отдельных экземпляра класса THREE.WebGLRenderer и два отдельных экземпляра класса THREE.Scene.

    Пример кода на JavaScript с использованием three.js:

    // Создаем сцену
    var scene1 = new THREE.Scene();
    var scene2 = new THREE.Scene();
     
    // Создаем два рендерера
    var renderer1 = new THREE.WebGLRenderer();
    var renderer2 = new THREE.WebGLRenderer();
     
    // Устанавливаем размеры канваса для каждого рендерера
    renderer1.setSize( window.innerWidth / 2, window.innerHeight );
    renderer2.setSize( window.innerWidth / 2, window.innerHeight );
     
    // Добавляем канвас элементы на страницу
    document.body.appendChild( renderer1.domElement );
    document.body.appendChild( renderer2.domElement );
     
    // Создаем камеру и добавляем ее к сцене
    var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
    scene1.add( camera );
    scene2.add( camera );
     
    // Создаем объекты и добавляем их к сценам
    var geometry = new THREE.BoxGeometry();
    var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
    var cube = new THREE.Mesh( geometry, material );
    scene1.add( cube );
     
    var geometry2 = new THREE.SphereGeometry();
    var material2 = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
    var sphere = new THREE.Mesh( geometry2, material2 );
    scene2.add( sphere );
     
    // Создаем функцию анимации
    function animate() {
        requestAnimationFrame( animate );
     
        // Вращение объектов в сцене 1
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
     
        // Вращение объектов в сцене 2
        sphere.rotation.x += 0.01;
        sphere.rotation.y += 0.01;
     
        // Рендеринг сцены 1
        renderer1.render( scene1, camera );
     
        // Рендеринг сцены 2
        renderer2.render( scene2, camera );
    }
     
    animate();

    // Создаем сцену var scene1 = new THREE.Scene(); var scene2 = new THREE.Scene(); // Создаем два рендерера var renderer1 = new THREE.WebGLRenderer(); var renderer2 = new THREE.WebGLRenderer(); // Устанавливаем размеры канваса для каждого рендерера renderer1.setSize( window.innerWidth / 2, window.innerHeight ); renderer2.setSize( window.innerWidth / 2, window.innerHeight ); // Добавляем канвас элементы на страницу document.body.appendChild( renderer1.domElement ); document.body.appendChild( renderer2.domElement ); // Создаем камеру и добавляем ее к сцене var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); scene1.add( camera ); scene2.add( camera ); // Создаем объекты и добавляем их к сценам var geometry = new THREE.BoxGeometry(); var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); var cube = new THREE.Mesh( geometry, material ); scene1.add( cube ); var geometry2 = new THREE.SphereGeometry(); var material2 = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); var sphere = new THREE.Mesh( geometry2, material2 ); scene2.add( sphere ); // Создаем функцию анимации function animate() { requestAnimationFrame( animate ); // Вращение объектов в сцене 1 cube.rotation.x += 0.01; cube.rotation.y += 0.01; // Вращение объектов в сцене 2 sphere.rotation.x += 0.01; sphere.rotation.y += 0.01; // Рендеринг сцены 1 renderer1.render( scene1, camera ); // Рендеринг сцены 2 renderer2.render( scene2, camera ); } animate();

    В данном примере создаются две сцены (scene1 и scene2), два рендерера (renderer1 и renderer2) и два канваса для отображения сцен. Каждая сцена содержит свои объекты, которые могут быть анимированы независимо друг от друга. Анимация происходит в функции animate(), где происходит вращение объектов в каждой сцене.

    Таким образом, можно создать два canvas для одной сцены в three.js, используя отдельные рендереры и сцены для каждого из них.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно