ThreeJS 官方案例学习(webgl_geometry_colors)
1.效果图
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ba19b867844340f0b52a4f589f783673.jpeg#pic_center)
2.源码
<template>
<div>
<div id="container"></div>
</div>
</template>
<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
import Stats from 'three/examples/jsm/libs/stats.module.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
import gsap from 'gsap';
export default {
data() {
return {
container: null,
height: 0,
width: 0,
scene: null,
camera: null,
renderer: null,
controller: null,
stats: null,
mixer: null,
model: null,
clock: new THREE.Clock(),
mouseX: 0,
mouseY: 0,
windowHalfX: 0,
};
},
mounted() {
this.init()
this.animate()
window.addEventListener("resize", this.onWindowSize)
window.addEventListener('mousemove', this.onDocumentMouseMove);
},
beforeUnmount() {
console.log('beforeUnmount===============');
this.container = null
this.scene = null
this.camera = null
this.renderer = null
this.controller = null
this.stats = null
this.mixer = null
this.model = null
},
methods: {
init() {
this.container = document.getElementById('container')
this.width = this.container.clientWidth
this.height = this.container.clientHeight
this.windowHalfX = this.container.clientWidth / 2;
this.windowHalfY = this.container.clientHeight / 2;
this.setScene()
this.setCamera()
this.setRenderer()
this.addHelper()
this.setLight()
this.setMesh()
this.addStatus()
},
setScene() {
this.scene = new THREE.Scene()
this.scene.background = new THREE.Color(0xffffff);
},
setCamera() {
this.camera = new THREE.PerspectiveCamera(20, this.width / this.height, 1, 10000)
this.camera.position.z = 1800;
this.camera.aspect = this.width / this.height;
this.camera.updateProjectionMatrix();
this.camera.lookAt(new THREE.Vector3(0, 0, 0))
this.scene.add(this.camera)
},
setRenderer() {
this.renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,
})
this.renderer.setSize(this.width, this.height);
this.renderer.setPixelRatio(window.devicePixelRatio);
this.container.appendChild(this.renderer.domElement);
},
setController() {
this.controller = new OrbitControls(this.camera, this.renderer.domElement);
this.controller.enableDamping = true;
this.controller.dampingFactor = 0.04;
this.controller.target.set(0, 0, 0);
},
addHelper() {
let helper = new THREE.CameraHelper(this.camera);
let axisHelper = new THREE.AxesHelper(150);
this.scene.add(axisHelper)
let gridHelper = new THREE.GridHelper(100, 30, 0x2C2C2C, 0x888888);
this.scene.add(gridHelper);
},
setPMREMGenerator() {
const pmremGenerator = new THREE.PMREMGenerator(this.renderer);
this.scene.environment = pmremGenerator.fromScene(new RoomEnvironment(this.renderer), 0.04).texture;
},
setLight() {
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
this.scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 3);
directionalLight.position.set(1, 0, 0);
this.scene.add(directionalLight);
},
addStatus() {
this.stats = new Stats();
this.container.appendChild(this.stats.dom);
},
setMesh() {
const radius = 200;
const material = new THREE.MeshPhongMaterial({
color: 0xffffff,
flatShading: true,
vertexColors: true,
shininess: 0,
});
const geometry1 = new THREE.IcosahedronGeometry(radius, 1);
const wireframeMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, wireframe: true, transparent: true });
const count = geometry1.attributes.position.count;
geometry1.setAttribute('color', new THREE.BufferAttribute(new Float32Array(count * 3), 3));
const geometry2 = geometry1.clone();
const geometry3 = geometry1.clone();
const color = new THREE.Color();
const positions1 = geometry1.attributes.position;
const positions2 = geometry2.attributes.position;
const positions3 = geometry3.attributes.position;
const colors1 = geometry1.attributes.color;
const colors2 = geometry2.attributes.color;
const colors3 = geometry3.attributes.color;
for (let i = 0; i < count; i++) {
color.setHSL((positions1.getY(i) / radius + 1) / 2, 1.0, 0.5, THREE.SRGBColorSpace);
colors1.setXYZ(i, color.r, color.g, color.b);
color.setHSL(0, (positions2.getY(i) / radius + 1) / 2, 0.5, THREE.SRGBColorSpace);
colors2.setXYZ(i, color.r, color.g, color.b);
color.setRGB(1, 0.8 - (positions3.getY(i) / radius + 1) / 2, 0, THREE.SRGBColorSpace);
colors3.setXYZ(i, color.r, color.g, color.b);
}
let mesh = new THREE.Mesh(geometry1, material)
let wireframe = new THREE.Mesh(geometry1, wireframeMaterial);
mesh.add(wireframe);
mesh.position.x = - 400;
mesh.rotation.x = - 1.87;
this.scene.add(mesh);
mesh = new THREE.Mesh(geometry2, material);
wireframe = new THREE.Mesh(geometry2, wireframeMaterial);
mesh.add(wireframe);
mesh.position.x = 400;
this.scene.add(mesh);
mesh = new THREE.Mesh(geometry3, material);
wireframe = new THREE.Mesh(geometry3, wireframeMaterial);
mesh.add(wireframe);
this.scene.add(mesh);
const canvas = document.createElement('canvas');
canvas.width = 128;
canvas.height = 128;
const context = canvas.getContext('2d');
const gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
gradient.addColorStop(0.1, 'rgba(210,210,210,1)');
gradient.addColorStop(1, 'rgba(255,255,255,1)');
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
const shadowTexture = new THREE.CanvasTexture(canvas);
const shadowMaterial = new THREE.MeshBasicMaterial({ map: shadowTexture });
const shadowGeo = new THREE.PlaneGeometry(300, 300, 1, 1);
let shadowMesh;
shadowMesh = new THREE.Mesh(shadowGeo, shadowMaterial);
shadowMesh.position.y = - 250;
shadowMesh.rotation.x = - Math.PI / 2;
this.scene.add(shadowMesh);
shadowMesh = new THREE.Mesh(shadowGeo, shadowMaterial);
shadowMesh.position.y = - 250;
shadowMesh.position.x = - 400;
shadowMesh.rotation.x = - Math.PI / 2;
this.scene.add(shadowMesh);
shadowMesh = new THREE.Mesh(shadowGeo, shadowMaterial);
shadowMesh.position.y = - 250;
shadowMesh.position.x = 400;
shadowMesh.rotation.x = - Math.PI / 2;
this.scene.add(shadowMesh);
},
onWindowSize() {
this.width = this.container.clientWidth
this.height = this.container.clientHeight
this.windowHalfX = this.container.clientWidth / 2;
this.windowHalfY = this.container.clientHeight / 2;
this.camera.aspect = this.width / this.height;
this.camera.updateProjectionMatrix();
this.renderer.setSize(this.width, this.height);
this.renderer.setPixelRatio(window.devicePixelRatio)
},
onDocumentMouseMove(event) {
this.mouseX = (event.clientX - this.windowHalfX)
this.mouseY = (event.clientY - this.windowHalfY)
},
animate() {
this.camera.position.x += (this.mouseX - this.camera.position.x) * 0.05;
this.camera.position.y += (- this.mouseY - this.camera.position.y) * 0.05;
this.camera.lookAt(this.scene.position);
const delta = this.clock.getDelta();
if (this.mixer) {
this.mixer.update(delta);
}
requestAnimationFrame(this.animate);
this.stats.update();
this.renderer.render(this.scene, this.camera);
},
},
};
</script>
<style>
#container {
position: absolute;
width: 100%;
height: 100%;
}
</style>