一篇文章掌握三維擴散光圈實作
- 1.demo效果
- 2. 實作思路
- 3. 實作要點
- 3.1 創建圓柱
- 3.2 圓柱擴散影片
- 4. demo代碼
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>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287467.html
標籤:其他
