【发布时间】:2018-09-08 21:13:08
【问题描述】:
我已经编写了代码来渲染包含像投影仪一样工作的灯光的场景。但是它们有很多(在单个着色器中可以用固定数量的灯光来表示更多)。所以现在我通过创建一个自定义着色器并为每个灯光渲染一次场景来渲染它。每次通过片段着色器确定该光的贡献,并且混合器将该贡献添加到后缓冲区。我发现在three.js中设置这真的很尴尬。我找不到像这样进行多次通过的方法,因为不同的通过需要不同的材料和不同的几何形状。我必须通过多个场景来做到这一点。那里的问题是我不能有一个在多个场景中的object3d(如果我错了,请纠正我)。所以我需要创建对象的副本——它所在的每个场景都有一个。这一切都很快开始看起来很hacky。太特别了,好像和 VR Rendering 等各种 Three.js 框架特性不兼容。每个灯光都需要阴影,但我没有每个灯光的阴影缓冲区的内存,所以它交替渲染灯光的阴影缓冲区,然后是该灯光的累积阶段,然后是下一个灯光的阴影缓冲区,然后蓄电池下一个灯,等等。
我宁愿以更“三个.js”的方式进行设置。我似乎正在编写 hack on hack 以使其正常工作,每次都放弃另一个无法与我的多通道技术一起正常工作的 three.js 框架功能。但我的所作所为似乎并没有那么不寻常。
令我惊讶的是,我想不出一种方法来设置一个多通道场景来执行此来回渲染和累积。我的第二个惊喜是我创建的 Object3D 不喜欢同时添加到多个场景中,因此我必须为每个想要进入的场景创建每个对象的副本,以防止它们的状态互相干扰。
那么有没有办法更好地渲染这种多通道累积场景呢?同样,我将其描述为一个场景,其中 > 单个着色器通道中允许的最大灯光数量,因此它们的贡献需要交替渲染(阴影缓冲区),然后在多个通道中累加累加。这些灯的工作原理类似于投影图像的典型电影放映机(而不是统一的纯色光源)。
我怎样才能像这样进行多通道渲染,同时仍然利用良好的框架功能,例如用于 VR 的立体渲染和自动阴影缓冲区创建?
这是一个简化的 sn-p,演示了所涉及的场景:
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 内容。
还有没有更“三.js”的方式?
【问题讨论】:
-
THREE.EffectsComposer 用于进行多通道渲染,但仅用于后期处理。老实说,您正在做的是相当低级的事情......可能值得使用较低级别的框架,或者从渲染器中获取 .gl 上下文并对其进行自己的处理。还有一个名为 .onbeforerender 的对象回调,您可以在场景管道确定您的对象将被渲染之前将函数插入到修改参数中。您也许可以在那里进行材质交换/逻辑。