携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情 >>
前言
先说结论:渲染目标就是在可以添加纹理的图元上,通过添加纹理的方式,将渲染目标绘制上去。(仅代表个人观点,不包含任何食用建议。请自行思考,选择是否按照我的理解来看渲染目标),渲染目标可能用到的场景:汽车后视镜,3D商场的试衣镜,监控视频里的活动画面等等。
实践探索
首先,新建渲染目标的代码如下
const rtWidth = 512;
const rtHeight = 512;
const renderTarget = new THREE.WebGLRenderTarget(rtWidth, rtHeight);
这里,注意宽度和高度的变量 rtWidth与rtHeight ,下面我们会用到它
然后,我们需要一个场景和透视相机
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,是取的上面渲染目标的rtWidth和rtHeight,而不是整个画布的width和height,这里,我们看到,得到的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);
为啥是蓝色,因为我设置rtScence的背景色是#2e79ef,以上代码将会用代码片段的方式进行引入