three.js入门(4) 场景的作用

时间:2021-08-10 05:55:50

在前面我们已经创建了一个new THREE.Scene()对象,已经了解了一个场景想要显示任何东西需要三种类型的组件:

组件 描述
相机 决定哪些东西在屏幕上渲染
光源 对材质如何显示,以及生成阴影时材质如何使用产生影响
物体 相机里主要的渲染对象,如方块、球体


THREE.Scene()就像是所有这些对象的容器。下面是对场景对象最重要的函数

函数/属性 描述
add(Object) 添加对象到场景中
children 返回场景中所有对象的列表,包括相机和光源
getChildByName(name) 利用name属性,返回场景中特定的对象
remove(Object) 把对象从场景中删除
traverse(function) 通过traverse这个函数,我们可以通过回调函数访问场景对象及其子对象
fog 通过这个属性,可以设置场景中的雾化效果,它可以渲染出一层雾气
overrideMaterial 通过这个属性,可以强制场景中的所有物体都使用相同的材质
background 通过这个属性,可以设置场景的背景,它总是第一个被渲染,可以是Color、纹理Texture覆盖、或者CubeTexture


我们通过一个例子来了解这些方法和属性:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>three.js入门(4)</title>
<script src="lib/three.js"></script>
<script src="lib/stats.min.js"></script>
<script src="lib/dat.gui.min.js"></script>
<style>
*{margin: 0;padding: 0;}
</style>
</head>

<body>
<script>
// 渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.setClearColor(0xff0000);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
// 场景
var scene = new THREE.Scene();

// 照相机
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(-30, 40, 30);
camera.lookAt(new THREE.Vector3(0, 0, 0));
// 辅助轴
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// 平面
var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.set(0, 0, 0);
plane.rotation.x = -0.5 * Math.PI;
plane.receiveShadow = true;
scene.add(plane);

// 灯光
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-10, 20, -10);
spotLight.castShadow = true;
scene.add(spotLight);
// 灯光辅助
var spotLightHelper = new THREE.SpotLightHelper(spotLight);
scene.add(spotLightHelper);
// 环境光
var ambientLight = new THREE.AmbientLight(0x0c0c0c);
scene.add(ambientLight);

//统计对象,用户显示FPS
var stats = initStats();

// 用来保存我们想要通过dat.gui修改的那些变量,或点击后运行的函数
var ctrls = {
//旋转速度
rotationSpeed:0.02,
number:scene.children.length,//创建中对象的数量
addBox:function(){//添加立方体
var boxSize = Math.ceil((Math.random() * 3));
var boxGeometry = new THREE.BoxGeometry(boxSize, boxSize, boxSize);
var boxMaterial = new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff});
var box = new THREE.Mesh(boxGeometry, boxMaterial);
box.castShadow = true;
//设置box的name属性,使得可以通过getChildByName
box.name = "box-" + scene.children.length;
// 随机位置
box.position.x = -30 + Math.round((Math.random() * planeGeometry.parameters.width));
box.position.y = Math.round((Math.random() * 5));
box.position.z = -10 + Math.round((Math.random() * planeGeometry.parameters.height));

//添加box对象到场景
scene.add(box);
//更新number的数量
this.number = scene.children.length;
},
removeBox : function () {//删除立方体
//获取场景中所有子对象列表,包括灯光和相机
var allChildren = scene.children;
var lastObject = allChildren[allChildren.length - 1];
if (lastObject instanceof THREE.Mesh) {
//从场景中删除对象
scene.remove(lastObject);
this.number = scene.children.length;
}
},
addFog : function(){// 在场景中添加雾化效果
// 雾化有两种
// 1.线性雾,密度随着距离的增加呈线性增长
// new THREE.Fog( hex, near, far )
// hex 是一个十六进制整数或CSS样式的字符串指定颜色
// near 开始应用雾的最小距离。距离当前相机小于near个单位的对象,将不会受到雾的影响。缺省为 1.
// far 结束应用雾的最大距离。距离当前相机大于far个单位的对象,将不会受到雾的影响。缺省为 1000.
// 2.指数雾,密度随距离呈指数级增长。
// new THREE.FogExp2(hex, density)
// hex 是一个十六进制整数或CSS样式的字符串指定颜色
// density 定义雾密度的增长速度。缺省为 0.00025.
scene.fog = new THREE.Fog(0xffffff,0.015,100);
},
overrideMaterial:function(){
//强制场景中的所有物体都使用相同的材质
scene.overrideMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
},
background:function(){
//设置场景的背景,它总是第一个被渲染,可以设置为Color来设置它的渲染清除颜色,同renderer.setClearColor(0xff0000);
//也可以设置纹理Texture覆盖canvas或CubeTexture
scene.background = new THREE.Color(0xffffff);
}
}
//初始化对象,并添加变量的取值范围
var gui = new dat.GUI();
gui.add(ctrls, 'rotationSpeed', 0, 0.5);
gui.add(ctrls, 'addBox');
gui.add(ctrls, 'removeBox');
gui.add(ctrls, 'addFog');
gui.add(ctrls, 'overrideMaterial');
gui.add(ctrls, 'background');
//添加并监听number变化
gui.add(ctrls, 'number').listen();

// 调用渲染函数
render();

var step = 0;
function render() {
stats.update();
// 访问场景对象及其子对象,如果子对象是Mesh对象,这改变他们的xyz
scene.traverse(function (e) {
if (e instanceof THREE.Mesh && e != plane) {
e.rotation.x += ctrls.rotationSpeed;
e.rotation.y += ctrls.rotationSpeed;
e.rotation.z += ctrls.rotationSpeed;
}
});
// 等同于
// function fn(callback){
// callback(scene)
// for (var i = 0; i < scene.children.length; i++) {
// callback(scene.children[i])
// }
// }
// fn(function(e){
// if (e instanceof THREE.Mesh && e != plane) {
// e.rotation.x += ctrls.rotationSpeed;
// e.rotation.y += ctrls.rotationSpeed;
// e.rotation.z += ctrls.rotationSpeed;
// }
// })

requestAnimationFrame(render);
renderer.render(scene, camera);
}
//初始化统计对象
function initStats(){
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.left = '0px';
document.body.appendChild(stats.domElement);
return stats;
}
</script>
</body>
</html>

渲染结果如下:

three.js入门(4) 场景的作用

运行这个例子可以通过点击
addBox添加立方体,
removeBox 删除立方体,
addFog 添加雾化效果,
overrideMaterial 强制场景中的所有物体的材质,
background 设置场景的背景,
children:控制台输出场景中的对象,
通过number可以查看场景中对象的个数

通过例子应该可以知道场景中方法和属性的使用方式,注释的很清楚,就不多说了!如果不清楚dat.gui的使用,看three.js入门(3)或者详细使用方式看这里

点击查看 示例代码