three.js中的多遍累积渲染

时间:2018-09-08 21:13:09

标签: three.js rendering

我已经编写了代码来渲染包含像投影机一样工作的灯光的场景。但是它们很多(单个着色器中可以用固定数量的灯光来表示)。因此,现在我通过创建自定义着色器并为每个光源渲染一次场景来渲染此场景。片段着色器每次通过都会确定该光的贡献,而混合器会将这一贡献添加到后缓冲中。我发现在Three.js中进行设置确实很尴尬。我找不到这样的多次加工方法,因为不同的加工需要不同的材料和不同的几何形状。我不得不通过多个场景来做到这一点。那里的问题是我不能有多个场景中的object3d(如果我错了,请纠正我)。因此,我需要创建对象的副本-为其中的每个场景创建一个副本。所有这些都开始看起来真的很笨拙。它是如此特殊,以致与VR渲染之类的three.js框架功能不兼容。每个光源都需要阴影,但是我没有足够的内存来存储每个光源的阴影缓冲区,因此它在为该光源渲染阴影缓冲区,然后为该光源渲染累积阶段,然后为下一个光源的阴影缓冲区,然后蓄电池,下一盏灯,等等。

我宁愿以一种更“ three.js”的方式进行设置。我似乎是一堆又一遍地写这篇文章,以使这项工作正常进行,每次都放弃了另一种Three.js框架功能,该功能无法与我的多遍技术结合使用。但这似乎与我所做的事情不同寻常。

主要让我惊讶的是,我无法找到一种方法来建立多遍场景来回渲染和累积。我的第二个惊喜是我创建的Object3D不喜欢同时添加到多个场景中,因此我必须为其要进入的每个场景创建每个对象的副本,以防止它们的状态发生变化。互相干扰。

有没有一种方法可以更好地渲染这种多遍累积场景?再次,我将其描述为一个场景,其中>单个着色器通道中允许的最大灯光数量,因此需要交替渲染(阴影缓冲区)它们的贡献,然后在多个通道中累加累积。灯光的工作方式类似于投射图像的典型电影放映机(而不是均匀的单色光源)。

如何进行这样的多遍渲染,并且仍然利用诸如VR立体渲染和自动阴影缓冲区创建之类的良好框架内容呢?

这是一个简化的片段,演示了涉及的场景:

  renderer.render(this.environment.scene, camera, null);
  for (let i = 0, ii = this.projectors.length; i < ii; ++i) {
    let projector = this.projectors[i];
    renderer.setClearColor(0x000000, 1);
    renderer.clearTarget(this.shadowRenderTarget, true, true, false);
    renderer.render(projector.object3D.depthScene, projector.object3D.depthCamera, this.shadowRenderTarget);
    renderer.render(projector.object3D.scene, camera);
  }

  renderer.render(this.foreground.scene, camera, null);

有一个场景会渲染来自环境的光照(用普通光照完成),然后每个投影机都有一个场景,该场景会计算出该投影机的阴影图,然后添加每个投影机的光贡献,然后出现一个“前景”场景,其中包含叠加层和UI内容。

还有更多的“ three.js”方式吗?

1 个答案:

答案 0 :(得分:1)

不幸的是,我认为答案是no

  

我宁愿以一种更“ three.js”的方式进行设置。为了使这项工作正常进行,我似乎是一堆又一遍地写着,

欢迎来到three.js开发的世界:)

场景图

您不能有一个节点属于多个父节点。我相信三个人也不允许您这样做:

const myPos = new THREE.Vector3()

myMesh_layer0.position = myPos
myMesh_layer1.position = myPos

它不适用于欧拉,四元数或矩阵。

在多个场景中管理矩阵更新也很棘手。

Three.js方式

除非您开始破解内核,否则没有办法进行“黑客破解”。

请注意,这是2018年,但是将Three.js包含到您的Web应用程序中的官方方法是通过<src>标签。

这是一个很好的示例,它可能是一个更好的主意,而不是the three.js way,而不是modern javascript way,即使用导入,npm安装等。

Three.js也没有强大的内核,它使您可以灵活地处理周围的代码。相当混乱和混乱,只暴露了数量有限的钩子,使您可以编写所需的效果。

三个通常与它的示例混为一谈,如果您选择一个随机的示例,它将以Three.js的方式编写,但至少到今天为止还没有最好的javascript /编码实践。

您经常会发现大型的单片文件,这会从分手中受益。

我相信仍然无法将示例作为模块导入。

看一下材料扩展示例,然后考虑是否要在项目中应用该模式。

您可能会遇到更多的痛点,但这足以说明three.js way可能并不总是理想的。

补救措施

很少。我花了一年多的时间尝试推onBeforeRenderonAfterRender钩子。它似乎很有用,并且可以进行一些重构,但是必须先取消另一个功能。

在那一年中迭代了另一个功能,仅解决了一个示例,直到很明显onBeforeRender可以解决两个示例,并允许更多的功能为止。

不幸的是,这似乎也是three.js的方式。由于基础如此之大,并包含许多示例,因此更有可能有人尝试优化单个示例,然后尝试找到用于重构整个示例的通用模式。

您可以在github上提出问题,但是要争辩像这样的通用性将非常困难。您最有可能必须编写一些代码作为建议。

这很快就会变得很麻烦,因为它可能会被拒绝,忽略,或者可能要求您提供示例或重构现有示例。

您提到您的骇客无法使用VR等三种功能。我认为这是三个问题,至少在过去的几年中,VR一直是开发的重点,但是从来没有解决核心问题。

好消息是,三个模块比以往任何时候都更加模块化,因此您可以分叉项目并调整所需的零件。与之相关的三个问题可能会移到更高的层次,例如,如果您在渲染器中发现一些耦合,从而使分支难以同步,那么比特定项目的整个目标要容易解释。