ThreeJs学习笔记【day17】渲染目标【1】

130 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情 >>

前言

先说结论:渲染目标就是在可以添加纹理图元上,通过添加纹理的方式,将渲染目标绘制上去。(仅代表个人观点,不包含任何食用建议。请自行思考,选择是否按照我的理解来看渲染目标),渲染目标可能用到的场景:汽车后视镜,3D商场的试衣镜,监控视频里的活动画面等等。

实践探索

首先,新建渲染目标的代码如下

const rtWidth = 512;
const rtHeight = 512;
const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);

这里,注意宽度和高度的变量 rtWidthrtHeight ,下面我们会用到它

然后,我们需要一个场景和透视相机


const rtFov = 75;
const rtAspect = rtWidth / rtHeight;
const rtNear = 0.1;
const rtFar = 5;
const rtCamera = new THREE.PerspectiveCamera(rtFov, rtAspect, rtNear, rtFar);
rtCamera.position.z = 2;
 
const rtScene = new THREE.Scene();
rtScene.background = new THREE.Color('#2e79ef');

这里注意,此处rtCamera的ascpect,是取的上面渲染目标的rtWidthrtHeight,而不是整个画布的widthheight,这里,我们看到,得到的aspect为1.0,为什么?正确的长宽比取决于我们要渲染的对象。在本例,我们要将渲染目标的纹理用在方块的一个面,基于方块的面我们设置长宽比为1.0

这里我们需要借助之前的三个立方体那篇的代码片段,给渲染目标的rtScence添加灯光和三个方块

{
  const color = 0xFFFFFF;
  const intensity = 1;
  const light = new THREE.DirectionalLight(color, intensity);
  light.position.set(-1, 2, 4);
  rtScene.add(light);
}
 
const boxWidth = 1;
const boxHeight = 1;
const boxDepth = 1;
const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
 
function makeInstance(geometry, color, x) {
  const material = new THREE.MeshPhongMaterial({color});
 
  const cube = new THREE.Mesh(geometry, material);
  rtScene.add(cube);
 
  cube.position.x = x;
 
  return cube;
}
 
const rtCubes = [
  makeInstance(geometry, 0x44aa88,  0),
  makeInstance(geometry, 0x8844aa, -2),
  makeInstance(geometry, 0xaa8844,  2),
];

注意,灯光与三个立方体,均是添加在渲染目标的场景内的

接下来,我们将渲染目标作为纹理,创建一个正方体来渲染他

const material = new THREE.MeshPhongMaterial({
  map: renderTarget.texture,
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

这里有人就发现了,threeJs都是要调用渲染方法然后传入场景和相机才会渲染,你这只是引入了个纹理,啥也没干呐,难道这里threeJs会帮我们自动做这件事情吗?

...

想多了兄弟,当然不是,接下来,就需要在render方法内,让渲染目标渲染到目标,首先需要设置webGl实例也就是rerender的renderTarget为我们之前创建好的target

renderer.setRenderTarget(renderTarget);
renderer.render(rtScene, rtCamera);
renderer.setRenderTarget(null);

image.png

为啥是蓝色,因为我设置rtScence的背景色是#2e79ef,以上代码将会用代码片段的方式进行引入