[WebAR和WebVR学习之路]从Three.js开始掌握We
《为什么要学习Three.js》
Three.js是JavaScript编写的WebGL第三方库。提供了非常多的3D显示功能。
Three.js对WebGL进行了封装,省去了很多WebGL底层的代码,使得编写Web的3D程序十分方便。
现如今,WebAR和WebVR逐渐进入人们的视野。由于Web不需要下载程序的简便性使得更多的人倾向于在Web页面开发VR/AR应用(快速捕捉客户)。因此,学习WebGL的开发使得一个VR/AR开发者更具有竞争力。
今天,我们将简单的从几个方面来讲解Three.js,已达到快速入门的目的。
知识需求:
简单的Web前端知识(HTML、CSS和JS)
简单的OpenGL的知识(包括OpenGL ES和WebGL)
《一个简单的Three.js页面框架》
由于Three.js需要一个简单的web服务器来测试,所以我们需要搭建一个简单的HTTP服务器。
对于大多数人来说,搭建web服务器是一个十分简单的事情,但对一些新手我们可以使用集成环境来快速搭建web服务器来测试(像是eclipse中集成的tomcat服务器一样)。
在这里我推荐使用Web Storm软件,搞前端开发的程序员对此软件并不陌生,其扩展性高使用十分便捷。
下面我们开始搭建一个简单的Three.js页面的框架。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example 01.01 - Bacis skeleton</title>
<script type="text/javascript"
src="../libs/three.js"></script>
<script type="text/javascript"
src="../libs/jquery-3.1.1.js"></script>
<style>
body{
/*设置页面的样式*/
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<!—用于显示WebGL输出的div-->
<div id="WebGL-output">
</div>
<!—以下为Three.js的具体代码-->
<script type="text/javascript">
//在加载过后自动运行的函数
$(function () {
//在此输入Three.js代码
});
</script>
</body>
</html>
《渲染并创建一个三维对象》
在上文的注释 在此输入Three.js代码的地方删除该注释,输入以下代码。
运行测试一下,效果如图。
后面我们将会讲解这一段简单的代码。
$(function () {
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var renderer=new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE,0.5);
renderer.setSize(window.innerWidth,window.innerHeight);
var axes=new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshBasicMaterial({color:0xcccccc});
var plane=new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x=-0.5*Math.PI;
plane.position.x=15;plane.position.y=0;plane.position.z=0;
scene.add(plane);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshBasicMaterial({color:0xff0000,wireframe:true});
var cube=new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.x=-4;cube.position.y=3;cube.position.z=0;
scene.add(cube);
var sphereGeometry=new THREE.SphereGeometry(4,20,20);
var sphereMaterial=new THREE.MeshBasicMaterial({color:0x7777ff,wireframe:true});
var sphere=new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x=20;sphere.position.y=4;sphere.position.z=2;
scene.add(sphere);
camera.position.x=-30;camera.position.y=40;camera.position.z=30;
camera.lookAt(scene.position);
$("#WebGL-output").append(renderer.domElement);
renderer.render(scene,camera);
});
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var renderer=new THREE.WebGLRenderer();
在本章的一开始,定义了scene、camera和renderer(场景、相机和渲染器)。
scene是一个容器,保存并跟踪想要渲染的物体,在后面创建了几何体之后(如立方体和球体等)会添加到scene变量中。
camera变量定义了在渲染好的scene里看到什么。
最后是renderer对象,renderer对象负责计算指定的相机角度下的浏览器中scene的呈现样子。
在以上实例中,我们创建了一个WebGLRenderer对象,使用计算机的图形卡来渲染场景。
renderer.setClearColor(0xEEEEEE,0.5);
renderer.setSize(window.innerWidth,window.innerHeight);
接下来通过renderer的setClearColor函数来设置renderer的背景色为接近白色的颜色(0xEEEEEE),并通过setSize()函数来告诉renderer将scene渲染为多大的尺寸。
通过以上的代码,我们有了一个空白的scene、一个renderer和一个camera。
下面我们来创建一个坐标轴对象,并添加到场景中。
var axes=new THREE.AxisHelper(20);
scene.add(axes);
通过THREE的AxisHelper函数我们创建了一个长度为20的坐标轴,并通过scene的add函数将其添加到了场景中。
下面我们再创建一个平面(plane)并修改其旋转和位置。
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshBasicMaterial({color:0xcccccc});
var plane=new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x=-0.5*Math.PI;
plane.position.x=15;plane.position.y=0;plane.position.z=0;
scene.add(plane);
首先通过THREE.PlaneGeometry(60,20)来定义该平面的尺寸,在该章节中,我们将平面的尺寸设置为宽60,高20。在创建完几何体之后我们还需要给plane指定材质,在这里我们使用MeshBasicMaterial()方法来创建一个基本的材质,其颜色为0xcccccc。接下来将两个对象合并到一个名为plane的Mesh(网格)对象中。在将其放入场景之前还要修改其旋转和位置,先将其绕着x轴旋转90度,然后修改其position的x、y和z分量,最后将其加入scene中。
最后
camera.position.x=-30;camera.position.y=40;camera.position.z=30;
camera.lookAt(scene.position);
$("#WebGL-output").append(renderer.domElement);
renderer.render(scene,camera);
我们通过修改camera的位置和使用LookAt函数(对Unity和OpenGL熟悉的应该对此也不陌生)来修改camera的位置和朝向。在这里,我们的lookAt函数指向scene的中心。
最后,我们应该将renderer的输出挂接到HTML页面框架中的<div>元素中;在这里我们使用jQuery来选择正确的输出元素,并告诉 renderer用我们提供的相机来渲染scene。
《添加材质、灯光和阴影》
由于线框的渲染模式不会对灯光产生反应,因此我们需要修改cube和sphere的材质。
先将上一节的例子复制,并改名。
在创建完renderer之后,我们开始创建灯光:
var spotLight=new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
scene.add(spotLight);
上述通过SpotLight()方法来创建的一个探照灯光源,并通过spotLight对象的position.set(-40,60,-10)位置来照射我们的场景。
修改Material的类型为Lambert材质:
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
同时修改cube和sphere的材质类型
同理,我们也可以使用Phong光照模型来产生光照效果,MeshPhongMaterial();
最后,我们开始添加阴影。因为阴影的计算比较消耗计算资源,因此默认情况下Three.js不会渲染阴影。
我们在renderer下面加入
renderer.shadowMapEnabled=true;
在plane创建完成之后加入
plane.receiveShadow=true;
cube.castShadow=true;
sphere.castShadow=true;
spotLight.castShadow=true;
来使其接收阴影。
最后产生的效果如下图:
该节的整体代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example 01.03 - Light and shadow</title>
<script type="text/javascript"
src="../libs/three.js"></script>
<script type="text/javascript"
src="../libs/jquery-3.1.1.js"></script>
<style>
body{
/*set margin to 0 and overflow to hidden,to use the complete page*/
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<!--Div which will hold the Output-->
<div id="WebGL-output">
</div>
<!--Javascript code that runs out Three.js examples-->
<script type="text/javascript">
//once everything is loaded, we run out Three.js stuff.
$(function () {
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var renderer=new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE,0.5);
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.shadowMapType=THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled=true;
var spotLight=new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
spotLight.castShadow=true;
spotLight.shadowMapHeight=4096;
spotLight.shadowMapWidth=4096;
scene.add(spotLight);
var ambientLight=new THREE.AmbientLight(0xffffff);
ambientLight.intensity=0.3;
scene.add(ambientLight);
var axes=new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshPhongMaterial({color:0xffffff});
var plane=new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x=-0.5*Math.PI;
plane.position.x=15;plane.position.y=0;plane.position.z=0;
plane.receiveShadow=true;
scene.add(plane);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshPhongMaterial({color:0xff0000});
var cube=new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.x=-4;cube.position.y=3;cube.position.z=0;
cube.castShadow=true;
scene.add(cube);
var sphereGeometry=new THREE.SphereGeometry(4,20,20);
var sphereMaterial=new THREE.MeshPhongMaterial({color:0x7777ff});
var sphere=new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x=20;sphere.position.y=4;sphere.position.z=2;
sphere.castShadow=true;
scene.add(sphere);
camera.position.x=-30;camera.position.y=40;camera.position.z=30;
camera.lookAt(scene.position);
$("#WebGL-output").append(renderer.domElement);
renderer.render(scene,camera);
});
</script>
</body>
</html>
《简单的动画和帧率监控》
在Three.js中,使用requestAnimationFrame()方法可以指定一个渲染函数,按照浏览器的时间间隔(通常是每秒60帧)来调用该函数。在指定的渲染函数中,可以对场景中的物体的位置 、旋转和缩放等进行更新。
那么在进行动画之前,我们先来引入帧率检测的代码。首先在HTML页面引入stats.js这个库。
<script type="text/javascript" src="../libs/stats.js"></script>
然后再添加一个用于展示统计信息的div
<div id="Stats-output"></div>
最后编写初始化stats的代码:
function initStats() {
var stats=new Stats();
stats.setMode(0);
stats.domElement.style.position='absolute';
stats.domElement.style.left='0px';
stats.domElement.style.top='0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
并在主体代码的开头引入stats对象
var stats=initStats();
下面,我们来编写每一帧需要调用的渲染函数
function renderScene() {
stats.update();
//animate cube
cube.rotation.x+=0.02;cube.rotation.y+=0.02;cube.rotation.z+=0.02;
//animate sphere
step+=0.04;
sphere.position.x=20+(10*Math.cos(step));
sphere.position.y=2+(10*Math.abs(Math.sin(step)));
requestAnimationFrame(renderScene);
renderer.render(scene,camera);
}
该渲染函数在每次调用会更新stats信息,更新方块的旋转和球体的运动位置。最后通过requestAnimationFrame函数来指定renderScene函数为指定时间间隔渲染的函数。最后调用renderer渲染器的render函数重新渲染。
最后我们在代码的主体加入一次对renderScene函数的调用。
本节所有代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example 01.04 - Simple Animation</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-3.1.1.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<style>
body{
/*set margin to 0 and overflow to hidden,to use the complete page*/
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output"></div>
<!--Div which will hold the Output-->
<div id="WebGL-output"></div>
<!--Javascript code that runs out Three.js examples-->
<script type="text/javascript">
//once everything is loaded, we run out Three.js stuff.
function init() {
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var renderer=new THREE.WebGLRenderer();
var stats=initStats();
renderer.setClearColor(0xEEEEEE,0.5);
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.shadowMapType=THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled=true;
var spotLight=new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
spotLight.castShadow=true;
spotLight.shadowMapHeight=4096;
spotLight.shadowMapWidth=4096;
scene.add(spotLight);
var ambientLight=new THREE.AmbientLight(0xffffff);
ambientLight.intensity=0.3;
scene.add(ambientLight);
var axes=new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshPhongMaterial({color:0xffffff});
var plane=new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x=-0.5*Math.PI;
plane.position.x=15;plane.position.y=0;plane.position.z=0;
plane.receiveShadow=true;
scene.add(plane);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshPhongMaterial({color:0xff0000});
var cube=new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.x=-4;cube.position.y=3;cube.position.z=0;
cube.castShadow=true;
scene.add(cube);
var sphereGeometry=new THREE.SphereGeometry(4,20,20);
var sphereMaterial=new THREE.MeshPhongMaterial({color:0x7777ff});
var sphere=new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x=20;sphere.position.y=4;sphere.position.z=2;
sphere.castShadow=true;
scene.add(sphere);
camera.position.x=-30;camera.position.y=40;camera.position.z=30;
camera.lookAt(scene.position);
document.getElementById("WebGL-output").appendChild(renderer.domElement);
renderer.render(scene,camera);
renderScene();
var step=0;
function renderScene() {
stats.update();
//animate cube
cube.rotation.x+=0.02;cube.rotation.y+=0.02;cube.rotation.z+=0.02;
//animate sphere
step+=0.04;
sphere.position.x=20+(10*Math.cos(step));
sphere.position.y=2+(10*Math.abs(Math.sin(step)));
requestAnimationFrame(renderScene);
renderer.render(scene,camera);
}
function initStats() {
var stats=new Stats();
stats.setMode(0);
stats.domElement.style.position='absolute';
stats.domElement.style.left='0px';
stats.domElement.style.top='0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload=init;
</script>
</body>
</html>
《使用dat.GUI来编写一个简单的UI》
dat.GUI为Google公司的一些人创建的库,该库的文档(http://code.google.com/p/dat-gui/ 需翻墙)通过这个库,我们可以实现用slider滑动条来控制立方体的自旋速度和球体的弹跳速度。
首先需要引用dat.GUI.js库
<script type="text/javascript" src="../libs/dat.gui.js"></script>
接下来添加一个JavaScript对象:
var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
};
然后创建一个gui对象并添加控制器:
var gui=new dat.GUI();
gui.add(controls,'rotationSpeed',0,0.5);
gui.add(controls,'bouncingSpeed',0,0.5);
注意,这些代码需要写在渲染函数之前。
接下来修改上一节的renderScene函数中的方块和球体的动画控制代码:
function renderScene() {
stats.update();
//animate cube
cube.rotation.x+=controls.rotationSpeed;cube.rotation.y+=controls.rotationSpeed;cube.rotation.z+=controls.rotationSpeed;
//animate sphere
step+=controls.bouncingSpeed;
sphere.position.x=20+(10*Math.cos(step));
sphere.position.y=2+(10*Math.abs(Math.sin(step)));
requestAnimationFrame(renderScene);
renderer.render(scene,camera);
}
编写完成之后运行效果如下:
本节的完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example 01.05 - dat.GUI UserInterface</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-3.1.1.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body{
/*set margin to 0 and overflow to hidden,to use the complete page*/
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output"></div>
<!--Div which will hold the Output-->
<div id="WebGL-output"></div>
<!--Javascript code that runs out Three.js examples-->
<script type="text/javascript">
//once everything is loaded, we run out Three.js stuff.
function init() {
var scene=new THREE.Scene();
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var renderer=new THREE.WebGLRenderer();
var stats=initStats();
renderer.setClearColor(0xEEEEEE,0.5);
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.shadowMapType=THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled=true;
var spotLight=new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
spotLight.castShadow=true;
spotLight.shadowMapHeight=4096;
spotLight.shadowMapWidth=4096;
scene.add(spotLight);
var ambientLight=new THREE.AmbientLight(0xffffff);
ambientLight.intensity=0.3;
scene.add(ambientLight);
var axes=new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshPhongMaterial({color:0xffffff});
var plane=new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x=-0.5*Math.PI;
plane.position.x=15;plane.position.y=0;plane.position.z=0;
plane.receiveShadow=true;
scene.add(plane);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshPhongMaterial({color:0xff0000});
var cube=new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.x=-4;cube.position.y=3;cube.position.z=0;
cube.castShadow=true;
scene.add(cube);
var sphereGeometry=new THREE.SphereGeometry(4,20,20);
var sphereMaterial=new THREE.MeshPhongMaterial({color:0x7777ff});
var sphere=new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x=20;sphere.position.y=4;sphere.position.z=2;
sphere.castShadow=true;
scene.add(sphere);
camera.position.x=-30;camera.position.y=40;camera.position.z=30;
camera.lookAt(scene.position);
document.getElementById("WebGL-output").appendChild(renderer.domElement);
renderer.render(scene,camera);
var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
};
var gui=new dat.GUI();
gui.add(controls,'rotationSpeed',0,0.5);
gui.add(controls,'bouncingSpeed',0,0.5);
//this renderScene() function should be called after every
renderScene();
var step=0;
function renderScene() {
stats.update();
//animate cube
cube.rotation.x+=controls.rotationSpeed;cube.rotation.y+=controls.rotationSpeed;cube.rotation.z+=controls.rotationSpeed;
//animate sphere
step+=controls.bouncingSpeed;
sphere.position.x=20+(10*Math.cos(step));
sphere.position.y=2+(10*Math.abs(Math.sin(step)));
requestAnimationFrame(renderScene);
renderer.render(scene,camera);
}
function initStats() {
var stats=new Stats();
stats.setMode(0);
stats.domElement.style.position='absolute';
stats.domElement.style.left='0px';
stats.domElement.style.top='0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload=init;
</script>
</body>
</html>
《动态改变渲染大小》
在使用Three.js的时候,我们还可以根据窗口大小的改变来调整渲染的大小。
在这里我们需要添加一个onSizeChanged函数
function onSizeChanged() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
编写完该函数之后我们需要对窗口大小改变的事件增加监听:
window.addEventListener('resize', onSizeChanged, false);
注意,这里要把renderer、camera等变量定义成作用域更广的变量,具体参见详细代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example 01.06 - Resize</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/jquery-3.1.1.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
<style>
body{
/*set margin to 0 and overflow to hidden,to use the complete page*/
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output"></div>
<!--Div which will hold the Output-->
<div id="WebGL-output"></div>
<!--Javascript code that runs out Three.js examples-->
<script type="text/javascript">
//once everything is loaded, we run out Three.js stuff.
var scene;
var camera;
var stats;
var renderer;
function init() {
scene=new THREE.Scene();
camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
renderer=new THREE.WebGLRenderer();
stats=initStats();
renderer.setClearColor(0xEEEEEE,0.5);
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.shadowMapType=THREE.PCFSoftShadowMap;
renderer.shadowMapEnabled=true;
var spotLight=new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
spotLight.castShadow=true;
spotLight.shadowMapHeight=4096;
spotLight.shadowMapWidth=4096;
scene.add(spotLight);
var ambientLight=new THREE.AmbientLight(0xffffff);
ambientLight.intensity=0.3;
scene.add(ambientLight);
var axes=new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60,20,1,1);
var planeMaterial = new THREE.MeshPhongMaterial({color:0xffffff});
var plane=new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x=-0.5*Math.PI;
plane.position.x=15;plane.position.y=0;plane.position.z=0;
plane.receiveShadow=true;
scene.add(plane);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshPhongMaterial({color:0xff0000});
var cube=new THREE.Mesh(cubeGeometry,cubeMaterial);
cube.position.x=-4;cube.position.y=3;cube.position.z=0;
cube.castShadow=true;
scene.add(cube);
var sphereGeometry=new THREE.SphereGeometry(4,20,20);
var sphereMaterial=new THREE.MeshPhongMaterial({color:0x7777ff});
var sphere=new THREE.Mesh(sphereGeometry,sphereMaterial);
sphere.position.x=20;sphere.position.y=4;sphere.position.z=2;
sphere.castShadow=true;
scene.add(sphere);
camera.position.x=-30;camera.position.y=40;camera.position.z=30;
camera.lookAt(scene.position);
document.getElementById("WebGL-output").appendChild(renderer.domElement);
//effect.render(scene,camera);
var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
};
var gui=new dat.GUI();
gui.add(controls,'rotationSpeed',0,0.5);
gui.add(controls,'bouncingSpeed',0,0.5);
//this renderScene() function should be called after every
renderScene();
var step=0;
function renderScene() {
stats.update();
//animate cube
cube.rotation.x+=controls.rotationSpeed;cube.rotation.y+=controls.rotationSpeed;cube.rotation.z+=controls.rotationSpeed;
//animate sphere
step+=controls.bouncingSpeed;
sphere.position.x=20+(10*Math.cos(step));
sphere.position.y=2+(10*Math.abs(Math.sin(step)));
requestAnimationFrame(renderScene);
renderer.render(scene,camera);
}
function initStats() {
var stats=new Stats();
stats.setMode(0);
stats.domElement.style.position='absolute';
stats.domElement.style.left='0px';
stats.domElement.style.top='0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onload=init;
window.addEventListener('resize', onResize, false);
</script>
</body>
</html>
那么到这里,我们就完成了对Three.js的入门学习。下面我们会更加深入的讲解Three.js。
参考资料:
Learning Three.js The JavaSctipt 3D Library for WebGL ·Jos Dirksen