首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文本交织的多个场景

文本交织的多个场景
EN

Stack Overflow用户
提问于 2019-02-22 17:39:16
回答 1查看 70关注 0票数 1

我正在考虑将three.js用于我的三维模型可视化Sphinx扩展。扩展允许您在文档中轻松地可视化交互式3D对象,但它是当前,它使用的是一个未维护的过期库。

three.js库有大量的示例。其中有一个引起了我的注意:WebGL多元素文本的例子。

这是一个很好的例子,因为它满足了我对Sphinx扩展的需求:

  • 它允许一个页面中有多个场景。
  • 所有场景共享相同的WebGLRenderer,因此可以将许多场景放在一个页面中。
  • 它允许将文本和场景交织在一起。

现在,它只有一个警告: CPU/GPU消耗。即使当您没有滚动或与3D可视化交互时,CPU/GPU似乎很忙。

起初,我认为这可能是由于每个场景的动画。我不需要我的扩展动画,只需要交互,所以我决定删除它们并强制在场景用户交互上重新渲染:

代码语言:javascript
复制
diff --git a/examples/webgl_multiple_elements_text.html b/examples/webgl_multiple_elements_text.html
index 289e4935a..e9fe7e087 100644
--- a/examples/webgl_multiple_elements_text.html
+++ b/examples/webgl_multiple_elements_text.html
@@ -196,6 +196,7 @@
                    scene.userData.camera = camera;

                    var controls = new THREE.OrbitControls( camera, views[ n ] );
+                   controls.addEventListener( 'change', render );
                    scene.userData.controls = controls;

                    scenes.push( scene );
@@ -223,7 +224,6 @@
            function animate() {

                render();
-               requestAnimationFrame( animate );

            }

通过这个非常简单的改变:

  • 动画停止了,我不介意
  • CPU/GPU的消耗也停止了,这正是我想要的。
  • 场景仍然是交互式的(即:你可以移动摄像机),当然,如果我主动与它们交互,我不介意使用CPU/GPU。

然而,现在有一个问题:如果您试图向下滚动页面,场景将不会与文本一起滚动。

我怎么才能解决这个问题?

考虑因素:

  • 目标是在用户不滚动或不与场景交互的情况下使用"0“CPU/GPU (毕竟,它被用于文档页面,用户大部分时间都将在文档页面中阅读)。
  • 如果滚动不会对CPU/GPU产生明显的影响,那就太好了;这甚至可能吗?还是我们需要重新绘制所有的场景,同时滚动,就像我们需要做的时候,与他们互动?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-02-23 06:35:49

scroll事件中添加一个要调用呈现的队列

代码语言:javascript
复制
window.addEventListerner('scroll', queueRenderIfNotQueued);

let renderQueued = false;
function render() {
  renderQueued = false;
  ...
}

function queueRenderIfNotQueued() {
  if (!renderQueued) {
    renderQueued = true;
    requestAnimationFrame(render);
  }
}

您也可能希望在调整大小时呈现。

代码语言:javascript
复制
window.addEventListerner('resize', queueRenderIfNotQueued);

下面是一个从此页此页的想法中修改的示例

代码语言:javascript
复制
'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    alpha: true
  });

  const sceneElements = [];

  function addScene(elem, fn) {
    sceneElements.push({
      elem,
      fn
    });
  }

  function makeScene(elem) {
    const scene = new THREE.Scene();

    const fov = 45;
    const aspect = 2; // the canvas default
    const near = 0.1;
    const far = 5;
    const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
    camera.position.set(0, 1, 2);
    camera.lookAt(0, 0, 0);

    const controls = new THREE.OrbitControls(camera, elem);
    controls.enableZoom = false;
    controls.enablePan = false;

    {
      const color = 0xFFFFFF;
      const intensity = 1;
      const light = new THREE.DirectionalLight(color, intensity);
      light.position.set(-1, 2, 4);
      scene.add(light);
    }

    const geometry = new THREE.BoxBufferGeometry(1, 1, 1);
    const material = new THREE.MeshPhongMaterial({color:'red'});
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
    
    function render(rect) {
      camera.aspect = rect.width / rect.height;
      camera.updateProjectionMatrix();
      renderer.render(scene, camera);    
    }
    
    function renderWithBounds() {
      const rect = elem.getBoundingClientRect();
      const {
        left,
        right,
        top,
        bottom,
        width,
        height
      } = rect;

      renderer.setViewport(left, top, width, height);
      renderer.setScissor(left, top, width, height);
      render(rect);
    }
    
    controls.addEventListener('change', renderWithBounds);

    addScene(elem, render);
  }

  [...document.querySelectorAll('.diagram')].forEach(makeScene);
 

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  const clearColor = new THREE.Color('#000');

  let renderQueued = false;
  function render() {
    renderQueued = false;
    resizeRendererToDisplaySize(renderer);

    renderer.setScissorTest(false);
    renderer.setClearColor(clearColor, 0);
    renderer.clear(true, true);
    renderer.setScissorTest(true);

    const transform = `translateY(${window.scrollY}px)`;
    renderer.domElement.style.transform = transform;

    for (const {
        elem,
        fn
      } of sceneElements) {
      // get the viewport relative position opf this element
      const rect = elem.getBoundingClientRect();
      const {
        left,
        right,
        top,
        bottom,
        width,
        height
      } = rect;

      const isOffscreen =
        bottom < 0 ||
        top > renderer.domElement.clientHeight ||
        right < 0 ||
        left > renderer.domElement.clientWidth;

      if (!isOffscreen) {
        renderer.setViewport(left, top, width, height);
        renderer.setScissor(left, top, width, height);

        fn(rect);
      }
    }
  }

  function queueRenderIfNotQueued() {
    if (!renderQueued) {
      renderQueued = true;
      requestAnimationFrame(render);
    }
  }
  
  queueRenderIfNotQueued();
  window.addEventListener('scroll', queueRenderIfNotQueued);
  window.addEventListener('resize', queueRenderIfNotQueued);
}

main();
代码语言:javascript
复制
#c {
  position: absolute;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  display: block;
  z-index: -1;
}

.diagram {
  display: inline-block;
  width: 5em;
  height: 3em;
}

.left {
  float: left;
  margin-right: .25em;
}

.right {
  float: right;
  margin-left: .25em;
}

p {
  margin: 1em auto;
  max-width: 500px;
  font-size: xx-large;
}
代码语言:javascript
复制
<canvas id="c"></canvas>
<p>
  <span class="diagram left"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
  <span class="diagram right"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
  <span class="diagram left"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
  <span class="diagram right"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
  <span class="diagram left"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
  <span class="diagram right"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>

<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/js/controls/OrbitControls.js"></script>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54832421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档