是否可以在 THREE.js 中启用无限数量的渲染器?

2023-11-29

为了避免 XY 问题,让我解释一下我来自哪里。 我想使用 THREE.js 使用同一时间轴绘制大量堆叠在一起的波形。波形只是三线,我通过修改正交相机的视图范围来实现这些波形的缩放/平移/缩放。

我最初尝试完成此任务,导致我创建多个具有固定高度的画布元素,彼此堆叠,并将 THREE.WebGLRenderer 附加到每个画布。 这工作得很好,直到我尝试将其缩放到超过 15 个左右的波形,其中 THREE.js 向我发出警告“活动 webgl 上下文太多”,并开始删除旧上下文。

我觉得这是一个不错的做法,考虑到这里应用的是相同的技术:http://twojs.org/examples/#webgl_multiple_canvases_grid

在此示例中,创建了 4 个 WebGLRenderer,每个画布一个。

那么,是否可以以某种方式覆盖此警告,并创建无限数量的画布元素,每个元素都有自己的渲染器?

ASIDE:

我考虑过使用一个场景并在其中相应地定位波形,并使用多个摄像机,其方法类似于http://trijs.org/examples/#webgl_multiple_views.

问题有两个:

(1) 我失去了在每个波形的基础上进行 dom 操作和轻松附加键和鼠标侦听器的能力。

(2) 该解决方案似乎也无法扩展。一旦渲染器的高度超过 6000px 左右的高度,它就会开始进入某种类型的损坏状态,并且部分场景不会出现,而其余内容会出现拉伸以进行补偿。

感谢任何能提供帮助的人!


您可以使用一张非滚动全窗口大小的画布,并为您的波形使用占位符 DIV。然后使用 1 个渲染器,每个波形有 1 个场景并调用renderer.setViewport and renderer.setScissor渲染每个场景之前每个 div 的位置。

有效地像这样

renderer.setScissorTest( true );
scenes.forEach( function( scene ) {

  // get the element that is a place holder for where we want to
  // draw the scene
  var viewElement = scene.viewElement;

  // get its position relative to the page's viewport
  var rect = viewElement.getBoundingClientRect();

  // check if it's offscreen. If so skip it
  if ( rect.bottom < 0 || rect.top  > renderer.domElement.clientHeight ||
     rect.right  < 0 || rect.left > renderer.domElement.clientWidth ) {
    return;  // it's off screen
  }

  // set the viewport
  var width  = rect.right - rect.left;
  var height = rect.bottom - rect.top;
  var left   = rect.left;
  var top    = rect.top;

  renderer.setViewport( left, top, width, height );
  renderer.setScissor( left, top, width, height );

  camera.aspect = width / height;
  camera.updateProjectionMatrix();

  renderer.render( scene, camera );
} );
renderer.setScissorTest( 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;

  for ( var ii =  0; ii < numScenes; ++ii ) {

    var scene = new THREE.Scene();

    // make a list item.
    var element = document.createElement( "div" );
    element.innerHTML = template;
    element.className = "list-item";

    // Look up the element that represents the area
    // we want to render the scene
    scene.element = element.querySelector(".scene");
    content.appendChild(element);

    // add one random mesh to 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();
  
  canvas.style.transform = `translateY(${window.scrollY}px`;

  renderer.setClearColor( 0xFFFFFF );
  renderer.clear( true );
  renderer.setClearColor( 0xE0E0E0 );

  renderer.setScissorTest( true );
  scenes.forEach( function( scene ) {
    // so something moves
    scene.children[0].rotation.x = Date.now() * 0.00111;
    scene.children[0].rotation.z = Date.now() * 0.001;

    // get the element that is a place holder for where we want to
    // draw the scene
    var element = scene.element;

    // get its position relative to the page's viewport
    var rect = element.getBoundingClientRect();

    // check if it's offscreen. If so skip it
    if ( rect.bottom < 0 || rect.top  > renderer.domElement.clientHeight ||
       rect.right  < 0 || rect.left > renderer.domElement.clientWidth ) {
      return;  // it's off screen
    }

    // set the viewport
    var width  = rect.right - rect.left;
    var height = rect.bottom - rect.top;
    var left   = rect.left;
    var top    = rect.top;

    renderer.setViewport( left, top, width, height );
    renderer.setScissor( left, top, width, height );

    camera.aspect = width / height;
    camera.updateProjectionMatrix();

    renderer.render( scene, camera );

  } );
  renderer.setScissorTest( 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: 0;
}


#content {
  position: absolute;
  top: 0; width: 100%;
  z-index: 1;
  padding: 2em;
}

#c {
  position: absolute;
  left: 0;
  top: 0;
  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 only screen and (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 about this object, scene, whatever</div>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>

Update:

这里最初的解决方案使用了画布position: fixed意味着画布没有滚动。下面的新解决方案将其更改为position: absolute; top: 0然后设置画布的每一帧的变换

  canvas.style.transform = `translateY(${window.scrollY}px`;

这样做的优点是,即使我们无法每帧更新画布,画布也会随着页面滚动,直到我们有机会更新它。这使得滚动保持同步。

您可以比较旧的解决方案 to the 新的解决方案。两者都设置为仅每 4 帧渲染一次,以夸大问题。上下滚动它们,差异应该很明显。

更新2:

还有一个解决方案是虚拟化 WebGL 上下文在其中,您创建一个离屏 WebGL 上下文,然后进行修补,以便 WebGL 的其他用途获得一个虚拟 WebGL 上下文,该上下文在单个共享的实际 WebGL 上下文之上进行模拟。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在 THREE.js 中启用无限数量的渲染器? 的相关文章

  • 使用 ReactJS 旋转图像预览

    我正在尝试使用 ReactJS 旋转图像的预览 因此 我首先允许渲染预览的上传功能 然后在用户点击上传之前 我希望他们可以选择根据自己的喜好旋转图像 这是我用来预览图像的 class ImageUpload extends React Co
  • Jquery - 如何替换div中的一个单词?

    我有一个从其他位置复制的 div 我需要更改其中的一个单词 这是 HTML div class dealer addy 8726 N Royal Ln br Irving TX 75063 br email protected cdn cg
  • 如何使用 angular2 在客户端生成 rsa 密钥对?

    我需要知道如何使用 angular2 在客户端生成 rsa 密钥对 我需要生成私钥 公钥对并将私钥保存到数据库中 并希望在客户端内使用公钥 我怎样才能实现这个 我找到了这个https www npmjs com package genera
  • Browserify 与 jQuery >= 2 生成“jQuery 需要一个带有文档的窗口”

    我正在使用 browserify 使用 CommonJS 样式的依赖项来捆绑我的前端 javascript 例如 我有 require jquery dist jquery v2 1 0 beta2 require underscore
  • 如何对页面的某个部分进行实时更新?

    我需要刷新页面的各个部分 以便在有新数据时进行更新 我该怎么办 使用jquery 例子 是的 jQuery 非常适合这个 查看这些方法 http api jquery com category ajax http api jquery co
  • Puppeteer 登录 Instagram

    我正在尝试使用 Puppeteer 登录 Instagram 但不知何故无法登录 你能帮助我吗 这是我正在使用的链接 https www instagram com accounts login https www instagram co
  • Google 闭包编译器使用 WebStorm

    我喜欢用谷歌闭包编译器 https developers google com closure compiler in WebStorm https www jetbrains com webstorm 我已经通过 npm 下载了它 npm
  • 闭包和异步 Node.js 函数

    All 尝试了解 Node js 上下文中的闭包 异步调用 我有以下代码 timer setInterval pollOID 1000 function pollOID for channel in channels session get
  • Angularjs 使用 ng-init 为 ng-model 赋值

    您好 我有以下问题 看起来很简单并且应该有效 但事实并非如此 在我的代码中我输入了
  • Array.from 的时间复杂度

    时间复杂度是多少Array from 例如 const set new Set set add car set add cat set add dog console log Array from set time complexity o
  • 链接index.html client.js 和 server.js

    我从 Node js 开始 我的第一个程序已经遇到了问题 下面是我正在使用的代码 索引 html
  • Chrome 扩展程序导致 DOM 闪烁,该扩展程序会在页面加载之前删除 DOM 元素

    我正在编写一个 chrome 扩展 我想在页面加载之前删除内容 例如this http tech blog tomchambers me 2016 01 13 How to write a simple page rewriting Chr
  • 未处理的 Promise 拒绝:push.on 不是函数

    我正在使用离子2 我得到这个打字稿error当尝试设置推送通知时 我从教程中复制了此示例代码 因此预计它可以工作 我一定有什么问题 任何想法请 Unhandled Promise rejection push on is not a fun
  • Firebase 停止监听 onAuthStateChanged

    从版本 3 0 0 开始 我很难删除身份验证状态更改侦听器 要根据文档启动侦听器 firebase auth onAuthStateChanged function user handle it 但是 我在文档中找不到任何涉及删除身份验证状
  • up() 和 down() 与 Ext.getCmp()

    我很困惑我需要在 up down 和 Ext getCmp ID 之间使用哪一个作为 grep 对象 对我来说 定义对象的 ID 并通过 Ext getCmp ID 检索对象更容易 而且代码看起来更干净 例如 console log thi
  • Python 中 Javascript 的 reduce()、map() 和 filter() 的等价物是什么?

    Python 的等价物是什么 Javascript function wordParts currentPart lastPart return currentPart lastPart word Che mis try console l
  • Bootstrap 多选限制问题

    我使用创建了一个多选下拉列表引导多选 http davidstutz github io bootstrap multiselect 我需要在选项选择中设置一个限制 这里我将其设置为 5 如果达到限制 我只需禁用其他选择选项 它就可以完美工
  • ag-Grid 中的行格式

    我们需要有条件地将行文本设置为粗体 目前它仅适用于单个单元格 但我们需要在所有列单元格上应用文本粗体 应用格式设置后 isBold 列必须隐藏 删除 此列仅用于格式化 如何应用文本缩进 10px isBold 列包含真实值的第一列的 有可能
  • 当 JavaScript 抛出异常时不要停止它

    我正在使用 JavaScript 编写一个 Windows 边栏小工具 现在我想捕获所有 JavaScript 异常并将其记录到文本文件中 一个问题是 当任何一行抛出异常时 下一行将不会被执行 是否可以自动捕获异常 以便执行以下 JavaS
  • Jquery 脉动改变颜色或图像

    我正在尝试使用 jquery 脉动代码让 div 改变颜色 但我希望它从红色变为黑色 但我听说要做到这一点 你必须下载某个插件 所以我希望它脉动为图片 到目前为止我有这两个代码 img src 36 gif alt width 105 he

随机推荐

  • 将轴名称添加到图表中 C#

    我正在与winforms使用 C 我使用图表 我想在代码中设置 X 轴和 Y 轴的标题 我试过 chart1 chartarea 0 axisX title xxx 但它不起作用 我不知道为什么 我正在使用网络上的图表控件 并通过以下方式设
  • 为什么Oracle监听器和数据库服务没有运行?

    我刚刚开始接触 Red Hat Linux 7 2 和 Oracle 12c 因此 我上周末致力于尝试看看是否可以在 RHEL 7 2 上支持 Oracle 12c 最后 是的 我能够在 RHEL 7 2 VM 上运行 Oracle 但并非
  • 如何使用nodejs获取mongodb单个文档的大小(以字节为单位)?

    我正在使用 db coll findOne 获取文档 我想使用仅具有 mongo 本地驱动程序的 NodeJS 获取文档的大小 以字节为单位 这可能吗 可以使用BSON 这是 mongodb 驱动程序的依赖项 var bson requir
  • 在 Os.Rename 中强制覆盖

    如果另一个文件已经存在 是否可以强制重命名 os rename 来覆盖另一个文件 例如 在下面的代码中 如果文件 Tests csv 已存在 它将被 Tests txt 文件替换 也已重命名为 Tests csv os rename C U
  • 如何将数组列表放入列表框中

    因此 我在一项作业上需要帮助 并且我已经尝试解决它一个多星期了 但我需要帮助将数组列表放入列表框中 That s what the GUI should look like in the end all the information ha
  • 从 Swing GUI 编译并运行 Java 代码

    我正在用 Java Swing 构建一个 GUI 并且必须从中执行 Java 代码 为了测试简单的代码 比如用 Java 打印 HelloWorld 就可以了 我看过论坛问题 我只知道我必须调用操作系统 我使用的是Windows7 来执行该
  • 初始化网格时,同一 DataGridView 列中的控件不呈现

    好坏 我在 DataGridView 列中托管不同的控件 当我在初始化网格的同时添加控件时 控件显示为文本框 不好 如果我在 DataGridView 初始化后添加控件 控件会正确呈现 好 public Form1 InitializeCo
  • jQuery 在 for 循环中动态增加变量名称

    是否可以将 i 添加到 for 循环内的 var 中 如果语法错误 它看起来像下面的代码 for i 1 i lt countProjects i var test i otherVar something Thanks 为此最好使用数组
  • 反射 - 获取 lambda 表达式内的方法调用列表

    我正在尝试找到一种方法来获取 C 3 5 中 lambda 表达式内的方法调用列表 例如 在下面的代码中 我想使用方法 LookAtThis Action a 来分析 lambda 表达式的内容 换句话说 我希望 LookAtThis 返回
  • 如何使用散景后端控制全息视图中的(活动)工具

    如何控制在某个环境中使用 激活哪些工具holoviews情节与bokeh后端 我见过这个答案 但仅此而已adds一个新的活跃工具 它不会阻止任何其他工具 例如平移 处于活动状态 对于一个具体的例子 假设我只想要悬停工具 我会尝试这样做 im
  • 项目的选择器不是另一个项目的后代

    给定下面的 HTML 您将如何选择所有不是 itemcontainer 后代的 name s 类似于 group header name not 源自 itemcontainer 我知道这可以通过 jQuery 或添加其他类很容易地完成 但
  • cv2.getOptimalNewCameraMatrix 在某些数据集上返回 [0,0,0,0] 的 ROI

    我正在使用 OpenCV 2 x 开发一个 Python 程序 下面是我的代码摘录 该代码在已捕获和保存的文件列表上运行 所有图像都是80 x 60 8 位灰度图像 我得到的最好的投资回报率是 1 6 73 49 对于一台相机 但我的另一台
  • 在Java中将base64字符串转换为图像

    我有一个通过 JSON 字符串发送给我的图像 我想在我的 Android 应用程序中将该字符串转换为图像 然后显示该图像 JSON 字符串如下所示 data image png base64 iVBORw0KGgoAAAANSUhEUgAA
  • WinAPI C++ 客户端在读取之前检测匿名管道上的写入

    我正在编写一个 C Windows 客户端控制台应用程序 该应用程序从 STDIN 上的匿名管道读取数据 我希望能够按如下方式使用我的程序 echo input text here my app exe 并在应用程序中使用通过管道输入的文本
  • 为什么我的 JLabel 没有显示

    我正在调用此方法 称为检查我的抽象类之一 但由于某种原因 我添加到 JPanel 面板 的 JLabel 问题 没有显示 为什么会出现这种情况 任何解释 我都使用重绘和验证方法 但仍然没有显示任何内容 您遇到的问题是您阻塞了事件调度线程 阻
  • 了解 Java 中的一个大公司项目 [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 理解java大公司项目的最好方法是什么 关于这个主题 有一个不错的播客 采访 Dave Thomas 务实的程序员 Dave here 他称之为 软件考古学 由于许多不同的原因 组织经常失
  • 将强类型属性名称作为参数传递

    我有一个收藏IEnumerable
  • mvc4 中 Global.asax 中的会话超时重定向

    我试图检测会话何时结束 然后在我的全局 asax 文件中完成此操作后将用户重定向到主页 我正在使用我发现的下面的代码here 全局 asax protected void Session Start if Context Session n
  • Razor 页面中 foreach 循环内的表单

    我有一个标准的 Razor 页面 其中列出了我的数据库中的所有订单 它的编码非常标准 IList
  • 是否可以在 THREE.js 中启用无限数量的渲染器?

    为了避免 XY 问题 让我解释一下我来自哪里 我想使用 THREE js 使用同一时间轴绘制大量堆叠在一起的波形 波形只是三线 我通过修改正交相机的视图范围来实现这些波形的缩放 平移 缩放 我最初尝试完成此任务 导致我创建多个具有固定高度的