粒子渐变色 需要材质颜色 和 BufferGeometry.colors的配合使用
设置颜色的时候 大概需要调整到图上这个颜色拾取器的位置上
<template>
<div>
<div class="main" ref="box" style="
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
align-content: center;
">
<h1 v-if="loading">loading...h1>
<i v-if="loading" style="
font-size: 36px;
margin: 12px 0 8px;
transition: transform 0.3s ease-in-out;
will-change: transform;
"><svg viewBox="0 0 1024 1024" width="1em" height="1em" aria-hidden="true" focusable="false"
class="anticon-loading">
<path
d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9 437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z">
path>
svg>i>
div>
div>
template>
<script lang="ts">
import {
WebGLRenderer, //渲染器
Scene, //场景
PerspectiveCamera, //相机
Color, //颜色
AxesHelper, //辅助线
Points, //粒子/点
PointsMaterial, //粒子/点材质
BufferGeometry, //容器
BufferAttribute,
MathUtils,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; //镜头控制
import { defineComponent, ref, onMounted, watch } from "vue";
import * as dat from "dat.gui"; //调试插件
import Stats from "three/examples/jsm/libs/stats.module.js"; //性能监控插件
export default defineComponent({
setup() {
const loading = ref(true);
//提前创建好调试插件
const gioData = new dat.GUI(); //测试插件
gioData.domElement.style.display = "none"; //初始不显示 加载完成再显示
const box = ref<HTMLElement | null>(null); //ref获取dom
const scence: Scene = new Scene(); //场景
const camera = new PerspectiveCamera( //新建相机
120, //摄像机视锥体垂直视野角度
window.innerWidth / window.innerHeight, //摄像机视锥体长宽比
0.1, //摄像机视锥体近端面
10000 //摄像机视锥体远端面
);
const stats = Stats(); //性能监控
var gui = {
color: "#010136",
number: 3000,
size: 2,
Attenuation: false,
x: 100,
y: 100,
z: 100,
vertexColors: true
};
var orbitControls: OrbitControls; //摄像机控制
var rander: WebGLRenderer; //渲染器
var xAxis: AxesHelper; //坐标轴
var points: Points; //点
var pointsMaterial: PointsMaterial; //点样式
var geometry: BufferGeometry; //点定义的矩形
// 渲染器方法
function randerFun() {
rander = new WebGLRenderer({ antialias: true, alpha: true }); //新建渲染器 antialias 否执行抗锯齿
rander.setClearColor(0x000000, 1); //更改渲染器颜色为默认
}
randerFun();
//新建场景
function scenceFun() {
scence.name = "场景"; //场景名字
camera.name = "相机"; //相机名字
camera.position.set(0, 0, 1); //相机位置
orbitControls = new OrbitControls(camera, rander.domElement); //相机控制插件 实现拖拽渲染
orbitControls.autoRotate = true;
}
scenceFun();
//坐标轴 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
function xAxisFun() {
xAxis = new AxesHelper(29); //长度29的坐标轴
xAxis.name = "坐标轴"; //坐标轴名字
scence.add(xAxis); //添加实例
}
xAxisFun();
function pointsFun() {
geometry = new BufferGeometry(); //通过顶点定义集合体
let list = listMap()
geometry.setAttribute(
"position",
new BufferAttribute(new Float32Array(list), 3)
);
geometry.setAttribute(
"color",
new BufferAttribute(new Float32Array(list), 3)
);
pointsMaterial = new PointsMaterial({
vertexColors: gui.vertexColors,//使用数组中定义的颜色值
//点材质
color: new Color(gui.color), //点颜色
size: gui.size, //点大小
// map: new TextureLoader().load("/img/3d/negz.jpg"), //图片材质
});
//vertexColors 和 color位置必须是 color在后 否则无法渲染出想要的效果
pointsMaterial.sizeAttenuation = false; //指定点的大小是否因相机深度而衰减
points = new Points(geometry, pointsMaterial);
scence.add(points);
}
pointsFun();
//遍历出一个位置数组/矩阵
function listMap(length: number = gui.number) {
let list: any = [];
for (let i = 0; i < length; i++) {
//创建一千个顶点,
let x = MathUtils.randInt(0, gui.x)
let y = MathUtils.randInt(0, gui.y)
let z = MathUtils.randInt(0, gui.z)
list.push(x); //x
list.push(y); //y
list.push(z); //z
}
return list;
}
function guiFun() {
gioData
.add(gui, "size", 0.01, 5)
.name("粒子大小")
.onChange((e) => {
//exlint忽略本段错误 因为eslint不允许使用ts的忽略编译错误 所以需要忽略eslint配置
/* eslint-disable */
//ts忽略下一句错误 因为接口没有写points.material中拥有color属性 所以报错
// @ts-ignore
points.material.size = e;
/* eslint-enable */
//忽略结束
});
gioData
.addColor(gui, "color")
.name("粒子颜色")
.onChange((e) => {
//exlint忽略本段错误 因为eslint不允许使用ts的忽略编译错误 所以需要忽略eslint配置
/* eslint-disable */
//ts忽略下一句错误 因为接口没有写points.material中拥有color属性 所以报错
// @ts-ignore
points.material.color.set(new Color(e));
/* eslint-enable */
//忽略结束
});
gioData
.add(gui, "number")
.min(300)
.name("数量")
.max(10000)
.step(3)
.onChange((e) => {
let list = new Float32Array(listMap(e))
points.geometry.setAttribute("position", new BufferAttribute(list, 3));
points.geometry.setAttribute("color", new BufferAttribute(list, 3)
);
});
gioData
.add(gui, "x")
.min(10)
.name("x轴长度")
.max(100)
.step(3)
.onChange((e) => {
let list = new Float32Array(listMap())
points.geometry.setAttribute("position", new BufferAttribute(list, 3));
points.geometry.setAttribute("color", new BufferAttribute(list, 3))
});
gioData
.add(gui, "y")
.min(10)
.name("y轴长度")
.max(100)
.onChange((e) => {
let list = new Float32Array(listMap())
points.geometry.setAttribute("position", new BufferAttribute(list, 3));
points.geometry.setAttribute("color", new BufferAttribute(list, 3))
});
gioData
.add(gui, "z")
.min(10)
.name("z轴长度")
.max(100)
.onChange((e) => {
let list = new Float32Array(listMap())
points.geometry.setAttribute("position", new BufferAttribute(list, 3));
points.geometry.setAttribute("color", new BufferAttribute(list, 3))
});
gioData
.add(gui, "vertexColors")
.name("是否开启随机色")
.onChange((e) => {
points.material.vertexColors = e//更改数组颜色应用状态
points.material.needsUpdate = true//重新绘制材质
});
}
guiFun();
//aim定时执行 动画
var aim = () => {
stats.update(); //刷新性能监控
orbitControls.update();
rander.render(scence, camera); //更新试图
requestAnimationFrame(aim); //定时器 到时间调用自己
};
// 定时器
watch(loading, (e) => {
if (!e) {
box.value?.append(rander.domElement);
document.body.appendChild(stats.dom);
gioData.domElement.style.display = "inherit";
aim();
}
});
//生命周期 页面加载完
onMounted(() => {
rander.setSize(window.innerWidth, window.innerHeight); //更改渲染大小
loading.value = false;
// !loading.value && box.value?.append(rander.domElement); //box渲染完成则添加
// !loading.value && box.value?.appendChild(stats.dom); //box渲染完成则添加性能监控
// 点击事件
});
//使画布动态大小
window.onresize = () => {
camera.aspect = window.innerWidth / window.innerHeight; //更改比例
camera.updateProjectionMatrix(); //更新摄像机投影矩阵
rander.setSize(window.innerWidth, window.innerHeight); //更改场景大小
};
return {
box,
loading,
};
},
});
</script>
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)