<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); //设置渲染器的背景颜色为白色
}
3、初始化场景函数,如下代码所示:
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);//当场景交换时重绘场景