模块化参照https://blog.csdn.net/weixin_42776111/article/details/127511552
想模块化实现鼠标选中模型高亮,但是失败了
下面高亮模块js
import * as THREE from 'three'
import {EffectComposer} from "../../examples/jsm/postprocessing/EffectComposer.js";
import {RenderPass} from "../../examples/jsm/postprocessing/RenderPass.js";
import {OutlinePass} from "../../examples/jsm/postprocessing/OutlinePass.js";
import {FXAAShader} from "../../examples/jsm/shaders/FXAAShader.js";
import {ShaderPass} from "../../examples/jsm/postprocessing/ShaderPass.js";
export function Tclick(renderer, scene, camera){
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
renderer.domElement.style.touchAction = 'none';
renderer.domElement.addEventListener( 'pointermove', onPointerMove );
function onPointerMove(event) {
var composer = new EffectComposer( renderer );
var renderPass = new RenderPass( scene, camera );
composer.addPass( renderPass );
var v2 = new THREE.Vector2( window.innerWidth, window.innerHeight )
var outlinePass = new OutlinePass( v2, scene, camera );
outlinePass.edgeStrength = 5;//包围线浓度
outlinePass.edgeGlow = 0.5;//边缘线范围
outlinePass.edgeThickness = 2;//边缘线浓度
outlinePass.pulsePeriod = 2;//包围线闪烁频率
outlinePass.visibleEdgeColor.set( '#ffffff' );//包围线颜色
outlinePass.hiddenEdgeColor.set( '#190a05' );//被遮挡的边界线颜色
composer.addPass( outlinePass );
var effectFXAA = new ShaderPass( FXAAShader );
effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
composer.addPass( effectFXAA );
console.log(composer)
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
const intersects = raycaster.intersectObject( scene, true );
if ( intersects.length > 0 ) {
var selectedObjects = []
const selectedObject = intersects[0].object;
selectedObjects.push(selectedObject);
outlinePass.selectedObjects = selectedObjects;
return composer
} else {
outlinePass.selectedObjects = [];
}
}
}
下面是TEngie.js
//初始化渲染器、场景、相机以及灯光
import { WebGLRenderer, Scene,PerspectiveCamera,Vector2,AmbientLight, DirectionalLight,AxesHelper,Raycaster,MOUSE} from 'three'
import OrbitControls from 'three-orbitcontrols';
import {Tclick} from './Tclick'
export class TEngie{
dom = null;
scene = null; // 场景
constructor(dom){
// 创建渲染器
var renderer = new WebGLRenderer({antialias: true}) //开启抗锯齿
renderer.setClearColor('rgb(214, 234, 255)')//设置旋绕背景颜色,默认是黑色
dom.appendChild(renderer.domElement) // 将渲染器挂载到dom
//渲染器大小和dom节点大小一致
//设置渲染高度和宽度与窗口大小一致
renderer.setSize(window.innerWidth, window.innerHeight)
//场景
var scene = new Scene()
//相机
var camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000)
camera.position.set(400, 200, 400) // 设置相机位置
// camera.lookAt(new Vector3(0, 0, 0)) // 设置相机看先中心点
// camera.up = new Vector3(0, 0, 0) // 设置相机自身的方向
//鼠标
let orbitControls = new OrbitControls(camera, renderer.domElement)
//发光模块
var composer = Tclick(renderer, scene, camera)
//console.log(composer)
//自适应窗口
window.addEventListener( 'resize', onWindowResize);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//渲染
function animate (){
renderer.render(scene, camera) // 渲染器渲染场景和相机
if(composer){
composer.render();
}
requestAnimationFrame(animate);
}
animate()
this.dom = dom ;
this.scene = scene;
}
//添加不同内容函数:如模型、灯光
addObject(object) {
object.forEach(elem => {
this.scene.add(elem)
})
}
}
//设置灯光
export const allLights = []
// 添加环境光 自然光强度,0最低 1最强
export const ambientLight = new AmbientLight( 0x404040)
// 平行光
export const directionalLight = new DirectionalLight( 0xffffff);
allLights.push(ambientLight,directionalLight)
//设置辅助线
export const allHelper = []
// 坐标辅助
export const axesHelper = new AxesHelper(5000) // 创建坐标辅助
allHelper.push(axesHelper)
首先,需要在vue组件中引入threejs库,然后在mounted钩子函数中初始化场景、相机、光源等对象。接着,需要监听鼠标移动事件,获取鼠标在场景中的坐标,然后计算与场景中所有模型的交点,找到最近的交点,并将对应的模型高亮。具体实现代码如下:
<template>
<div ref="container"></div>
</template>
<script>
import * as THREE from 'three';
export default {
mounted() {
// 初始化场景、相机、光源等对象
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
const pointLight = new THREE.PointLight(0xffffff, 0.5);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshPhongMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube, ambientLight, pointLight);
// 设置渲染器大小,并将渲染器添加到DOM中
renderer.setSize(window.innerWidth, window.innerHeight);
this.$refs.container.appendChild(renderer.domElement);
// 监听鼠标移动事件
renderer.domElement.addEventListener('mousemove', event => {
const mouse = new THREE.Vector2(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1
);
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
const target = intersects[0].object;
target.material.color.set(0xff0000);
}
});
// 渲染场景
function render() {
requestAnimationFrame(render);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
render();
}
};
</script>
需要注意的是,这里使用了Phong着色器材质,所以需要设置光源。而且,如果场景中有多个模型,需要将模型添加到场景中,并设置模型的名称,以便在交点计算时能够区分不同的模型。同时,可能需要在模型高亮时将其他模型的材质还原为原来的颜色。