【可视化学习】88-3D后期效果(二)
发表于:2024-09-24 |

前言

本篇讲解利用postprocessing来实现选中效果

初始化项目并导入模型和环境贴图

这里我就不展开了,都是之前讲过的那些代码,我直接贴一下。这里和之前稍微有点不同是因为要加后期效果,所以给renderer加上了

1
2
logarithmicDepthBuffer: true,
powerPreference: "high-performance",

代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";

// 初始化场景
const scene = new THREE.Scene();
// 初始化相机
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.set(8, 4, 0);
camera.lookAt(0, 2, 0);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
// 初始化渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,
powerPreference: "high-performance",
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);


// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.target.set(0, 2, 0);

// 添加环境纹理
let rbgeLoader = new RGBELoader();
rbgeLoader.load("./texture/powerplant.hdr", (texture) => {
texture.mapping = THREE.EquirectangularReflectionMapping;
scene.background = texture;
scene.environment = texture;
scene.backgroundBlurriness = 1;
});

// 添加聚光灯
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-200, 200, -100);
spotLight.angle = 0.1;
spotLight.intensity = 5;
scene.add(spotLight);


// 添加模型
let dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("./draco/");
let gltfLoader = new GLTFLoader();
let bear, elephant, dear;
gltfLoader.setDRACOLoader(dracoLoader);
gltfLoader.load("./model/bear.gltf", (gltf) => {
bear = gltf.scene.children[0];
scene.add(bear);
bear.position.set(0, 0, -4);
});

gltfLoader.load("./model/elephant.gltf", (gltf) => {
elephant = gltf.scene.children[0];
elephant.position.set(0, 0, 4);
scene.add(elephant);
});

gltfLoader.load("./model/dear.gltf", (gltf) => {
dear = gltf.scene.children[0];
scene.add(dear);
});

// 设置渲染函数
const render = () => {
renderer.render(scene, camera);
controls.update();
requestAnimationFrame(render);
};
render();

此时效果如下
效果图

初始化后期效果

这里的具体属性内容大家可以去github那边自己查看一下,我就不展开了:
https://github.com/pmndrs/postprocessing

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import {
EffectComposer,
RenderPass,
SelectiveBloomEffect,
BlendFunction,
EffectPass,
SMAAEffect,
OutlineEffect,
} from "postprocessing";

// 实例化后期处理效果
const composer = new EffectComposer(renderer);
// 添加renderPass
composer.addPass(new RenderPass(scene, camera));

// 添加发光效果
const bloomEffect = new SelectiveBloomEffect(scene, camera, {
mipmapBlur: true,
blendFunction: BlendFunction.ADD,
luminanceThreshold: 0.7,
luminanceSmoothing: 0.3,
intensity: 10,
});
// 添加轮毂效果
const outlineEffect = new OutlineEffect(scene, camera, {
blendFunction: BlendFunction.ADD,
edgeStrength: 3,
pulseSpeed: 0,
visibleEdgeColor: 0xffffff,
hiddenEdgeColor: 0x22090a,
blur: false,
xRay: true,
usePatternTexture: false,
});
// 添加ontlinePass
const outlinePass = new EffectPass(camera, outlineEffect);
composer.addPass(outlinePass);

// 添加抗锯齿效果
const smaaEffect = new SMAAEffect();
// 添加效果通道
let effectPass = new EffectPass(camera, bloomEffect, smaaEffect);
composer.addPass(effectPass);

// 设置渲染函数
const render = () => {
// renderer.render(scene, camera);
controls.update();
composer.render();
requestAnimationFrame(render);
};
render();

做个测试

我们给熊加上这个后期效果看一下

1
2
3
4
5
6
7
gltfLoader.load("./model/bear.gltf", (gltf) => {
bear = gltf.scene.children[0];
scene.add(bear);
bear.position.set(0, 0, -4);
outlineEffect.selection.set(bear);
bloomEffect.selection.set(bear);
});

可以看到我们的熊有了描边和高光效果
效果图

添加选中逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 添加鼠标点击事件
let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();
let intersects = [];
window.addEventListener("click", (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
let object = intersects[0].object;
outlineEffect.selection.set([object]);
bloomEffect.selection.set([object]);
}
});

这样,我们的选中高光效果就完成了,最终效果如下
效果图

结语

本文给大家介绍了一种选中的效果,大家有空的话也可以看看这个库的实现方式,能够很好帮助大家完善3D内容显示。本篇文章就到这里了,更多内容敬请期待,债见~

上一篇:
【Canvas学习】05-canvas写字板和刮刮卡效果
下一篇:
可拖拽的select组件