ThreeJS初体验
Posted 钱塘风华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreeJS初体验相关的知识,希望对你有一定的参考价值。
如何搭建ThreeJS的开发环境
我们只要简单地在html文档中引入three.js,然后在script标签内写上一个初始化函数,并且挂载在window.onload上就好了
<html>
<head>
<title>threeJS-DEMO</title>
<script src="./js/three.js"></script>
<style>
</style>
</head>
<body>
<div id="WebGL-output">
</div>
<script type="text/javascript">
function init() {
}
window.onload = init
</script>
</body>
</html>
如何渲染场景
创建THREE.Scene对象;
添加摄像机;
添加光源;
添加需要渲染的物体;
使用渲染器对象渲染场景。
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.setClearColorHex();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
// 以下分别创建了要渲染的物体,包括一个平面、立方体和球体,并添加到了场景中
var planeGeometry = new THREE.PlaneGeometry(60, 20);
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.BoxGeometry(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);
// 将渲染的结果追加到div中
document.getElementById("WebGL-output").appendChild(renderer.domElement);
// 告诉渲染器使用指定的摄像机来渲染场景
renderer.render(scene, camera);
}
给场景添加阴影和动画效果
在ThreeJS中基本材质 THREE.MeshBasicMaterial不会对光源有任何反应,所以将之前的基本材质改为材质 THREE.MeshLambertMaterial
将以上代码 15、26、36行分别改为:
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xcccccc});
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
添加一个光源
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
scene.add(spotLight);
由于渲染阴影需要耗费大量的计算资源,ThreeJS默认不会渲染阴影,所以需要告诉渲染器渲染阴影
renderer.shadowMapEnabled = true;
指定哪个物体投射阴影,哪个物体接受阴影
plane.receiveShadow = true;
...
cube.castShadow = true;
...
sphere.castShadow = true;
定义能够产生阴影的光源
spotLight.castShadow = true;
引入 requestAnimationFrame() 方法来产生动画效果,创建一个处理渲染的方法
var step = 0;
function renderScene() {
// 让正方体围绕其轴旋转
cube.rotation.x += 0.02;
cube.rotation.y += 0.02;
cube.rotation.z += 0.02;
// 使球体抛物线弹跳,step定义弹跳速度
step += 0.04;
sphere.position.x = 20 + ( 10 * (Math.cos(step)));
sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));
// 使用requestAnimationFrame使得动画可以持续运行
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
}
...
// 第二段代码55行不再调用renderer.render(scene, camera)
// 而使调用renderScene()来启动动画
renderScene();
辅助库添加简化试验流程
添加辅助库 dat.GUI 和 stats.js 创建用户控制界面和快速获取场景渲染时的帧数
// head中引入 dat.gui.js 和 stats.js
<script src="./js/dat.gui.js"></script>
<script src="./js/stats.js"></script>
辅助库需要的js代码不再赘述,见最后整体代码
场景对浏览器的自适应
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', onResize, false);
整体代码如下:
<html>
<head>
<title>threeJS-DEMO</title>
<script src="./js/three.js"></script>
<script src="./js/stats.js"></script>
<script src="./js/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output"></div>
<div id="WebGL-output"></div>
<script>
var camera;
var scene;
var renderer;
function init() {
var stats = initStats();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
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.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
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.MeshLambertMaterial({color: 0x7777ff});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 20;
sphere.position.y = 0;
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 ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
scene.add(spotLight);
document.getElementById("WebGL-output").appendChild(renderer.domElement);
var step = 0;
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);
renderScene();
function renderScene() {
stats.update();
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;
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>
以上是关于ThreeJS初体验的主要内容,如果未能解决你的问题,请参考以下文章