首页 > 代码库 > 多视口的实现

多视口的实现

1. 多视口

1.1. 什么是视口及实现方法

   WebGL视口就是窗口上绘制模型的地方, WebGL一般情况下只有一个窗口,但是可以有多个视口, 有时候我们需要多个视口显示同一个模型的不同角度,这个时候就要用到多视口,在three.js中实现多视口有两种方法,第一种用多个相机,每个相机关联一个视口,显示每个相机的时候,都要重新定义视口在页面上的位置, 第二种只有一个相机,但是这个相机关联多个视口,然后同一个相机分多次绘制,就可以把相机内部的模型绘制到不同的视口内部。

1.2. 多视口的原理

就是每次Render都改变视口矩阵,视口矩阵改变了,模型在屏幕上绘制的位置也就改变了,所以实现多视口可以用多个相机或者一个相机,但是每次视口矩阵都要不同。opengl可以使用glViewPort()改变视口矩阵,three.js可以使用renderer.setViewport( left, bottom, width, height )改变视口矩阵,一般情况下,视口矩阵的参数会被规格化到01之间。

也就是把屏幕的长宽定为1.0, 然后根据比例输入参数。

 

1.3. 案例

   three.js中的一个例子webgl_multiple_views.html

 技术分享

最左边的视口定义如下,窗口长宽规格化为1,以左下角为原点,

{

left: 0,       视口在X方向的坐标

bottom: 0,     视口在Y方向的坐标

width: 0.5,    视口宽0.5,长宽都规格化到01之间

height: 1.0,    视口高1.0

background: new THREE.Color().setRGB( 0.5, 0.5, 0.7 ),  背景色

eye: [ 0, 300, 1800 ],  眼睛的位置

up: [ 0, 1, 0 ],        向上向量

fov: 30,             抬头的角度

updateCamera: function ( camera, scene, mouseX, mouseY ) {

camera.position.x += mouseX * 0.05;

camera.position.x = Math.max( Math.min( camera.position.x, 2000 ), -2000 );

camera.lookAt( scene.position ); //mousreX, mouseY,鼠标在屏幕上移动的时候的坐标,根据坐标的变化,实现球的运动

    }

},

定义完第一个视口后,用同样的方法定义其它两个视口,只要改变left, bottom, width, height,就可以改变视口的位置。

 

这个例子同样可以形成阴影,方法如下,先形成一个二维的画布,并且在上面绘制一个填充的矩形

var canvas = document.createElement( ‘canvas‘ );

canvas.width = 128;

canvas.height = 128;

 

形成阴影纹理,这是three.js中的实现阴影的方式

var shadowMaterial = new THREE.MeshBasicMaterial({ map: shadowTexture, transparent: true });

var shadowGeo = new THREE.PlaneBufferGeometry( 300, 300, 1, 1 );

 

然后把球挂场景上

group1 = THREE.SceneUtils.createMultiMaterialObject( geometry, materials );

group1.position.x = -400; 改变位置

group1.rotation.x = -1.87;

scene.add( group1 );

 

然后在不同的视口,使用不同的相机绘制,然后就形成了多视口

for ( var ii = 0; ii < views.length; ++ii ) {

view = views[ii];

camera = view.camera;

view.updateCamera( camera, scene, mouseX, mouseY );

 

    //从规格化的视口转变为屏幕坐标

var left   = Math.floor( windowWidth  * view.left );

var bottom = Math.floor( windowHeight * view.bottom );

var width  = Math.floor( windowWidth  * view.width );

var height = Math.floor( windowHeight * view.height );

 

    //设置视口在屏幕上的位置

renderer.setViewport( left, bottom, width, height );

renderer.setScissor( left, bottom, width, height );

renderer.enableScissorTest ( true );

renderer.setClearColor( view.background );

camera.aspect = width / height;

camera.updateProjectionMatrix();

renderer.render( scene, camera );

}

 

交流图形学的一切,尤其是大型程序的设计,每天有原创文章
微信公众号: GraphicsPlatform

qq群: 559684273
qq:   1829634717

将近两百篇图形学相关的技术文章,经常更新
技术博客: http://www.cnblogs.com/lizhengjin

多视口的实现