ThreeJs入门37 您所在的位置:网站首页 摄像机左上角 ThreeJs入门37

ThreeJs入门37

#ThreeJs入门37| 来源: 网络整理| 查看: 265

「这是我参与2022首次更文挑战的第41天,活动详情查看:2022首次更文挑战」

示例代码采用three.js-r73版本: github.com/mrdoob/thre…

我们上节讲解了多摄像机、多视图、多角度摄影,对于多视图我们还需要了解一些其他的东西。类似于3Dmax的多视图显示又应该如何做呢?我们一起来看下吧。

3Dmax的多视图 如果你有用过3Dmax,那么你对于多视图是会比较熟悉的。看下图

aa18972bd40735faad72ed9e9f510fb30f240812.jpg

在我们的3Dmax软件上显示一个物体,但是我们显示了4个窗口,分别显示了物体的正面、侧面、斜面、透视和实体效果。 我们通过three.js也能实现类似的效果,下面我们就开始吧。 效果展示 我们在场景中添加了3个20面体和对应的阴影。通过设置摄像机不同的位置,来达到类似于3Dmax的效果

image.png

图1:正面看的效果 图2:侧面看的效果 图3:上面看的效果 图4:斜面看的效果 下面讲解的时候会以图1234来进行说明做的是哪一部分的内容 场景渲染方式 我们的渲染方式其实有两种: 多个相机、多个渲染器、单个场景 上一节讲述的就是这个渲染方式 多个相机、多个渲染器、多个场景 这一节我们要讲述的渲染方式 实现方式 通过一个场景,放入3个20面体 把场景添加到4个容器中,这个时候我们不设置摄像机或者设置一个摄像机,4个容器展示效果一样 摆放4个不同位置的摄像机,就可以显示出不同的效果了 静态界面 我们先把html界面布局好 我们准备4个容器,用来布局我们的场景 body { color: #808080; font-family: Monospace; font-size: 13px; text-align: center; background-color: #fff; margin: 0px; overflow: hidden; } #container { position: relative; } #container1, #container2, #container3, #container4 { position: absolute; border: 1px solid red; } #container1 { width: 500px; height: 250px; } #container2 { width: 500px; height: 250px; left: 520px; } #container3 { width: 500px; height: 250px; top: 270px; } #container4 { width: 500px; height: 250px; top: 270px; left: 520px; } 初始化视图 我们需要初始化4个画布,来放置我们场景中不同摄像机的位置 function initView() { container1 = document.getElementById("container1"); container2 = document.getElementById("container2"); container3 = document.getElementById("container3"); container4 = document.getElementById("container4"); } 初始化场景 我们初始化一个场景,用来放我们的物体、摄像机、灯光等 function initScene() { scene = new THREE.Scene(); } 初始化灯光 初始化一个环境光,添加到场景中 function initLight() { light = new THREE.DirectionalLight(0xffffff); light.position.set(0, 0, 1).normalize(); scene.add(light); } 初始化摄像机 我们使用的摄像机都是透视投影 设置远近距离 const near = 1 const far = 10000 图1摄像机 图1中需要的摄像机,是正对屏幕往里看的效果 camera1 = new THREE.PerspectiveCamera(45, 500 / 250, near, far); camera1.setViewOffset(500, 250, 0, 0, 500, 250) camera1.position.z = 1800 // z轴看向原点,正对屏幕

image.png

图2摄像机 图2需要的摄像机,是从侧面看的效果 camera2 = new THREE.PerspectiveCamera(45, 500 / 250, near, far); camera2.setViewOffset(500, 250, 0, 0, 500, 250) camera2.position.x = 1800 // x轴看向原点,从球的侧面往左看 类似于在图1中摆放了从右往左看的摄像机

image.png

图3摄像机 图3需要的摄像机,是从上往下看 这里我们调整y的位置时,也需要调整快门的方向,保证快门和y轴平行 camera3 = new THREE.PerspectiveCamera(45, 500 / 250, near, far); camera3.setViewOffset(500, 250, 0, 0, 500, 250) camera3.position.y = 1800 // y轴看向原点,从球的上面往下看 camera3.up.set(0, 0, 1) // 默认为(0,1,0),调整快门的方向,和y轴平行 类似于在图1中摆放了一个向下看的摄像机

image.png

图4摄像机 图3需要的摄像机,是从右下角往左上角看 camera4 = new THREE.PerspectiveCamera(45, 500 / 250, near, far); camera4.setViewOffset(500, 250, 0, 0, 500, 250) // 斜着看物体 camera4.position.x = 300 camera4.position.z = 800 类似于在图1中摆放了一个向下看的摄像机

image.png

初始化20面几何体 上一节课我们已经实现过了,这一节不做过多介绍,直接看代码 var shadowMaterial; function createShadowByCanvas() { // 创建画布 var canvas = document.createElement("canvas"); // 设置画布大小宽128,高128 canvas.width = 128; canvas.height = 128; // 得到画布的可画类context var context = canvas.getContext("2d"); // 创建一个放射性渐变,渐变从画布的中心开始,到以canvas.width/2为半径的圆结束。如果不明白可以参考:http://www.w3school.com.cn/htmldom/met_canvasrenderingcontext2d_createradialgradient.asp var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 ); // 在离画布中心canvas.width*0.1的位置添加一种颜色, gradient.addColorStop(0.1, "rgba(210,210,210,1)"); // 在画布渐变的最后位置添加一种颜色, gradient.addColorStop(1, "rgba(255,255,255,1)"); // 填充方式就是刚才创建的渐变填充 context.fillStyle = gradient; // 实际的在画布上绘制渐变。 context.fillRect(0, 0, canvas.width, canvas.height); // 将画布转为纹理 var shadowTexture = new THREE.CanvasTexture(canvas); shadowTexture.needsUpdate = true; // 将纹理添加到材质中 shadowMaterial = new THREE.MeshBasicMaterial({ map: shadowTexture }); } function initShadowPlane() { // 定义一个宽和高都是300的平面,平面内部没有出现多个网格。 var shadowGeo = new THREE.PlaneGeometry(300, 300, 1, 1); // 构建一个Mesh网格,位置在(0,-250,0),即y轴下面250的距离。 mesh = new THREE.Mesh(shadowGeo, shadowMaterial); mesh.position.y = -250; // 围绕x轴旋转-90度,这样竖着的平面就横着了。阴影是需要横着的。 mesh.rotation.x = -Math.PI / 2; scene.add(mesh); // 第二个平面阴影 mesh = new THREE.Mesh(shadowGeo, shadowMaterial); mesh.position.x = -400; mesh.position.y = -250; mesh.rotation.x = -Math.PI / 2; scene.add(mesh); // 第三个平面阴影 mesh = new THREE.Mesh(shadowGeo, shadowMaterial); mesh.position.x = 400; mesh.position.y = -250; mesh.rotation.x = -Math.PI / 2; scene.add(mesh); } // 初始化物体 function initObject() { // 20面体的半径是200单位 var radius = 200; // 生成3个20面体 var geometry1 = new THREE.IcosahedronGeometry(radius, 1); // 由于场景中有3个20面体,所以这里通过clone函数复制3个。clone函数将生产一模一样的一个几何体。 var geometry2 = geometry1.clone(); var geometry3 = geometry1.clone(); var faceIndices = ['a', 'b', 'c', 'd']; var color, f1, f2, f3, p, n, vertexIndex; for (var i = 0; i < geometry1.faces.length; i++) { f1 = geometry1.faces[i]; f2 = geometry2.faces[i]; f3 = geometry3.faces[i]; n = (f1 instanceof THREE.Face3) ? 3 : 4; for (var j = 0; j < n; j++) { vertexIndex = f1[faceIndices[j]]; p = geometry1.vertices[vertexIndex]; color = new THREE.Color(0xffffff); color.setHSL((p.y / radius + 1) / 2, 1.0, 1.0); f1.vertexColors[j] = color; color = new THREE.Color(0xffffff); color.setHSL(0.0, (p.y / radius + 1) / 2, 1.0); f2.vertexColors[j] = color; color = new THREE.Color(0xffffff); color.setHSL(0.125 * vertexIndex / geometry1.vertices.length, 1.0, 1.0); f3.vertexColors[j] = color; } } var materials = [ new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors }), new THREE.MeshBasicMaterial({ color: 0x000000, shading: THREE.FlatShading, wireframe: true, transparent: true }) ]; /* --几何体1-- */ group1 = THREE.SceneUtils.createMultiMaterialObject( geometry1, materials ); group1.position.x = -400; group1.rotation.x = -1.87; scene.add( group1 ); /* --几何体2-- */ group2 = THREE.SceneUtils.createMultiMaterialObject( geometry2, materials ); group2.position.x = 400; group2.rotation.x = 0; scene.add( group2 ); /* --几何体3-- */ group3 = THREE.SceneUtils.createMultiMaterialObject( geometry3, materials ); group3.position.x = 0; group3.rotation.x = 0; scene.add( group3 ); } 我们上一节是使用r93版本实现的20面几何体,这一节我们使用r73版本实现的几何体,由于r73版本没有IcosahedronBufferGeometry这个方法,所以我们通过IcosahedronGeometry方法来实现。 这里也用到了THREE.SceneUtils.createMultiMaterialObject方法,这个方法可以把多种材质的数组,添加到一个几何体中 初始化渲染器 我们需要4个渲染器,添加到4个容器中 renderer1 = new THREE.WebGLRenderer({ antialias: true }); renderer1.setSize(500, 250); renderer2 = new THREE.WebGLRenderer({ antialias: true }); renderer2.setSize(500, 250); renderer3 = new THREE.WebGLRenderer({ antialias: true }); renderer3.setSize(500, 250); renderer4 = new THREE.WebGLRenderer({ antialias: true }); renderer4.setSize(500, 250); container1.appendChild(renderer1.domElement); container2.appendChild(renderer2.domElement); container3.appendChild(renderer3.domElement); container4.appendChild(renderer4.domElement); 如果只使用一个渲染器,四个容器中添加这个渲染器,那么会造成只有最后一个容器添加了这个渲染器,也就是如下效果

image.png

渲染函数 我们需要让4个摄像机都看向场景,不然的话可能摄像机就看不到我们的物体了。 function animation() { render() requestAnimationFrame(animation); } function render() { camera1.lookAt(scene.position) camera2.lookAt(scene.position) camera3.lookAt(scene.position) camera4.lookAt(scene.position) renderer1.render(scene, camera1) renderer2.render(scene, camera2) renderer3.render(scene, camera3) renderer4.render(scene, camera4) }

codepen示例代码



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有