做三维渲染时,偶尔会有分屏绘制的需求,将从不同角度观察到的场景绘制到屏幕上,类似下面这种。
某些本地双人游戏,也是利用了这种分屏机制,例如《双人成行》、《胡闹厨房》(在这里,特别向大家推荐《双人成行》这款游戏,真的非常棒)。
本篇文章,讲解如何使用 Threejs 进行分屏绘制。
讲解 Threejs 分屏绘制之前,先了解下 CS 中的两个概念 viewport 和 scissor。
viewport,中文意,即视口、视窗的意思,scissor 是用剪刀剪、剪刀的意思。
关于viewport的详细解释,可以看这里。简答的说viewport就是摄像机观察到的空间(可以绘制到屏幕上的区域)。
scissor 就是裁剪的意思,可以将 viewport 进行裁剪,绘制 viewport 其中的一块区域,我在 StackExchange 上找到一个关于 viewport 和 scissor 很形象的解释,作者用图片很形象的解释了 viewport、scissor 和窗口大小之间的关系,分为四种不同情况。
在 opengl(webGL) 中裁剪空间的范围是 -1 ~ + 1的。
然后,裁剪空间内的图像需要映射到屏幕窗口坐标系。
想像一下,我们的窗口是黑色的背景,在绘制之前使用白色去清除颜色(openGL 中使用 glClearColor 指定清屏颜色)。
注意到此时,viewport是一个较小的区域,但是 glClear
影响的却是整个屏幕,因为 glClear
的范围由 scissor 的范围决定。
理解了 viewport 和 scissor,接下来我们使用 Threejs 进行分屏绘制。
需要完整的代码,请戳这里。
看一下效果,点击这里大屏查看。
在例子中,使用了两个不同位置的相机,然后利用WebGLRenderer分屏渲染这两个相机。
renderer.setScissorTest(true); // enable scissor test
// view1
scene.background = new THREE.Color("black");
renderer.setViewport(0, 0, halfW, container.clientHeight);
renderer.setScissor(0, 0, halfW, container.clientHeight);
renderer.render(scene, camera1);
// view2
scene.background = new THREE.Color("gray");
renderer.setViewport(halfW, 0, container.clientWidth / 2, container.clientHeight);
renderer.setScissor(halfW, 0, container.clientWidth / 2, container.clientHeight);
renderer.render(scene, camera2);
首先需要通过 renderer.setScissorTest(true)
开启 scissor test,然后使用 renderer.setViewport
和 renderer.setScissor
分别设置 viewport 和 scissor 的位置,这样就可以进行分屏渲染。
(完)