threejs点击模型实现模型边缘高亮的选中效果--更改后提高帧率

先来个效果图

之前写的那个稍微有点问题,帧率只有30,参照官方代码修改后,帧率可以达到50了,在不全屏的状态下,帧率60


1.首先需要导入库

js 复制代码
// 用于模型边缘高亮
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js"
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js"
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js"
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"
import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass.js"
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js"

然后需要注意,我这里使用的是vue的框架,但是对于变量的定义我用的是全局的定义。

js 复制代码
// 模型边缘高光
let composer;
let outlinePass;
let renderPass;
let effectFXAA;

2.添加EffectComposer效果组合器

js 复制代码
add_composer() {
  // 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
  composer = new EffectComposer(renderer)
  // 新建一个场景通道  为了覆盖到原来的场景上
  renderPass = new RenderPass(scene, camera)
  composer.addPass(renderPass);
  // 物体边缘发光通道
  outlinePass = new OutlinePass(mouse, scene, camera)
  outlinePass.visibleEdgeColor.set(parseInt(0x00ff00)) // 呼吸显示的颜色
  outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色
  composer.addPass(outlinePass)

  // 解决高亮后环境变暗的问题
  const outputPass = new OutputPass();
  composer.addPass( outputPass );

  // 自定义的着色器通道 作为参数
  effectFXAA = new ShaderPass(FXAAShader)
  effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
  composer.addPass(effectFXAA)

},
  • outlinePass = new OutlinePass(mouse, scene, camera)中的mouse就是 new THREE.Vector2( window.innerWidth, window.innerHeight ),可以直接用这个

把上面这个函数,在mounted的时候调用一下,初始化一次,后面想让哪个模型高亮,就传哪个模型进去

3.点击模型边缘高亮

现在就需要在点击模型的事件中去调用这个函数

js 复制代码
// 点击模型事件
pick(event) {
  const found = self.cast(event)[0];
  if (found) {
    // [transformer]是给变压器加,[transformer,car]是给变压器和房子加,子模型要.object
    outlinePass.selectedObjects = [found.object]; 
  }
},

我的self就是this。

我想要实现的是子模型的高亮,所以我要取子模型的object,其次需要注意的就是传入的参数是个数组,你传入哪些模型,点击的时候,那些模型就会一起高亮,我这里传入的是一个,是选中的子模型。

如果你不想让这个模型边缘高亮了,那么outlinePass.selectedObjects = \[\]; 这个数组里放哪个模型哪个模型边缘高亮,通过修改 outlinePass.selectedObjects 实现。

4.移除模型边缘高亮

当不想要高亮的时候,把composer赋值为空就可以了。

js 复制代码
doubel_pick(event) {
  outlinePass.selectedObjects = [];
},

5.监听窗口变化

当窗口大小改变时,需要对应着改变渲染的大小

js 复制代码
// 随着窗体的变化修改场景
function onResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  composer.setSize(window.innerWidth, window.innerHeight);
  effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight );
}
// 监听窗体调整大小事件
window.addEventListener('resize', onResize, false);

6.循环渲染

js 复制代码
const animate = () => {
  stats.update();
  controls.update();
  //renderer.render(scene, camera);  不在需要renderer.render了
  composer.render(scene, camera)
  self.render_animation = requestAnimationFrame(animate);
};
animate()

这里需要注意的就是不要再添加renderer.render了,因为前面new EffectComposer的时候已经把renderer添加进去了,后面就是组合效果,只需要循环render后面这个composer就可以了,这是我的理解。

当然这也是造成之前帧率低的主要原因,循环渲染了,所以,删掉他,直接composer.render(scene, camera),帧率50,在不全屏的情况下,帧率60,基本满足需求。


附官方案例

案例:threejs.org/examples/?q...

源码:github.com/mrdoob/thre...

前面被其他博客误导了。

相关推荐
答案answer3 天前
不用写一行Three.js代码,也能搭出复杂数字孪生场景
github·three.js
纸片人4 天前
甲方只给了一张卫星截图,我用 Three.js + Blender 建了一座 3D 能源站
three.js·数据可视化
纸片人4 天前
从一座城市钻进一个房间:Three.js + Blender 做一个五级钻取的数字楼宇大屏
three.js·数据可视化
妖精的羽翼4 天前
Web3D(Three.js)应用分级 + 学习路线规划(由浅入深,贴合接单 + 求职)
学习·three.js
踩着两条虫5 天前
我在浏览器里“盖”了一个村:Vue + Three.js 大屏开发踩坑记
前端·vue.js·three.js
子龙_5 天前
来在网页上用threejs画个蛋白质吧
前端·webgl·three.js
沧沧凉凉11 天前
一段需求、零素材,Claude Code 派了 33 个代理给我做了个 3D 动作游戏
游戏·ai编程·three.js
牧艺17 天前
浏览器端 3D 看车重磅升级:从三款展车到可试驾的八车展厅
前端·three.js·交互设计
像我这样帅的人丶你还19 天前
📱iPhone Duo 开屏动画咋实现的?
javascript·webgl·three.js
夏天要喝冰可乐19 天前
Antigravity + Blender MCP(下):3D 智慧仓储数字孪生进阶实战
前端·webgl·three.js