【问题标题】:Make a scene a 3D texture in THREE.js (3D Render Targets)在 THREE.js(3D 渲染目标)中使场景成为 3D 纹理
【发布时间】:2014-08-09 06:54:56
【问题描述】:

我正在查看位于 here 的 THREE.js 示例,想知道如何防止渲染为纹理的场景“扁平化”。换句话说,当设置为WebGLRenderTarget 时,场景失去了有深度的错觉。

我到处查看,包括在 THREE.js 文档中,并没有发现这种功能的提及,可能是因为它会给用户的处理器带来不必要的大量负载(除了在非常特殊的情况下)。不过,也许这在纯 WebGL 中是可能的?

编辑: Downvoters - 为什么这个问题很糟糕?我已经对这个问题进行了大量研究,但是由于我是 WebGL 新手,所以我不能完全吐出毫无意义的代码......我该如何改进我的查询?

【问题讨论】:

  • (1) 为什么不修改示例并使用透视相机而不是正射相机,并将渲染目标用作平面而不是球体的纹理。这就是电影院里发生的事情。见stemkoski.github.io/Three.js/Camera-Texture.html (2) 这里不涉及不必要的“重大负载”。
  • 感谢您的回复! (1)我明白你在说什么(并且已经尝试过了),但这并不能阻止“扁平化”。在我引用的示例中,球体上的投影曲率有些误导。似乎 WebGL 只在投影表面上渲染 2D 错觉 (并且有充分的理由,这就是我提到处理器负载的原因)。当投影表面相对于相机旋转时,这种错觉消失了,您可以看出渲染的表面很像电影屏幕,而不是具有真实的 3 维深度的东西。
  • 你的例子确实给了我一个好主意,我可能很快就能回答我自己的问题。
  • 对不起,我不知道你在说什么......如果你无法回答自己的问题,也许其他人可以帮助你。

标签: javascript three.js webgl


【解决方案1】:

如果有意义的话,我认为您想使用屏幕空间投影而不是 UV 投影。以您的电视示例为例,屏幕上的 UV 点会随着您移动相机而发生变化。你想要一些保持不变的东西,即。无论你移动多少,你都在看同样的东西。我不确定在没有着色器的情况下如何做到这一点,但在片段着色器中你有 gl_FragCoord

【讨论】:

  • 我会对此进行一些实验并回复您。听起来它可能比我的解决方案效果更好。
【解决方案2】:

因为 THREE.js “扁平化”了它渲染的每个场景,所以只需要改变视角(相对于主场景的主摄像头)来保持渲染目标的深度错觉。这是一个可以做到这一点的东西的骨架:

var scene = new THREE.Scene(),
    rtScene = new THREE.Scene(),
    camera = new THREE.PerspectiveCamera( ..... ),
    rtCamera = new THREE.PerspectiveCamera( ..... ),
    rtCube = new THREE.Mesh(new THREE.CubeGeometry(1,1,1), new THREE.MeshSimpleMaterial({ color: 0x0000ff }),
    rtTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBFormat }),
    material = new THREE.MeshBasicMaterial({ map: rtTexture }),
    cube = new THREE.Mesh(new THREE.CubeGeometry(1,1,1), material);

function init() {
  //manipulate cameras
  //add any textures, lighting, etc

  rtScene.add( rtCube );
  scene.add( cube );
}

function update() {
   //some function of cube.rotation & cube.position
   //that changes the rtCamera rotation & position,
   //depending on the desired effect.
}

function animate() {
  requestAnimationFrame( animate );
  render();
}

function render() {
  renderer.clear();
  update();
  renderer.render( rtScene, rtCamera, rtTexture, true );
  renderer.render( scene, camera );
}

init();
animate();

我在我的代码中假设camera 将保持静止,而cube 围绕y 轴旋转。每个面都有自己的material 更新实例。每个人脸的 update() 函数是一堆三角函数,可以很容易地用余弦定律推导出来。一旦我的本地工作正常,我将发布一个 jsFiddle 示例。

【讨论】:

  • “换句话说,当设置为 WebGLRenderTarget 时,场景失去了具有深度的错觉。”这是什么意思?渲染目标可以在一端存储许多不同的内容,另一方面,每当您使用 three.js 时,您都会在屏幕上查看渲染目标的内容。你在说什么深度损失?
  • @pailhead 这正是重点,WebGL 从不渲染深度,只是一种幻觉(以 2D 的方式绘制事物,使它们看起来像是在 3D 中)。问题在于,对于任何使用 WebGLRenderTarget 的对象与主场景的相机不对齐,渲染目标看起来像电视屏幕,而不像具有实际深度的东西(出于显而易见的原因 - 你不 总是想要渲染目标的深度)。要解决此问题,您只需在 rtScene 内操作相机以保持深度。
  • 该链接确实帮助我更多地了解了 THREE 相机的工作原理,谢谢!我的问题涉及与金字塔视场错觉类似的错觉,因此与本次讨论有关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-19
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 2015-12-25
  • 1970-01-01
相关资源
最近更新 更多