半小时学会制作三维扩散光圈(three.js实战2)
Posted 点燃火柴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了半小时学会制作三维扩散光圈(three.js实战2)相关的知识,希望对你有一定的参考价值。
1.demo效果
2. 实现思路
使用CylinderGeometry创建圆柱,圆柱的顶面和底面隐藏,侧面使用纹理贴图材质。在render函数中,使圆柱的半径不断变大,使圆柱的材质可见度不断降低,从而实现扩散的光圈效果
3. 实现要点
3.1 创建圆柱
-
创建圆柱几何体
使用THREE.CylinderGeometry类创建圆柱几何体 -
创建圆柱材质
这里分别创建圆柱的侧面、顶面和底面的材质,放到一个数组中,侧面材质使用加载的纹理作为纹理贴图,是否透明属性transparent设置为true;顶面和底面的材质的opacity属性设置为0,表示不可见。 -
创建圆柱网格对象
使用上面创建的几何体和材质使用THREE.Mesh直接创建即可,然后添加到场景中
示例代码如下
//创建圆柱
let geometry = new THREE.CylinderGeometry(4, 4, 4, 64);
//加载纹理
let texture = new THREE.TextureLoader().load('../assets/textures/texture01.png');
texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //每个都重复
texture.repeat.set(1, 1);
texture.needsUpdate = true;
let materials = [
//圆柱侧面材质,使用纹理贴图
new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide,
transparent: true
}),
//圆柱顶材质
new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0,
side: THREE.DoubleSide
}),
//圆柱底材质
new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0,
side: THREE.DoubleSide
})
];
cylinderMesh = new THREE.Mesh(geometry, materials);
scene.add(cylinderMesh);
3.2 圆柱扩散动画
这里定义一个记录圆柱半径的cylinderRadius变量,和记录材质可见度的变量,然后半径不断扩大,可见度不断降低,让后把这两个变化的属性设置到圆柱对象上,最后在render中调用该函数即可
let cylinderRadius = 0;
let cylinderOpacity= 1;
//圆柱光圈扩散动画
function cylinderAnimate() {
cylinderRadius += 0.01;
cylinderOpacity-= 0.003;
if (cylinderRadius > 4) {
cylinderRadius = 0;
cylinderOpacity= 1;
}
if (cylinderMesh) {
cylinderMesh.scale.set(1 + cylinderRadius, 1, 1 + cylinderRadius); //圆柱半径增大
cylinderMesh.material[0].opacity = cylinderOpacity; //圆柱可见度减小
}
}
4. demo代码
<!DOCTYPE html>
<html>
<head>
<title>光圈扩散</title>
<script type="text/javascript" src="../three/build/three.js"></script>
<script type="text/javascript" src="../three/examples/js/controls/OrbitControls.js"></script>
<script type="text/javascript" src="../three/examples/js/libs/stats.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output"></div>
<div id="WebGL-output"></div>
<script type="text/javascript">
var scene, camera, renderer, cylinderMesh, stats, controls, clock;
function initScene() {
scene = new THREE.Scene();
//用一张图加载为纹理作为场景背景
scene.background = new THREE.TextureLoader().load("../assets/textures/starry-deep-outer-space-galaxy.jpg");
}
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(20, 30, 50);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
function initLight() {
//添加环境光
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);
}
function initModel() {
//创建圆柱
let geometry = new THREE.CylinderGeometry(4, 4, 4, 64);
//加载纹理
let texture = new THREE.TextureLoader().load('../assets/textures/texture01.png');
texture.wrapS = texture.wrapT = THREE.RepeatWrapping; //每个都重复
texture.repeat.set(1, 1);
texture.needsUpdate = true;
let materials = [
//圆柱侧面材质,使用纹理贴图
new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide,
transparent: true
}),
//圆柱顶材质
new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0,
side: THREE.DoubleSide
}),
//圆柱底材质
new THREE.MeshBasicMaterial({
transparent: true,
opacity: 0,
side: THREE.DoubleSide
})
];
cylinderMesh = new THREE.Mesh(geometry, materials);
scene.add(cylinderMesh);
initPlane()
}
//创建底面
function initPlane() {
const planeGeometry = new THREE.PlaneGeometry(50, 50, 1, 1); //创建一个平面几何对象
//材质
const planeMaterial = new THREE.MeshLambertMaterial({
color: 0x080631,
transparent: true,
opacity: 0.8
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
//设置平面位置
plane.rotation.x = -0.5 * Math.PI;
plane.position.set(0, -2, 0);
//平面添加到场景中
scene.add(plane);
}
//初始化渲染器
function initRender() {
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setClearColor(0x111111, 1); //设置背景颜色
renderer.setSize(window.innerWidth, window.innerHeight);
//renderer.shadowMap.enabled = true; //显示阴影
document.getElementById("WebGL-output").appendChild(renderer.domElement);
}
//初始化轨道控制器
function initControls() {
clock = new THREE.Clock(); //创建THREE.Clock对象,用于计算上次调用经过的时间
controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.autoRotate = true; //是否自动旋转
}
let cylinderRadius = 0;
let cylinderOpacity = 1;
//圆柱光圈扩散动画
function cylinderAnimate() {
cylinderRadius += 0.01;
cylinderOpacity -= 0.003;
if (cylinderRadius > 4) {
cylinderRadius = 0;
cylinderOpacity = 1;
}
if (cylinderMesh) {
cylinderMesh.scale.set(1 + cylinderRadius, 1, 1 + cylinderRadius); //圆柱半径增大
cylinderMesh.material[0].opacity = cylinderOpacity; //圆柱可见度减小
}
}
//性能监控
function initStats() {
stats = new Stats();
stats.setMode(0); //0: fps, 1: ms
document.getElementById("Stats-output").appendChild(stats.domElement);
}
function render() {
cylinderAnimate(); //圆柱光圈扩散更新
stats.update();
const delta = clock.getDelta(); //获取自上次调用的时间差
controls.update(delta) //控制器更新
requestAnimationFrame(render);
renderer.render(scene, camera);
}
//页面初始化
function init() {
initScene();
initCamera();
initLight();
initModel();
initRender();
initStats();
initControls();
render();
}
window.onload = init;
</script>
</body>
</html>
以上是关于半小时学会制作三维扩散光圈(three.js实战2)的主要内容,如果未能解决你的问题,请参考以下文章
既有方向又会动的线,包你学会制作按箭头方向流动的线(three.js实战3)
三维空间中绘制点线面UV贴图,万能的BufferGeometry(three.js实战4)