<pre name="code" class="javascript"><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>canvas_camera_orthographinc</title> <style> body { font-family:'宋体';//设置body区域显示的字体 background-color: #f0f0f0;//设置body的背景颜色 margin: 0px;//设置body的边距 overflow: hidden;//overflow表示溢出元素需要做的处理,hidden表示内容会被修剪,并且其余内容是不可见的。 } </style> </head> <body> <script src="three.js-master/build/three.js"></script> <script src="three.js-master/build/renderers/Projector.js"></script> <script src="three.js-master/build/renderers/CanvasRenderer.js"></script> <script src="three.js-master/build/controls/OrbitControls.js"></script> <script> var rendererCanvas,scene,camera,light; function initRenderer() { rendererCanvas=new THREE.CanvasRenderer(); //创建一个基于canvas的渲染器 rendererCanvas.setSize( window.innerWidth, window.innerHeight );//设置渲染器的大小 document.body.appendChild(rendererCanvas.domElement); //将渲染器添加到body区域 rendererCanvas.setClearColor(0xffffff); //设置渲染器的背景颜色为白色 } function initScene() { scene=new THREE.Scene();//创建一个场景 } function initCamera() { //创建一个正投影相机照相机 camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000 ); //camera=new THREE.PerspectiveCamera(70,window.innerWidth/window.innerHeight,1,1000);//创建透视照相机 camera.position.x = 200; camera.position.y = 100; camera.position.z = 200;//设置相机的位置 camera.lookAt(scene.position);//将相机固定在scene.position所指向的位置 scene.add(camera);//将相机加到场景中去 } function initLight() { var ambientLight = new THREE.AmbientLight(0x0000FF);//创建一个环境光,光为蓝色 scene.add( ambientLight ); } function initGeometry() { var geometry=new THREE.Geometry(); /* 在画网格时,需要提供四个坐标点,然后使用LineBasicMaterial根据坐标点画线段,如: 1、(-500,0,500)在空间坐标系中,该坐标点在第四象限 2、(500,0,500)在空间坐标系中,该坐标点在第一象限 3、(500,0,500)与第二个点坐标相同 4、(500,0,-500)在空间坐标系中,该坐标点在第二象限 如: (-500,0,-500) (-300,0,-500) (-100,0,-500) (100,0,-500) (300,0,-500) (500,0,-500) (-500,0,-500)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-500) (-500,0,-450)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-450) (-500,0,-400)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-400) (-500,0,-350)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-350) (-500,0,-300)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-300) (-500,0,-250)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-250) (-500,0,-200)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-200) (-500,0,-150)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-150) (-500,0,-100)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-100) (-500,0, -50)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-50) (-500,0, 0)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,0) (-500,0, 50)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,50) (-500,0,100)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,100) (-500,0,150)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,150) (-500,0,200)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,200) (-500,0,250)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,250) (-500,0,300)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,300) (-500,0,350)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,350) (-500,0,400)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,400) (-500,0,450)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,450) (-500,0,500)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,500) (-500,0,500)(-350,0,500)(-200,0,500)(-50,0,500) (100,0,500) (250,0,500) (400,0,500)(500,0,500) */ var size=500,step=50; for(var i=-size;i<=size;i+=step) { geometry.vertices.push(new THREE.Vector3(-size,0,-i)); geometry.vertices.push(new THREE.Vector3(size,0,-i)); geometry.vertices.push(new THREE.Vector3(-i,0,size)); geometry.vertices.push(new THREE.Vector3(-i,0,-size)); } var material=new THREE.LineBasicMaterial({color:0x000000,opacity:0.5});//创建一个颜色为黑色,线条透明度为0.5 var line=new THREE.LineSegments(geometry,material); scene.add(line); var geometry1 = new THREE.BoxGeometry( 50, 50, 50 );//创建一个立方体 var material1 = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw:0.1 } );//材质颜色为白色,0.5是否在立方体上线条的显示程度,越小显示越明显 for ( var i = 0; i < 100; i ++ ) { var cube = new THREE.Mesh( geometry1, material1 );//绘制立方体 //以下是设置立方体的位置 cube.position.x = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; cube.position.y = ( cube.scale.y * 50 ) / 2; cube.position.z = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; scene.add( cube ); } } function render() { rendererCanvas.render(scene,camera); } function initStart() { initRenderer(); initScene(); initCamera(); initLight(); initGeometry(); render(); var control=new THREE.OrbitControls(camera);//添加控制动作,参数camera是相机,说明控制的是相机 control.addEventListener('change',render);//当场景交换时重绘场景 } initStart(); /* 基本步骤: 1、创建一个渲染器,并设置其大小,将其添加到div或body区域中 (1) 声明全局render对象; (2) 获取画布的高和宽; (2) 生成渲染器对象 (3) 指定渲染器的高宽(一般跟画布框大小一致); (4) 追加canvas元素到canvas3d元素中; (5) 设置渲染器的清除色。 2、创建一个照相机,并设置照相机的中心位置,即z轴 (1) 声明全局的变量(对象); (2) 设置透视投影的相机; (3) 设置相机的位置坐标; (4) 设置相机的上为「z」轴方向; (5) 设置视野的中心坐标。 3、创建一个场景 4、创建灯光 (1) 声明全局变量(对象) (2) 设置平行光源 (3) 设置光源向量 (4) 追加光源到场景 5、创建物体或加载模型,创建贴图对象,并将贴图转换成材质,并将材质贴到物体上,最后添加到场景中 6、开始渲染 */ </script> </body> </html>
运行效果图如下:
对以上代码进行分析:
1、首先声明全局变量
var rendererCanvas,scene,camera,light;其中包括渲染器变量,场景变量,相机变量以及环境光变量。
2、初始化渲染器函数,如下代码所示:
function initRenderer() { rendererCanvas=new THREE.CanvasRenderer(); //创建一个基于canvas的渲染器 rendererCanvas.setSize( window.innerWidth, window.innerHeight );//设置渲染器的大小 document.body.appendChild(rendererCanvas.domElement); //将渲染器添加到body区域 rendererCanvas.setClearColor(0xffffff); //设置渲染器的背景颜色为白色 }
function initScene() { scene=new THREE.Scene();//创建一个场景 }4、初始化相机函数,并将相机固定在某个位置,如下代码所示:
function initCamera() { //创建一个正投影相机照相机 //camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000 ); camera=new THREE.PerspectiveCamera(70,window.innerWidth/window.innerHeight,1,1000);//创建透视照相机 camera.position.x = 200; camera.position.y = 100; camera.position.z = 200;//设置相机的位置 camera.lookAt(scene.position);//将相机固定在scene.position所指向的位置 scene.add(camera);//将相机加到场景中去 }5、初始化环境光函数,如下代码所示:
function initLight() { var ambientLight = new THREE.AmbientLight(0x0000FF);//创建一个环境光,光为蓝色 scene.add( ambientLight ); }6、初始化Geometry函数,在此函数中,首先创建的是网格,然后在创建各个小立方体,创建网格的方法是通过先设置4个顶点,然后在通过LineSegments函数将四个点画一条线出来,比如:有四个顶点a、b、c、d对应的坐标是(-500,0,500)、(500,0,500)、(500,0,500)、(500,0,-500),那么执行这个动作则是从a画一条线到b,然后在从c画一条线到d,由于b和c的坐标相同,所以看起来就是向连接的,如下所示:
那么映射到屏幕上的效果是透视相机的效果,刚开始时比较大,所以要缩小才能看到,如下图所示:
以下是正交相机的效果,如下图所示:
相对应的代码如下所示:
function initGeometry() { var geometry=new THREE.Geometry(); geometry.vertices.push(new THREE.Vector3(-500,0,500)); geometry.vertices.push(new THREE.Vector3(500,0,500)); geometry.vertices.push(new THREE.Vector3(500,0,500)); geometry.vertices.push(new THREE.Vector3(500,0,-500)); var material=new THREE.LineBasicMaterial({color:0x000000,opacity:0.5}); var line=new THREE.LineSegments(geometry,material); scene.add(line); }那么要画成一个网格,那必须有一个循环来保存这些顶点,如下代码所示:
function initGeometry() { var geometry=new THREE.Geometry(); var size=500,step=50; for(var i=-size;i<=size;i+=step) { geometry.vertices.push(new THREE.Vector3(-size,0,-i)); geometry.vertices.push(new THREE.Vector3(size,0,-i)); geometry.vertices.push(new THREE.Vector3(-i,0,size)); geometry.vertices.push(new THREE.Vector3(-i,0,-size)); } var material=new THREE.LineBasicMaterial({color:0x000000,opacity:0.5});//创建一个颜色为黑色,线条透明度为0.5 var line=new THREE.LineSegments(geometry,material); scene.add(line); }运行效果图(透视相机)如下所示:
网格画好了,在上边画小的立方体,那么首先创建一个立方体,然后在材质绑定,如下代码所示:
var geometry1 = new THREE.BoxGeometry( 50, 50, 50 );//创建一个立方体 var material1 = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw:0.5 } );//材质颜色为白色,0.5是否在立方体上线条的显示程度,越小显示越明显 for ( var i = 0; i < 100; i ++ ) { var cube = new THREE.Mesh( geometry1, material1 );//绘制立方体 //以下是设置立方体的位置 cube.position.x = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; cube.position.y = ( cube.scale.y * 50 ) / 2; cube.position.z = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; scene.add( cube ); }如下overdraw:0.5的效果图:
如下overdraw:0.1的效果图,可以观察到有细小的白色线条:
整个函数的代码如下所示:
function initGeometry() { var geometry=new THREE.Geometry(); /* 在画网格时,需要提供四个坐标点,然后使用LineBasicMaterial根据坐标点画线段,如: 1、(-500,0,500)在空间坐标系中,该坐标点在第四象限 2、(500,0,500)在空间坐标系中,该坐标点在第一象限 3、(500,0,500)与第二个点坐标相同 4、(500,0,-500)在空间坐标系中,该坐标点在第二象限 如: (-500,0,-500) (-300,0,-500) (-100,0,-500) (100,0,-500) (300,0,-500) (500,0,-500) (-500,0,-500)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-500) (-500,0,-450)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-450) (-500,0,-400)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-400) (-500,0,-350)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-350) (-500,0,-300)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-300) (-500,0,-250)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-250) (-500,0,-200)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-200) (-500,0,-150)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-150) (-500,0,-100)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-100) (-500,0, -50)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,-50) (-500,0, 0)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,0) (-500,0, 50)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,50) (-500,0,100)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,100) (-500,0,150)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,150) (-500,0,200)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,200) (-500,0,250)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,250) (-500,0,300)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,300) (-500,0,350)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,350) (-500,0,400)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,400) (-500,0,450)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,450) (-500,0,500)/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/___/(500,0,500) (-500,0,500)(-350,0,500)(-200,0,500)(-50,0,500) (100,0,500) (250,0,500) (400,0,500)(500,0,500) */ var size=500,step=50; for(var i=-size;i<=size;i+=step) { geometry.vertices.push(new THREE.Vector3(-size,0,-i)); geometry.vertices.push(new THREE.Vector3(size,0,-i)); geometry.vertices.push(new THREE.Vector3(-i,0,size)); geometry.vertices.push(new THREE.Vector3(-i,0,-size)); } var material=new THREE.LineBasicMaterial({color:0x000000,opacity:0.5});//创建一个颜色为黑色,线条透明度为0.5 var line=new THREE.LineSegments(geometry,material); scene.add(line); var geometry1 = new THREE.BoxGeometry( 50, 50, 50 );//创建一个立方体 var material1 = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw:0.1 } );//材质颜色为白色,0.5是否在立方体上线条的显示程度,越小显示越明显 for ( var i = 0; i < 100; i ++ ) { var cube = new THREE.Mesh( geometry1, material1 );//绘制立方体 //以下是设置立方体的位置 cube.position.x = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; cube.position.y = ( cube.scale.y * 50 ) / 2; cube.position.z = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; scene.add( cube ); } }7、对场景进行渲染函数,如下所示:
function render() { rendererCanvas.render(scene,camera); }8、最后对所有的函数进行统一初始化,如下代码所示:
function initStart() { initRenderer(); initScene(); initCamera(); initLight(); initGeometry(); render(); var control=new THREE.OrbitControls(camera);//添加控制动作,参数camera是相机,说明控制的是相机 control.addEventListener('change',render);//当场景交换时重绘场景 }最后只需要调用initStart()即可完成所有的工作
9、对场景添加控制,比如说按鼠标滚轮可以扩大或缩小,按着鼠标左键可以在原点进行旋转等等,首先要引入OrbitControls.js文件,然后通过
var control=new THREE.OrbitControls(camera);//添加控制动作,参数camera是相机,说明控制的是相机
来创建一个控制变量,参数是照相机则说明是对照相机的控制,最后在添加监听函数,就是当照相机改变时就调用对场景的重新渲染,如下代码:
control.addEventListener('change',render);//当场景交换时重绘场景