代码
<template>
<div class="circle" ref="circle"></div>
</template>
<script setup>
import {onMounted, ref} from "vue";
import * as THREE from 'three';
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
let scene, camera, renderer, controls, circle = ref(null);
let timeValue = {value: 0.0}
function init() {
let width = circle.value.clientWidth;
let height = circle.value.clientHeight
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({
antialias: true, //开启锯齿
});
renderer.setSize(width, height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.setClearColor(new THREE.Color('#32373E'), 1);
camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000)
camera.position.set(500, 500, 500)
controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.AmbientLight(0xadadad, 0.8); // soft white light
scene.add(light)
let light_2 = new THREE.HemisphereLight(0x00AAFF, 0xFFAA00, 0.8)
scene.add(light_2)
scene.add(new THREE.AxesHelper(500))
let vertexShader = `
// uniform mat4 modelMatrix;//不需要声明
varying vec3 v_position;
varying vec2 vUv;
void main(){
// 模型矩阵modelMatrix对顶点位置坐标进行模型变换
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
v_position = position;
vUv = uv;
}`
let fragmentShader = `
varying vec3 v_position;
uniform float v_time;
varying vec2 vUv;
// 底部颜色
uniform vec3 wall_color;
// 移动的光带颜色
uniform vec3 v_color;
float size = 1.0/10.0;
void main() {
float v = v_time;
float percent = vUv.y / 1.0;
if (mod(vUv.y-v,size) >0.001 && mod(vUv.y-v,size) < 0.005) {
gl_FragColor = vec4(v_color, (1.0-percent)*0.6);
} else {
gl_FragColor = vec4(wall_color, (1.0-percent)*0.6);
}
}
`
let material2 = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
side: THREE.DoubleSide,
transparent: true,
uniforms: {
v_time: timeValue,
v_color: {
value: new THREE.Color('#FFFFFF')
},
wall_color: {
value: new THREE.Color('#FF4127')
}
}
})
let c = [0, 0, 100, 0, 100, 100, 0, 100, 0, 0];
let posArr = [];
let uvrr = [];
let h = 250; //围墙拉伸高度
for (let i = 0; i < c.length - 2; i += 2) {
// 围墙多边形上两个点构成一个直线扫描出来一个高度为h的矩形
// 矩形的三角形1
posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], 0, c[i + 2], c[i + 3], h);
// 矩形的三角形2
posArr.push(c[i], c[i + 1], 0, c[i + 2], c[i + 3], h, c[i], c[i + 1], h);
// 注意顺序问题,和顶点位置坐标对应
uvrr.push(0, 0, 1, 0, 1, 1);
uvrr.push(0, 0, 1, 1, 0, 1);
}
let geometry = new THREE.BufferGeometry(); //声明一个空几何体对象
// 设置几何体attributes属性的位置position属性
geometry.attributes.position = new THREE.BufferAttribute(new Float32Array(posArr), 3);
// 设置几何体attributes属性的位置uv属性
geometry.attributes.uv = new THREE.BufferAttribute(new Float32Array(uvrr), 2);
geometry.computeVertexNormals()
let mesh = new THREE.Mesh(geometry, material2); //网格模型对象Mesh
scene.add(mesh);
mesh.rotateX(-Math.PI/2)
}
function animal() {
renderer.render(scene, camera);
timeValue.value += 0.005
if (timeValue.value >= 1.0) {
timeValue.value = 0.0;
}
requestAnimationFrame(animal)
}
onMounted(() => {
init();
circle.value.appendChild(renderer.domElement)
animal();
})
</script>
<style scoped lang="less">
.circle {
height: 100%;
}
</style>