Appearance
展示线
关键代码
js
// 创建球体
const sphere = new THREE.SphereGeometry(150, 20, 20);
const material = new THREE.MeshBasicMaterial({
wireframe: true,
color: 0xffffff
});
const mesh = new THREE.Mesh(sphere, material);
mesh.position.set(0, 0, 0);
scene.add(mesh);如上所见,我们渲染一个几何体其实说白了都是一些顶点连接而成的
点材质
如果我们只想渲染这些点,而不要线呢,也就是下面这样
我们可以通过点材质来实现
关键代码
js
const sphere = new THREE.SphereGeometry(150, 20, 20);
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.size = 3.5;
pointsMmaterial.color = new THREE.Color(0xffff00);
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(sphere, pointsMmaterial);
scene.add(points);星空效果
看到这里,想起来我们之前学过的自定义顶点,那么我们是不是可以用自定义顶点来实现一个星空效果呢
关键代码
js
const geometry = new THREE.BufferGeometry();
const vertices = [];
const colors = [];
for (let i = 0; i < 10000; i++) {
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
vertices.push(x, y, z);
colors.push(Math.random(), Math.random(), Math.random());
}
// 给自定义顶点设置颜色
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 给自定义顶点设置位置
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.size = 3.5;
// 设置了颜色默认是不生效,必须开启自定义着色器
pointsMmaterial.vertexColors = true;
pointsMmaterial.color = new THREE.Color(0xffff00);
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(geometry, pointsMmaterial);
scene.add(points);星空效果升级
做到这里,发现都是正方形的星星,太丑了,利用图片贴图,美化下
关键代码
js
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(star);
const geometry = new THREE.BufferGeometry();
const vertices = [];
const colors = [];
for (let i = 0; i < 10000; i++) {
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
vertices.push(x, y, z);
colors.push(Math.random(), Math.random(), Math.random());
}
// 给自定义顶点设置颜色
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 给自定义顶点设置位置
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.map = texture;
// 开启透明
pointsMmaterial.transparent = true;
// 设置透明贴图
pointsMmaterial.alphaMap = texture;
pointsMmaterial.depthWrite = false;
pointsMmaterial.size = 6.5;
// 设置了颜色默认是不生效,必须开启自定义着色器
pointsMmaterial.vertexColors = true;
pointsMmaterial.color = new THREE.Color(0xffff00);
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(geometry, pointsMmaterial);
scene.add(points);雪花飞舞
在之前星空的贴图下其实可以实现雪花飞舞的效果,换个图片,让雪花动起来就可以了
关键代码
js
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(xuehua);
const geometry = new THREE.BufferGeometry();
const vertices = [];
const colors = [];
for (let i = 0; i < 100000; i++) {
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
vertices.push(x, y, z);
colors.push(255, 255, 255);
}
// 给自定义顶点设置颜色
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 给自定义顶点设置位置
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.map = texture;
// 开启透明
pointsMmaterial.transparent = true;
// 设置透明贴图
pointsMmaterial.alphaMap = texture;
pointsMmaterial.depthWrite = false;
pointsMmaterial.size = 14.5;
// 设置了颜色默认是不生效,必须开启自定义着色器
pointsMmaterial.vertexColors = true;
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(geometry, pointsMmaterial);
scene.add(points);以上雪花就完成了,怎么动起来的呢? 在render函数改变下位置就行了
js
xuehuapoints.rotation.x += 0.003;
xuehuapoints.rotation.y += 0.002;完整代码
html
<template>
<div id="canvas"></div>
</template>
<script setup>
import * as THREE from 'three';
import { onMounted } from 'vue';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { useRoute } from 'vue-router';
import star from '../assets/star.png';
import xuehua from '../assets/xuehua.png';
const route = useRoute();
onMounted(() => {
const scene = new THREE.Scene();
// 查看线的构成几何体
if (route.query.type === '1') {
// 创建球体
const sphere = new THREE.SphereGeometry(150, 20, 20);
const material = new THREE.MeshBasicMaterial({
wireframe: true,
color: 0xffffff
});
const mesh = new THREE.Mesh(sphere, material);
mesh.position.set(0, 0, 0);
scene.add(mesh);
}
// 查看点
if (route.query.type === '2') {
const sphere = new THREE.SphereGeometry(150, 20, 20);
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.size = 3.5;
pointsMmaterial.color = new THREE.Color(0xffff00);
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(sphere, pointsMmaterial);
scene.add(points);
}
// 利用自定义顶点生成星河的感觉
if (route.query.type === '3') {
const geometry = new THREE.BufferGeometry();
const vertices = [];
const colors = [];
for (let i = 0; i < 10000; i++) {
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
vertices.push(x, y, z);
colors.push(Math.random(), Math.random(), Math.random());
}
// 给自定义顶点设置颜色
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 给自定义顶点设置位置
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.size = 3.5;
// 设置了颜色默认是不生效,必须开启自定义着色器
pointsMmaterial.vertexColors = true;
pointsMmaterial.color = new THREE.Color(0xffff00);
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(geometry, pointsMmaterial);
scene.add(points);
}
// 贴个星星图 看上去更好看
if (route.query.type === '4') {
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(star);
const geometry = new THREE.BufferGeometry();
const vertices = [];
const colors = [];
for (let i = 0; i < 10000; i++) {
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
vertices.push(x, y, z);
colors.push(Math.random(), Math.random(), Math.random());
}
// 给自定义顶点设置颜色
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 给自定义顶点设置位置
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.map = texture;
// 开启透明
pointsMmaterial.transparent = true;
// 设置透明贴图
pointsMmaterial.alphaMap = texture;
pointsMmaterial.depthWrite = false;
pointsMmaterial.size = 6.5;
// 设置了颜色默认是不生效,必须开启自定义着色器
pointsMmaterial.vertexColors = true;
pointsMmaterial.color = new THREE.Color(0xffff00);
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(geometry, pointsMmaterial);
scene.add(points);
}
let xuehuapoints = null;
// 做个雪花飞舞的感觉
if (route.query.type === '5') {
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(xuehua);
const geometry = new THREE.BufferGeometry();
const vertices = [];
const colors = [];
for (let i = 0; i < 100000; i++) {
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
vertices.push(x, y, z);
colors.push(255, 255, 255);
}
// 给自定义顶点设置颜色
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// 给自定义顶点设置位置
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const pointsMmaterial = new THREE.PointsMaterial();
pointsMmaterial.map = texture;
// 开启透明
pointsMmaterial.transparent = true;
// 设置透明贴图
pointsMmaterial.alphaMap = texture;
pointsMmaterial.depthWrite = false;
pointsMmaterial.size = 14.5;
// 设置了颜色默认是不生效,必须开启自定义着色器
pointsMmaterial.vertexColors = true;
// 近大远小的感觉 默认是 false就是一样大
// pointsMmaterial.sizeAttenuation = false;
const points = new THREE.Points(geometry, pointsMmaterial);
xuehuapoints = points;
scene.add(points);
}
// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.shadowMap.enabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
// 注意 位置不要太大 不然可能会让后面的往上飞的感觉
const camera = new THREE.PerspectiveCamera(60,
window.innerWidth / window.innerHeight, 1,
route.query.type === '5' ? 300 : 3000);
camera.position.set(2, 142, 407);
camera.lookAt(0, 0, 0);
const controls = new OrbitControls(camera, renderer.domElement);
document.getElementById('canvas').appendChild(renderer.domElement);
function render() {
renderer.render(scene, camera);
// 让雪花动起来
if (route.query.type === '5') {
xuehuapoints.rotation.x += 0.003;
xuehuapoints.rotation.y += 0.002;
// xuehuapoints.rotation.z += 0.002;
}
requestAnimationFrame(render);
}
render();
window.onresize = () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
};
});
</script>