vue3 threejs 物体发光描边

发布于:2025-05-27 ⋅ 阅读:(39) ⋅ 点赞:(0)

threejs官网案例: three.js examples

我的代码(标注了重点代码,加上即可)

<template>

    <div class="greenhouse" ref="canvasContainerRef">
    </div>

</template>

<script setup>
import * as THREE from "three";
import anime from "animejs"

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";

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 { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';//重点

import { ref, onMounted, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const renderer = ref(); //渲染器

let scene = new THREE.Scene(); //场景--scene是只读属性
const camera = ref(null); //相机
let orbitControls = null
let composer = null//重点
let effectFXAA = null//重点
const initThree = () => {
    // width和height用来设置Three.js输出Canvas画布尺寸,同时用来辅助设置相机渲染范围
    camera.value = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
    camera.value.position.set(200, 200, 200);
    // scene.background = new THREE.Color(0xffffff);
    // 创建渲染器
    renderer.value = new THREE.WebGLRenderer({
        antialias: true, //开启抗锯齿(否则加载的模型有锯齿--)
    });
    renderer.value.setSize(window.innerWidth, window.innerHeight);
    renderer.value.setPixelRatio(window.devicePixelRatio); //设置设备像素比率,防止Canvas画布输出模糊。

    const canvasContainerRef = proxy.$refs["canvasContainerRef"];

    //环境光
    var ambient = new THREE.AmbientLight(0xffffff, 1);
    scene.add(ambient);
    canvasContainerRef.appendChild(renderer.value.domElement);
    const axesHelper = new THREE.AxesHelper(150);
    scene.add(axesHelper);
    orbitControls = new OrbitControls(camera.value, renderer.value.domElement); //旋转、放大缩小
    // 初始化加载器

    const loader = new GLTFLoader();

    renderer.value.outputEncoding = THREE.sRGBEncoding; //解决加载gltf格式模型纹理贴图和原图不一样问题
    // 创建后处理对象EffectComposer,WebGL渲染器作为参数

    composer = new EffectComposer(renderer.value);//重点
    // 创建一个渲染器通道,场景和相机作为参数
    const renderPass = new RenderPass(scene, camera.value);//重点


    composer.addPass(renderPass);//重点

    const v2 = new THREE.Vector2(window.innerWidth, window.innerHeight);//重点

    const outlinePass = new OutlinePass(v2, scene, camera.value);//重点
    // 设置描边参数  //重点
    outlinePass.visibleEdgeColor.set(0xaeb63e); // 可见边颜色(绿色)
    outlinePass.hiddenEdgeColor.set(0x0000ff);  // 隐藏边颜色(蓝色)
    outlinePass.edgeStrength = 8.0;            // 边缘强度
    outlinePass.edgeThickness = 3.0;           // 边缘厚度
    outlinePass.pulsePeriod = 4;
    outlinePass.edgeGlow = 0.7;
    //MeshLambertMaterial受光照影响
    const material = new THREE.MeshLambertMaterial({
        color: 0xa1a314
    });
    const geometry = new THREE.BoxGeometry(100, 100, 100);
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh)

    composer.addPass(outlinePass);//重点
    effectFXAA = new ShaderPass(FXAAShader);//重点
    effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);//重点
    composer.addPass(effectFXAA);//重点
    // 一个模型对象
    outlinePass.selectedObjects = [mesh];//重点
    // loader.load("./士兵.glb", (gltf) => {
    //     scene.add(gltf.scene)

    // });
    scene.add(camera.value);
    animateRender();
};


// 动画循环
const animateRender = () => {
    requestAnimationFrame(animateRender);
    //  renderer.value.render(scene, camera.value)
    composer.render(); // 只需要调用composer.render()//重点

};

onMounted(() => {
    initThree()
});
</script>

<style scoped lang="scss"></style>

有两点注意:

一、vue3里面申明的scene composer effectFXAA 不能定义为响应式否则会报错。

二、由于使用了composer.render(),所以抗锯齿会失效,模型会有锯齿。


网站公告

今日签到

点亮在社区的每一天
去签到