【译】快速贴士:如何用Three.js渲染到纹理

默认情况下,你用Three.js所渲染的所有内容都会呈现在屏幕上。毕竟,如果你不能看到的话,渲染的重点何在?事实证明很重要的一点:数据在捕获之前被发送到屏幕上(从而丢失)。
这使得它更容易应用被处理后的效果,例如色彩校正,颜色转换或模糊并且它对着色效果也很有用。
这种技术被称为渲染到纹理或渲染到帧缓冲器,最终的结果将存储在一个纹理,随后可以渲染到屏幕上。本快速贴士中,我会告诉你怎么做,然后通过渲染一个立方体移动到另一个移动的立方体表面的实例来引导你。
注: 本教程是假设你对three.js有一些基础的熟悉。如果没有,请参考如何学习Three.js进行游戏开发。
基本实现
这里有很多的例子关于如何做到这一点,它们趋向于嵌入在更复杂的效果中。以下是你所需要把东西渲染到Three.js纹理之上的最低限度:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // @author Omar Shehata. 2016. // We are loading the Three.js library from the CDN here: //// This is the basic scene setup //// var scene = new THREE.Scene(); var width, height = window.innerWidth, window.innerHeight; var camera = new THREE.PerspectiveCamera( 70, width/height, 1, 1000 ); var renderer = new THREE.WebGLRenderer(); renderer.setSize( width,height); document.body.appendChild( renderer.domElement ); //// This is where we create our off-screen render target //// // Create a different scene to hold our buffer objects var bufferScene = new THREE.Scene(); // Create the texture that will store our result var bufferTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter}); //// // Add anything you want to render/capture in bufferScene here // //// function render() { requestAnimationFrame( render ); // Render onto our off-screen texture renderer.render(bufferScene, camera, bufferTexture); // Finally, draw to the screen renderer.render( scene, camera ); } render(); // Render everything! |
我们首先做好基本的场景设置。然后,我们创建另一个场景bufferScene;我们加入到这个场景的任何对象都将被吸引到我们屏幕外的目标而不是到屏幕上。
然后,我们创建bufferTexture,这是一个 WebGLRenderTarget类。这是Three.js用来让我们渲染到其他东西上而不是屏幕上的东西。
最后,我们要告诉Three.js要渲染的bufferScene:
1 | renderer.render(bufferScene, camera, bufferTexture); |
这就像渲染一个标准场景,不一样的是我们指定了第三个参数:渲染目标。
所以步骤是:
- 创建一个场景来保存你的对象。
- 创建一个纹理来保存你要渲染的东西。
- 把你的场景渲染到你的纹理上。
实际上,这就是我们要做的。不过这并不是很令人兴奋,因为我们什么都看不到。即使你添加新的东西到bufferScene,你仍然看不到任何东西;这是因为你需要以某种方式把你创建的纹理渲染到你的主场景中。以下是如何做到这一点的例子。
用法示例
我们将在场景中创建一个立方体,把它绘制到一个纹理,然后使用它作为一个新的立方体的纹理!
1. 启动一个基本的场景
这里我们有一个红色旋转的立方体和背景为蓝色的基本场景。这里没有什么特殊的事情发生,不过你可以通过切换演示图中的CSS或JS 标签来检查代码。
示例:You can fork and edit this on CodePen.2. 渲染当前场景到纹理
现在我们要行动并把它渲染到一个纹理。我们需要做的就是像上述实现的那样创建一个bufferScene,并把我们的对象添加进去。
示例:You can fork and edit this on CodePen.
如果做的正确,我们将不会看到任何东西,因为现在没有东西呈现在屏幕上。相反,我们的场景被渲染且保存在bufferTexture。
3. 渲染一个立方体纹理
bufferTexture 与其他纹理没有区别。我们可以简单的创建一个新对象并把它作为我们的纹理:
1 2 3 4 5 6 7 8 | var boxMaterial = new THREE.MeshBasicMaterial({map:bufferTexture}); var boxGeometry2 = new THREE.BoxGeometry( 5, 5, 5 ); var mainBoxObject = new THREE.Mesh(boxGeometry2,boxMaterial); // Move it back so we can see it mainBoxObject.position.z = -10; // Add it to the main scene scene.add(mainBoxObject); |
你可以尽可能的在你的第一个纹理上画任何东西,然后把它渲染到你所喜欢的任何地方!
潜在的用途
最直接的用途就是任何形式的后期处理效果。如果你想要在场景应用某种色彩校正或移位效果,而不是应用于每个单一的对象,你可以只渲染整个场景到一个纹理,最后应用任何你想要的效果到纹理并把它渲染到屏幕上。
任何种类的着色器需要多次通过(如模糊)将会利用这种技术。在本教程我将解释如何使用帧缓冲区来创造烟雾效果。
希望你发现了这个小技巧的有用之处!如果你发现任何错误或有任何疑问,请通过评论让我知晓!