默认情况下,您在 Three.js 中渲染的所有内容都会发送到屏幕上。毕竟,如果你看不到它,渲染它有什么意义呢?事实证明,有一个非常重要的点:在数据发送到屏幕(从而丢失)之前捕获数据。
这使得应用后期处理效果(如颜色校正、颜色偏移或模糊)变得更加容易,并且对于着色器效果也很有用。
此技术称为呈现到纹理或呈现到帧缓冲区;最终结果存储在纹理中。然后,您可以将其渲染到屏幕上。在此文章中,我将向您展示如何执行此操作,然后引导您完成将移动立方体渲染到另一个移动立方体表面上的实际示例。
注意:本教程假设你对 Three.js 有一定的基本了,或者可以访问GLTF编辑器使用了解下three.js的纹理处理功能。
基本实现
有很多关于如何做到这一点的例子,这些例子往往嵌入到更复杂的效果中。以下是在 Three.js 中将某些内容渲染到纹理上所需的最低限度:
// @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
然后我们创建 ,这是一个 WebGLRenderTarget。这就是 Three.js 用来让我们渲染到屏幕以外的其他东西上的东西。bufferTexture
最后,我们告诉 Three.js 渲染:bufferScene
renderer.render(bufferScene, camera, bufferTexture);
这就像渲染普通场景一样,只是我们指定了第三个参数:渲染目标。
所以步骤是:
- 创建一个场景来容纳您的对象。
- 创建纹理以存储渲染的内容
- 将场景渲染到纹理上
这基本上是我们需要做的。不过,这并不是很令人兴奋,因为我们什么也看不到。即使您确实向 中添加了内容,您仍然不会看到任何内容;这是因为您需要以某种方式将创建的纹理渲染到主场景中。下面是如何执行此操作的示例。bufferScene
示例用法
我们将在场景中创建一个立方体,将其绘制到纹理上,然后将其用作新立方体的纹理!
1. 从基本场景开始
这是我们的基本场景,后面有一个红色的旋转立方体和一个蓝色的平面。这里没有什么特别的事情,但您可以通过切换到演示中的 CSS 或 JS 选项卡来查看代码。
你可以在 CodePen 上分叉和编辑它。
2. 将此场景渲染到纹理上
现在我们要把它渲染到纹理上。我们需要做的就是创建一个类似于上述基本实现,并将我们的对象添加到其中。bufferScene
你可以在 CodePen 上分叉和编辑它。
如果做得好,我们将看不到任何东西,因为现在没有任何内容被渲染到屏幕上。相反,我们的场景被渲染并保存在 中。bufferTexture
3. 渲染带纹理的立方体
bufferTexture
与任何其他纹理没有什么不同。我们可以简单地创建一个新对象并将其用作我们的纹理:
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);
你可以在 CodePen 上分叉和编辑它。
您可以在第一个纹理中绘制任何内容,然后将其渲染到您喜欢的任何纹理上!
潜在用途
最直接的用途是任何类型的后期处理效果。如果要对场景应用某种颜色校正或转换,而不是应用于每个对象,则可以将整个场景渲染到一个纹理上,然后在将其渲染到屏幕之前将所需的任何效果应用于最终纹理。