【可视化学习】48-昼夜交替项目
发表于:2023-09-30 |

前言

本篇文章将给大家带来昼夜交替酒店项目

最终效果展示

先给大家看一下最终效果的视频,接下来我将一步步带着大家一起制作这个效果

初始化代码

这里我省略了初始化项目的部分,这部分已经做了很多次了,如果还有不懂的小伙伴可以去前面的文章找一下,我这里直接从初始化three的代码开始了,这里我为了展示效果,添加了一个矩阵

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
88
89
90
91
92
93
94
<template>
<div class="home" ref="screenDom">
</div>
</template>
<script setup>
import { onMounted} from "vue";
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
onMounted(() => {
// 1.创建场景
const scene = new THREE.Scene()

// 2.创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)

// 设置相机位置
camera.position.set(0, 0, 10)

// 添加相机
scene.add(camera)

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();

//设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);

// 将webgl渲染的canvas内容添加到body上
document.querySelector(".home").appendChild(renderer.domElement);

//当前是平面的,让平面立体起来,使用控制器controls
// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping=true
// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper)

// 持续渲染,让相机场景动起来
function render() {
controls.update()
// 使用渲染器通过相机将场景渲染进来
renderer.render(scene, camera);
// 渲染下一帧的时候就会调用render函数
requestAnimationFrame(render)
}

render()

// 监听画面的变化,更新渲染的画面
window.addEventListener("resize", () => {
// console.log("画面变化了")
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
// 更新渲染器
renderer.setSize(window.innerWidth, window.innerHeight);

// 设置渲染器的像素比
renderer.setPixelRatio(window.devicePixelRatio)
})

// 创建几何体
const geometry = new THREE.BufferGeometry();

// 设置顶点
const vertices=new Float32Array([
-1.0,-1.0,1.0,
1.0,-1.0,1.0,
1.0,1.0,1.0,
1.0,1.0,1.0,
-1.0,1.0,1.0,
-1.0,-1.0,1.0
])
// 设置顶点位置,3个为一组
geometry.setAttribute('position',new THREE.BufferAttribute(vertices,3))
// 设置材质
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

// 生成物体
const mesh=new THREE.Mesh(geometry,material)

// 将物体添加到场景中
scene.add(mesh)
})
</script>
<style scoped>
.home {
width: 100vw;
height: 100vh;
}
</style>

初始化效果

导入背景图

这里先把测试用的矩阵给去除

导入hdr的loader

1
2
// 导入HDR加载器
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader"

导入hdr的图片

1
2
3
4
5
6
7
8
 // 导入hdr图片
const hdrLoader = new RGBELoader();
hdrLoader.load("./assets/textures/023.hdr", (texture) => {
texture.mapping = THREE.EquirectangularReflectionMapping;
texture.format = THREE.RGBAFormat;
scene.background = texture;
scene.environment = texture;
});

背景图效果

导入模型

修改文件目录

这里我使用的是glb格式的模型,所以需要将node_modules中three文件夹下的examples文件夹中的jsm文件夹中的draco文件夹复制到public文件夹下,这样方便引入我们的glb文件

解压导入模型

1
2
3
4
5
6
7
8
9
const gltfLoader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("./draco/gltf/");
dracoLoader.setDecoderConfig({ type: "js" });
dracoLoader.preload();
gltfLoader.setDRACOLoader(dracoLoader);
gltfLoader.load("./model/building-min02.glb", (gltf) => {
scene.add(gltf.scene);
});

模型效果

调整下相机的位置

这里我自己找了个比较合适的角度

1
2
// 设置相机位置
camera.position.set(-117, 17, -140);

调整相机位置

去除模型地面并接受阴影

1
2
3
4
5
6
7
8
9
10
11
12
13
gltfLoader.load("./model/building-min02.glb", (gltf) => {
gltf.scene.traverse((child) => {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.material.shadowSide = THREE.BackSide;
}
if (child.isMesh && child.name == "Plane") {
child.visible = false;
}
});
scene.add(gltf.scene);
});

效果调整

添加水面

新建一个Ocean.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import * as THREE from "three";
import { Water } from "three/examples/jsm/objects/Water2.js";

export default class Ocean {
constructor(radius = 1000) {
// 创建水平
this.waterGeometry = new THREE.CircleGeometry(radius, 128);
this.water = new Water(this.waterGeometry, {
textureWidth: 1024,
textureHeight: 1024,
color: 0x08dbea,
flowDirection: new THREE.Vector2(1, 1),
scale: 100,
});
this.water.position.y = 0;
this.water.rotation.x = -Math.PI / 2;
this.mesh = this.water;
this.water.renderOrder = -1;
}
}

效果图

导入使用

1
2
let ocean = new Ocean();
scene.add(ocean.mesh);

修改水的材质

1
2
3
4
5
6
7
8
9
10
// 修改水面的颜色
this.water.material.fragmentShader =
this.water.material.fragmentShader.replace(
"gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );",
`
gl_FragColor = vec4( color, 1.0 ) * mix( refractColor, reflectColor, reflectance );
gl_FragColor = mix( gl_FragColor, vec4( 0.05, 0.3, 0.7, 1.0 ), vToEye.z*0.0005+0.5 );

`
);

效果调整

调整渲染器

此时我们发现我们的渲染有点不太清晰,这是因为我们渲染器需要添加深度检测抗锯齿等属性

1
2
3
4
5
6
7
8
9
10
11
12
13
// 初始化渲染器
const renderer = new THREE.WebGLRenderer({
// 设置对数深度缓冲区,优化深度冲突问题
logarithmicDepthBuffer: true,
// 开启抗锯齿
antialias: true,
});
// 开启阴影
renderer.shadowMap.enabled = true;
// 色调映射
renderer.toneMapping = THREE.ACESFilmicToneMapping;
// 强度
renderer.toneMappingExposure =1;

效果图

黑夜效果制作

当我们把色调映射的强度弄低的一点

1
renderer.toneMappingExposure =0.3;

效果图

实现昼夜交替

将hdr加载改造成promise

1
2
3
4
5
6
7
8
9
10
11
const bgPromise=()=>{
return new Promise((resolve,reject)=>{
hdrLoader.load("./assets/textures/023.hdr", (texture) => {
texture.mapping = THREE.EquirectangularReflectionMapping;
texture.format = THREE.RGBAFormat;
scene.background = texture;
scene.environment = texture;
resolve(texture)
});
})
}

昼夜交替函数书写

这里我定义了一个方法,传参是两个方法,一个是白天,一个是夜晚,这里我使用了我自己定义的一个类,将radius,utime,环境贴图传入,然后在这个类中,我定义了一个updateSun方法,这个方法是根据时间来改变太阳的位置,然后我在这个方法中,判断时间,如果是白天,就执行白天的方法,如果是晚上,就执行晚上的方法,这样就实现了昼夜交替的效果

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
// 是否是白天
let isDay;
// 添加天空球
function addSphereSky(dayCallback, nightCallback) {
let uTime = {
value: 0,
};
isDay = true;
let sphereSky = new SphereSky(10000, uTime, scene.environment);
scene.add(sphereSky.mesh, sphereSky.sun);

// 动态修改时间
gsap.to(uTime, {
value: 24,
duration: 24,
repeat: -1,
ease: "linear",
onUpdate: () => {
sphereSky.updateSun(uTime.value);
if (uTime.value > 6 && uTime.value <= 18 && !isDay) {
sphereSky.sun.visible = true;
isDay = true;
dayCallback();
}
if ((uTime.value > 18 || uTime.value <= 6) && isDay) {
isDay = false;
sphereSky.sun.visible = false;
nightCallback();
}
if (Math.abs(uTime.value - 12) < 4) {
renderer.toneMappingExposure = 1;
}
if (Math.abs(uTime.value - 12) > 6) {
renderer.toneMappingExposure = 0.3;
}
if (
Math.abs(uTime.value - 12) >= 4 &&
Math.abs(uTime.value - 12) <= 6
) {
let strength = 1 - (Math.abs(uTime.value - 12) - 4) / 2;
strength < 0.3 ? (strength = 0.3) : (strength = strength);
renderer.toneMappingExposure = strength;
}
},
});
return sphereSky;
}

天空盒类

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
88
89
90
import * as THREE from "three";
import {
Lensflare,
LensflareElement,
} from "three/examples/jsm/objects/Lensflare.js";
export default class SphereSky {
constructor(radius, uTime, envMap) {
let geometry = new THREE.SphereGeometry(radius, 32, 32);
let material = new THREE.MeshBasicMaterial({
map: envMap,
side: THREE.BackSide,
});
this.mesh = new THREE.Mesh(geometry, material);
this.mesh.rotation.y = -Math.PI / 2;

material.onBeforeCompile = (shader) => {
console.log(shader.fragmentShader);
shader.uniforms.uTime = uTime;
shader.fragmentShader = shader.fragmentShader.replace(
"#include <common>",
`
#include <common>
uniform float uTime;
`
);
shader.fragmentShader = shader.fragmentShader.replace(
"#include <dithering_fragment>",
`
#include <dithering_fragment>
float dayStrength = 0.0;
if( abs(uTime - 12.0) < 4.0 ){
dayStrength = 1.0;
}
if( abs(uTime - 12.0) > 6.0 ){
dayStrength = 0.15;
}
if( abs(uTime - 12.0) >= 4.0 && abs(uTime - 12.0) <= 6.0 ){
dayStrength = 1.0 - ( abs(uTime - 12.0) - 4.0 ) / 2.0;
dayStrength = clamp( dayStrength, 0.15, 1.0 );
}
gl_FragColor= mix(vec4(0.0,0.0,0.0,1.0),gl_FragColor,dayStrength);
`
);
};

// 创建太阳
let sunGeometry = new THREE.SphereGeometry(100, 32, 32);
let sunMaterial = new THREE.MeshStandardMaterial({
emissive: 0xffffcc,
});
this.sun = new THREE.Mesh(sunGeometry, sunMaterial);
this.sun.position.set(500, 500, 4000);
this.sun.visible = false;

// 创建直线光
let sunLight = new THREE.DirectionalLight(0xffffcc, 2);
sunLight.castShadow = true;
sunLight.shadow.camera.near = 0.1;
sunLight.shadow.camera.far = 10000;
sunLight.shadow.camera.left = -1000;
sunLight.shadow.camera.right = 1000;
sunLight.shadow.camera.top = 1000;
sunLight.shadow.camera.bottom = -1000;
sunLight.shadow.mapSize.width = 20480;
sunLight.shadow.mapSize.height = 20480;
sunLight.shadow.radius = 3;
this.sun.add(sunLight);

// 光晕效果
const textureLoader = new THREE.TextureLoader();
const textureFlare0 = textureLoader.load(
"./textures/lensflare/lensflare0.png"
);
const textureFlare3 = textureLoader.load(
"./textures/lensflare/lensflare3.png"
);
const lensflare = new Lensflare();
lensflare.addElement(new LensflareElement(textureFlare0, 700, 0));
lensflare.addElement(new LensflareElement(textureFlare3, 300, 0.6));
lensflare.addElement(new LensflareElement(textureFlare3, 200, 0.75));
lensflare.addElement(new LensflareElement(textureFlare3, 150, 0.9));
lensflare.addElement(new LensflareElement(textureFlare3, 100, 1));
sunLight.add(lensflare);
}
updateSun(time) {
this.sun.position.z = Math.cos(((time - 6) * 2 * Math.PI) / 24) * 4000;
this.sun.position.y = Math.sin(((time - 6) * 2 * Math.PI) / 24) * 4000;
}
}

添加夜晚建筑rgb效果

添加效果器

1
2
3
4
5
6
// 导入后期效果合成器
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
// three自带的效果
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
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
// 添加效果器
// 合成效果
const effectComposer = new EffectComposer(renderer);
effectComposer.setSize(window.innerWidth, window.innerHeight);

// 添加渲染通道
const renderPass = new RenderPass(scene, camera);
effectComposer.addPass(renderPass);


// 抗锯齿
const smaaPass = new SMAAPass(
window.innerWidth * renderer.getPixelRatio(),
window.innerHeight * renderer.getPixelRatio()
);
effectComposer.addPass(smaaPass);

// 发光效果
let unrealBloomPass = new UnrealBloomPass();
unrealBloomPass.enabled = false;
unrealBloomPass.threshold = 0.1;
unrealBloomPass.strength = 1;
unrealBloomPass.radius = 2;
effectComposer.addPass(unrealBloomPass);

// 创建视频纹理
let video = document.createElement("video");
video.src = "./textures/video/sucai01.mp4";
video.autoplay = true;
video.loop = true;
video.muted = true;
video.play();
let videoTexture = new THREE.VideoTexture(video);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bgPromise().then((texture)=>{
addSphereSky(
() => {
vetroMaterial.emissive = new THREE.Color(0x000000);
unrealBloomPass.enabled = false;
},
() => {
vetroMaterial.emissive = new THREE.Color(0x99cc99);
vetroMaterial.emissiveMap = videoTexture;
vetroMaterial.emissiveIntensity = 1;
unrealBloomPass.enabled = true;
}
);
})

这样就可以实现我们一开始的效果了,接下来我们将代码整理一下,将那些操作变成一个类

代码调整

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
// 导入后期效果合成器
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
// three框架本身自带效果
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
import { SMAAPass } from "three/examples/jsm/postprocessing/SMAAPass";
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
import gsap from "gsap";
// 导入海洋
import Ocean from "./Ocean";
// 添加天空球
import SphereSky from "./SphereSky";
export default class ThreePlus {
constructor(selector) {
this.actions = [];
this.textVideoArrays = [];
this.clock = new THREE.Clock();
this.domElement = document.querySelector(selector);
this.width = this.domElement.clientWidth;
this.height = this.domElement.clientHeight;
this.updateMeshArr = [];

this.init();
}
init() {
this.initScene();
this.initCamera();
this.initRenderer();
this.initControl();
this.initEffect();
this.render();
}
initScene() {
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0xcccccc);
}
initCamera() {
this.camera = new THREE.PerspectiveCamera(
45,
this.width / this.height,
0.000001,
10000
);
this.camera.position.set(0, 50, 320);

this.camera.aspect = this.width / this.height;
// 更新摄像机的投影矩阵
this.camera.updateProjectionMatrix();
}
initRenderer() {
this.renderer = new THREE.WebGLRenderer({
logarithmicDepthBuffer: true,
antialias: true,
premultipliedAlpha: true,
});
this.renderer.setSize(this.width, this.height);
this.renderer.shadowMap.enabled = true;
this.renderer.outputEncoding = THREE.sRGBEncoding;
this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
this.renderer.toneMappingExposure = 0.3;
this.renderer.sortObjects = true;
this.domElement.appendChild(this.renderer.domElement);
}
initControl() {
this.control = new OrbitControls(this.camera, this.renderer.domElement);
this.control.target.set(0, 15, 0);
}
render() {
this.control && this.control.update();
this.effectComposer.render();
requestAnimationFrame(this.render.bind(this));
}
gltfLoader(url) {
const gltfLoader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath("./draco/gltf/");
dracoLoader.setDecoderConfig({ type: "js" });
dracoLoader.preload();
gltfLoader.setDRACOLoader(dracoLoader);

return new Promise((resolve, reject) => {
gltfLoader.load(url, (gltf) => {
resolve(gltf);
});
});
}
hdrLoader(url) {
const hdrLoader = new RGBELoader();
return new Promise((resolve, reject) => {
hdrLoader.load(url, (hdr) => {
resolve(hdr);
});
});
}
setBg(url) {
return new Promise((resolve, reject) => {
this.hdrLoader(url).then((texture) => {
texture.mapping = THREE.EquirectangularRefractionMapping;
texture.anisotropy = 16;
texture.format = THREE.RGBAFormat;
this.scene.background = texture;
this.scene.environment = texture;
resolve(texture);
});
});
}
initEffect() {
// 合成效果
this.effectComposer = new EffectComposer(this.renderer);
this.effectComposer.setSize(window.innerWidth, window.innerHeight);

// 添加渲染通道
const renderPass = new RenderPass(this.scene, this.camera);
this.effectComposer.addPass(renderPass);

// 抗锯齿
const smaaPass = new SMAAPass(
window.innerWidth * this.renderer.getPixelRatio(),
window.innerHeight * this.renderer.getPixelRatio()
);
this.effectComposer.addPass(smaaPass);

// 发光效果
this.unrealBloomPass = new UnrealBloomPass();
this.unrealBloomPass.enabled = false;
this.unrealBloomPass.threshold = 0.1;
this.unrealBloomPass.strength = 1;
this.unrealBloomPass.radius = 2;
this.effectComposer.addPass(this.unrealBloomPass);

}
// 添加海洋
addOcean() {
let ocean = new Ocean();
this.scene.add(ocean.mesh);
}
// 添加辅助坐标轴
addAxis() {
let axis = new THREE.AxesHelper(20);
this.scene.add(axis);
}
// 添加天空球
addSphereSky(dayCallback, nightCallback) {
let uTime = {
value: 0,
};
this.isDay = true;
let sphereSky = new SphereSky(10000, uTime, this.scene.environment);
this.scene.add(sphereSky.mesh, sphereSky.sun);

// 动态修改时间
gsap.to(uTime, {
value: 24,
duration: 24,
repeat: -1,
ease: "linear",
onUpdate: () => {
sphereSky.updateSun(uTime.value);
if (uTime.value > 6 && uTime.value <= 18 && this.isDay == false) {
sphereSky.sun.visible = true;
this.isDay = true;
dayCallback();
}
// console.log(this.isDay);
if ((uTime.value > 18 || uTime.value <= 6) && this.isDay == true) {
this.isDay = false;
sphereSky.sun.visible = false;
// console.log(this.isDay);
nightCallback();
}
if (Math.abs(uTime.value - 12) < 4) {
this.renderer.toneMappingExposure = 1;
}
if (Math.abs(uTime.value - 12) > 6) {
this.renderer.toneMappingExposure = 0.3;
}
if (
Math.abs(uTime.value - 12) >= 4 &&
Math.abs(uTime.value - 12) <= 6
) {
let strength = 1 - (Math.abs(uTime.value - 12) - 4) / 2;
strength < 0.3 ? (strength = 0.3) : (strength = strength);
this.renderer.toneMappingExposure = strength;
}
},
});
return sphereSky;
}
}

在app.vue中修改

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
<template>
<div class="canvas-container" ref="screenDom">
</div>
</template>

<script setup>
import { onMounted,ref } from "vue";
import ThreePlus from "./three/index";
import * as THREE from "three";

let screenDom = ref(null);
const resizeFn = () => {
let scale = window.innerWidth / 1920;
screenDom.value.style.transform = `scale(${scale})`;
};
onMounted(() => {
resizeFn();
window.addEventListener("resize", resizeFn);
});

onMounted(() => {
let threePlus = new ThreePlus(".canvas-container");
window.threePlus = threePlus;
threePlus.camera.position.set(-117, 17, -140);

let bgPromise = threePlus.setBg("./assets/textures/023.hdr");
threePlus.addOcean();

// 创建视频纹理
let video = document.createElement("video");
video.src = "./textures/video/sucai01.mp4";
video.autoplay = true;
video.loop = true;
video.muted = true;
video.play();
let videoTexture = new THREE.VideoTexture(video);

threePlus.gltfLoader("./model/building-min02.glb").then((gltf) => {
let vetroMaterial = null;
gltf.scene.traverse((child) => {
if (child.isMesh) {
child.castShadow = true;
child.receiveShadow = true;
child.material.shadowSide = THREE.BackSide;
}
if (child.isMesh && child.name == "Plane") {
child.visible = false;
}
if (
child.isMesh &&
child.material.name == "Vetro" &&
vetroMaterial == null
) {
vetroMaterial = child.material;
}
});
bgPromise.then((texture) => {
threePlus.addSphereSky(
() => {
vetroMaterial.emissive = new THREE.Color(0x000000);
// threePlus.unrealBloomPass.enabled = false;
},
() => {
console.log("夜晚");
vetroMaterial.emissive = new THREE.Color(0x99cc99);
vetroMaterial.emissiveMap = videoTexture;
vetroMaterial.emissiveIntensity =1;
// threePlus.unrealBloomPass.enabled = true;
}
);
});

threePlus.scene.add(gltf.scene);
});

});
</script>

<style>
.canvas-container {
width: 1920px;
height: 1080px;
transform-origin: 0 0;
}
</style>

在style.css中修改样式

1
2
3
4
5
6
body {
background-color: #1e1a20;
}
::-webkit-scrollbar {
display: none;
}

结语

本篇文章就介绍到这里,更多内容敬请期待

上一篇:
【可视化学习】49-yuka自动导航避障AI库
下一篇:
一篇文章教会你如何抓包-fidder