three.js中帧缓存的使用

1. 概述

在网上查阅了一下three.js关于帧缓存的使用,感觉很多都是关于three.js中后处理通道的使用的。后处理通道确实使用FBO实现的,但其实我就是想获取某个时刻的渲染结果作为纹理,没必要在动态渲染中进行后处理。真正实现这个功能的是WebGLRenderTarget这个类,这是一个渲染目标的缓冲区,可以装载到WebGLRenderer中进行渲染,再从WebGLRenderTarget获取纹理对象。

2. 示例

2.1. 代码

废话不多说,直接给出代码:

'use strict';

function init() {

    var scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000000);      //场景的背景色

    // create a camera, which defines where we're looking at.
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

    // position and point the camera to the center of the scene
    camera.position.set(0, 0, 60);   //相机的位置
    camera.up.set(0, 1, 0);         //相机以哪个方向为上方
    camera.lookAt(new THREE.Vector3(0, 0, 0));          //相机看向哪个坐标

    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0xffffff, 1);     //渲染器的背景色   
    document.body.appendChild(renderer.domElement);

    
    //缓存场景
    var bufferScene = new THREE.Scene();
    //渲染目标缓冲区
    var bufferTexture = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);

    // create the ground plane
    var fboGeometry = new THREE.PlaneGeometry(60, 30);
    var fboMaterial = new THREE.MeshBasicMaterial({
        color: 0xAAAAAA
    });

    var fboPlane = new THREE.Mesh(fboGeometry, fboMaterial);

    // add the plane to the scene
    bufferScene.add(fboPlane);

    //渲染到目标缓冲区
    renderer.setRenderTarget(bufferTexture);
    renderer.render(bufferScene, camera);

    //渲染到屏幕
    renderer.setRenderTarget(null);

    // create the ground plane
    var planeGeometry = new THREE.PlaneGeometry(60, 30);
    var planeMaterial = new THREE.MeshBasicMaterial({     
        map: bufferTexture.texture      //获取渲染目标缓冲区中的纹理
    });

    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    scene.add(plane);
    
    function render() {
        requestAnimationFrame(render);               
        renderer.render(scene, camera);
    }
    render();
}

其运行的结果如下:
imglink1

2.2. 解析

渲染的结果出现了三个颜色部分:黑色区域,白色区域,以及灰色区域。对照代码来说,渲染器的清空色(背景色)是白色的:

renderer.setClearColor(0xffffff, 1);     //渲染器的背景色   

但是由于给当前的场景根节点设置背景色为黑色:

scene.background = new THREE.Color(0x000000);      //场景的背景色

所以最外层的部分是黑色。

场景根节点中绘制了一个面:

    // create the ground plane
    var planeGeometry = new THREE.PlaneGeometry(60, 30);
    var planeMaterial = new THREE.MeshBasicMaterial({     
        map: bufferTexture.texture      //获取渲染目标缓冲区中的纹理
    });

    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    scene.add(plane);

这个面的材质纹理来自于自定义的喧嚷目标缓冲区,并且预先通过渲染器将缓存场景渲染到这个缓冲区中:

    //缓存场景
    var bufferScene = new THREE.Scene();
    //渲染目标缓冲区
    var bufferTexture = new THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight);

    //...

    //渲染到目标缓冲区
    renderer.setRenderTarget(bufferTexture);
    renderer.render(bufferScene, camera);

    //渲染到屏幕
    renderer.setRenderTarget(null);

在缓存场景中,通过同一个相机,也绘制了一个面,这个面的材质颜色是灰色的:

    // create the ground plane
    var fboGeometry = new THREE.PlaneGeometry(60, 30);
    var fboMaterial = new THREE.MeshBasicMaterial({
        color: 0xAAAAAA
    });

    var fboPlane = new THREE.Mesh(fboGeometry, fboMaterial);

    // add the plane to the scene
    bufferScene.add(fboPlane);

所以最里层的部分就是缓存场景绘制面,也就是灰色的。而这个缓存场景是通过同一个渲染器绘制的,也就是缓存场景剩余的部分,就会是渲染器的背景色,也就是白色了。

3. 参考

  1. Quick Tip: How to Render to a Texture in Three.js
  2. 如何在ThreeJS中使用场景的渲染结果作为纹理?
posted @ 2020-06-20 12:56  charlee44  阅读(1258)  评论(0编辑  收藏  举报