第一个threejs程序
<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
</head>
<body>
<div id="threejs-example">
</div>
<script type="text/javascript">
function init() {
// 新建场景
var scene = new THREE.Scene();
// 设置相机
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// 构造渲染器,这里使用WebGL渲染器
var renderer = new THREE.WebGLRenderer();
// 设置背景色
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
// 向场景中添加坐标轴
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// 新建一个平面plane
var planeGeometry = new THREE.PlaneGeometry(60, 20); // 长60,宽20的平面
var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
// 确定平面坐标
plane.rotation.x = -0.5 * Math.PI; // 沿x轴旋转90度
plane.position.x = 15; // 在x,y,z三个方向上的偏移
plane.position.y = 0;
plane.position.z = 0;
// 向场景中添加平面
scene.add(plane);
// 创建一个方块cube
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true}); // 打开wireframe则可以看到物体的结构框架
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// 确定方块坐标
cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;
scene.add(cube);
// 创建一个球体sphere
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); // 使用lookAt()函数将相机指向场景的中心
document.getElementById("threejs-example").appendChild(renderer.domElement);
renderer.render(scene, camera); // 渲染场景
}
window.onload = init;
</script>
</body>
</html>
渲染阴影——添加光源并更改材质
MeshBasicMaterial基本材质不能对场景中的光源产生反应,它只能按照指定的颜色渲染物体,threejs中提供了两种材质可以对光源产生反应——MeshLambertMaterial和MeshPhongMaterial材质。
由于渲染阴影要消耗大量的计算资源,因此默认情况下threejs并不生成阴影。
要使threejs渲染出阴影效果,除了打开threejs的阴影渲染许可(renderer.shadowMapEnabled = true)外,还要确定哪些物体是接收阴影的,哪些物体是发出阴影的,分别打开相应物体Mesh对象的receiveShadow和castShadow设置。
另外,还要使场景中的光源渲染出阴影。
<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
</head>
<body>
<div id="threejs-example"></div>
<script type="text/javascript">
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();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
// 使threejs允许场景渲染出阴影(由于渲染阴影要消耗大量的计算资源,因此默认情况下threejs并不生成阴影)
renderer.shadowMapEnabled = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// 新建一个平面plane
var planeGeometry = new THREE.PlaneGeometry(60, 20); // 设置物体材质为MeshLambertMaterial,它可以对光源做出反应
var planeMaterial = new THREE.MeshLambertMaterial({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;
plane.receiveShadow = true;
scene.add(plane);
// 创建一个方块cube
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
// var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
var cubeMaterial = new THREE.MeshLambertMaterial({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);
// 创建一个球体sphere
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({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); // 使用lookAt函数将相机指向场景的中心
// 向场景中添加光源
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( -40, 60, -10 );
spotLight.castShadow = true; // 让聚光灯光源发出阴影
scene.add(spotLight);
document.getElementById("threejs-example").appendChild(renderer.domElement);
renderer.render(scene, camera);
}
window.onload = init;
</script>
</body>
</html>
持续渲染场景和开启渲染帧率监测器stats
可以利用requestAnimationFrame()写一个函数renderScene()达到持续渲染场景的效果,而要开启渲染帧率监测器,则需要引入stats.js,初始化stats对象后,需要在renderScene()函数中使用update()更新帧率。
<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
</head>
<body>
<div id="threejs-example"></div>
<div id="Stats-output"></div>
<script type="text/javascript">
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();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// 新建一个平面plane
var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshLambertMaterial({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;
plane.receiveShadow = true;
scene.add(plane);
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({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);
// 创建一个球体sphere
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({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);
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( -40, 60, -10 );
spotLight.castShadow = true;
scene.add(spotLight);
document.getElementById("threejs-example").appendChild(renderer.domElement);
// 利用requestAnimationFrame()写一个函数达到持续渲染场景的效果
var stats = initStats(); // stats的初始化必须在renderScene()调用之前(因为renderScene()函数中要使用stats实例对象)
renderScene();
function renderScene() {
stats.update(); // 刷新帧率
renderer.render(scene, camera);
requestAnimationFrame(renderScene);
}
function initStats() {
// 初始化帧率监测器
var stats = new Stats();
stats.setMode(0); // 模式值: 0: fps, 1: ms
// 把帧率监测器放在屏幕的左边
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>
添加动画交互
场景持续渲染时就可以在场景中添加一些交互动画了,在renderScene()函数中添加更改方块旋转角度和更改球体坐标的代码,即可实现动画。
<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
</head>
<body>
<div id="threejs-example"></div>
<div id="Stats-output"></div>
<script type="text/javascript">
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();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// 新建一个平面plane
var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshLambertMaterial({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;
plane.receiveShadow = true;
scene.add(plane);
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({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);
// 创建一个球体sphere
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({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);
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( -40, 60, -10 );
spotLight.castShadow = true;
scene.add(spotLight);
document.getElementById("threejs-example").appendChild(renderer.domElement);
var stats = initStats();
renderScene();
var step = 0;
function renderScene() {
stats.update();
// 方块旋转
cube.rotation.x += 0.02;
cube.rotation.y += 0.02;
cube.rotation.z += 0.02;
// 弹跳球
step += 0.04; // 弹跳速度
sphere.position.x = 20+( 10* Math.cos(step) );
sphere.position.y = 2 + ( 10*Math.abs(Math.sin(step)));
renderer.render(scene, camera);
requestAnimationFrame(renderScene);
}
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库
通过引入dat.gui.js库来生成一个控制界面,通过滑动条来控制方块的旋转速度和球体的弹跳速度。
<!DOCTYPE html>
<html>
<head>
<title>第一个threejs程序</title>
<script type="text/javascript" src="../libs/three.js"></script>
<script type="text/javascript" src="../libs/stats.js"></script>
<script type="text/javascript" src="../libs/dat.gui.js"></script>
</head>
<body>
<div id="threejs-example"></div>
<div id="Stats-output"></div>
<script type="text/javascript">
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();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// 新建一个平面plane
var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshLambertMaterial({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;
plane.receiveShadow = true;
scene.add(plane);
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({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);
// 创建一个球体sphere
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({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);
var spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( -40, 60, -10 );
spotLight.castShadow = true;
scene.add(spotLight);
document.getElementById("threejs-example").appendChild(renderer.domElement);
var controls = new function () {
this.rotationSpeed = 0.02;
this.bouncingSpeed = 0.03;
};
var gui = new dat.GUI();
gui.add(controls, 'rotationSpeed', 0, 0.5); // 取值范围是0 -- 0.5
gui.add(controls, 'bouncingSpeed', 0, 0.5); // GUI控制变量bouncingSpeed的取值
var stats = initStats();
var step = 0;
renderScene(); // 在renderScene()函数中使用到的变量必须在调用点之前被定义
function renderScene() {
stats.update();
// 使用dat.GUI控制方块的旋转速度
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;
// 使用dat.GUI控制球的弹跳速度
step += controls.bouncingSpeed;
sphere.position.x = 20 + ( 10 * (Math.cos(step)));
sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));
renderer.render(scene, camera);
requestAnimationFrame(renderScene);
}
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>