three-base 2.0.49 → 2.0.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Fire/Fire.d.ts +28 -0
- package/Fire/Fire.js +79 -0
- package/Fire/Fire.ts +99 -0
- package/Fire/FireGromtry.d.ts +9 -0
- package/Fire/FireGromtry.js +40 -0
- package/Fire/FireGromtry.ts +54 -0
- package/Fire/FireMaterial.d.ts +28 -0
- package/Fire/FireMaterial.js +83 -0
- package/Fire/FireMaterial.ts +95 -0
- package/README.md +14 -0
- package/ThreeBase.d.ts +1 -1
- package/ThreeBase.js +7 -7
- package/ThreeBase.ts +7 -7
- package/package.json +1 -1
package/Fire/Fire.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { BufferGeometry, Camera, Clock, Group, Material, NormalBufferAttributes, Object3DEventMap, Points, Scene, Vector2, WebGLRenderer } from "three";
|
|
2
|
+
import FireGromtry from "./FireGromtry";
|
|
3
|
+
import FireMaterial from "./FireMaterial";
|
|
4
|
+
export default class Fire extends Points {
|
|
5
|
+
constructor();
|
|
6
|
+
geometry: FireGromtry;
|
|
7
|
+
material: FireMaterial;
|
|
8
|
+
fireColor: string;
|
|
9
|
+
fireScale: number;
|
|
10
|
+
fireRadius: number;
|
|
11
|
+
fireHeight: number;
|
|
12
|
+
particleCount: number;
|
|
13
|
+
isPerspectiveCamera: boolean;
|
|
14
|
+
size: Vector2;
|
|
15
|
+
cacheProps: {
|
|
16
|
+
fireColor: string;
|
|
17
|
+
fireScale: number;
|
|
18
|
+
fireRadius: number;
|
|
19
|
+
fireHeight: number;
|
|
20
|
+
particleCount: number;
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
isPerspectiveCamera: boolean;
|
|
24
|
+
};
|
|
25
|
+
updataFrame: number;
|
|
26
|
+
clock: Clock;
|
|
27
|
+
onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry<NormalBufferAttributes>, material: Material, group: Group<Object3DEventMap>): void;
|
|
28
|
+
}
|
package/Fire/Fire.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-06-17 02:15:58
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-06-18 20:34:38
|
|
6
|
+
*/
|
|
7
|
+
import { Clock, Color, Points, Vector2 } from "three";
|
|
8
|
+
import FireGromtry from "./FireGromtry";
|
|
9
|
+
import FireMaterial from "./FireMaterial";
|
|
10
|
+
import { degToRad } from "three/src/math/MathUtils";
|
|
11
|
+
// 粒子火焰效果
|
|
12
|
+
export default class Fire extends Points {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
}
|
|
16
|
+
geometry = new FireGromtry(0, 0, 0);
|
|
17
|
+
material = new FireMaterial();
|
|
18
|
+
// 火焰的颜色
|
|
19
|
+
fireColor = "#ff2200";
|
|
20
|
+
// 火焰的整体缩放值
|
|
21
|
+
fireScale = 1;
|
|
22
|
+
// 火焰的燃烧半径
|
|
23
|
+
fireRadius = 0.5;
|
|
24
|
+
// 火焰的高度
|
|
25
|
+
fireHeight = 3;
|
|
26
|
+
// 火焰的粒子数量
|
|
27
|
+
particleCount = 500;
|
|
28
|
+
// 是否是透视相机
|
|
29
|
+
isPerspectiveCamera = true;
|
|
30
|
+
//渲染器的尺寸
|
|
31
|
+
size = new Vector2();
|
|
32
|
+
// 缓存的参数
|
|
33
|
+
cacheProps = {
|
|
34
|
+
fireColor: "#ff2200",
|
|
35
|
+
fireScale: 0,
|
|
36
|
+
fireRadius: 0.5,
|
|
37
|
+
fireHeight: 3,
|
|
38
|
+
particleCount: 500,
|
|
39
|
+
width: 0,
|
|
40
|
+
height: 0,
|
|
41
|
+
isPerspectiveCamera: true
|
|
42
|
+
};
|
|
43
|
+
// 当前渲染的帧数
|
|
44
|
+
updataFrame = 0;
|
|
45
|
+
// 时钟对象
|
|
46
|
+
clock = new Clock();
|
|
47
|
+
onBeforeRender(renderer, scene, camera, geometry, material, group) {
|
|
48
|
+
const delta = this.clock.getDelta();
|
|
49
|
+
renderer.getSize(this.size);
|
|
50
|
+
if (this.cacheProps.fireColor !== this.fireColor ||
|
|
51
|
+
this.cacheProps.fireScale !== this.fireScale ||
|
|
52
|
+
this.cacheProps.fireRadius !== this.fireRadius ||
|
|
53
|
+
this.cacheProps.fireHeight !== this.fireHeight ||
|
|
54
|
+
this.cacheProps.particleCount !== this.particleCount ||
|
|
55
|
+
this.cacheProps.isPerspectiveCamera !== this.isPerspectiveCamera ||
|
|
56
|
+
this.cacheProps.width !== this.size.x ||
|
|
57
|
+
this.cacheProps.height !== this.size.y) {
|
|
58
|
+
this.cacheProps.fireColor = this.fireColor;
|
|
59
|
+
this.cacheProps.fireScale = this.fireScale;
|
|
60
|
+
this.cacheProps.fireRadius = this.fireRadius;
|
|
61
|
+
this.cacheProps.fireHeight = this.fireHeight;
|
|
62
|
+
this.cacheProps.particleCount = this.particleCount;
|
|
63
|
+
this.cacheProps.isPerspectiveCamera = this.isPerspectiveCamera;
|
|
64
|
+
this.cacheProps.width = this.size.x;
|
|
65
|
+
this.cacheProps.height = this.size.y;
|
|
66
|
+
this.geometry = new FireGromtry(this.fireRadius * this.fireScale, this.fireHeight * this.fireScale, this.particleCount);
|
|
67
|
+
this.material.uniforms.color.value = new Color(this.fireColor);
|
|
68
|
+
this.material.uniforms.size.value = this.fireScale * 0.4;
|
|
69
|
+
if (camera.isPerspectiveCamera) {
|
|
70
|
+
this.material.uniforms.heightOfNearPlane.value = Math.abs(this.size.y / (2 * Math.tan(degToRad(camera.fov * 0.5))));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.material.uniforms.heightOfNearPlane.value = 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
this.isPerspectiveCamera = camera.isPerspectiveCamera;
|
|
77
|
+
this.material.uniforms.time.value = (this.material.uniforms.time.value + delta) % 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
package/Fire/Fire.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-06-17 02:15:58
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-06-18 20:34:38
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { BufferGeometry, Camera, Clock, Color, Group, Material, NormalBufferAttributes, Object3DEventMap, PerspectiveCamera, Points, Scene, Vector2, WebGLRenderer } from "three";
|
|
9
|
+
import FireGromtry from "./FireGromtry";
|
|
10
|
+
import FireMaterial from "./FireMaterial";
|
|
11
|
+
import { degToRad } from "three/src/math/MathUtils";
|
|
12
|
+
|
|
13
|
+
// 粒子火焰效果
|
|
14
|
+
export default class Fire extends Points {
|
|
15
|
+
|
|
16
|
+
constructor() {
|
|
17
|
+
super();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
geometry = new FireGromtry(0, 0, 0);
|
|
21
|
+
|
|
22
|
+
material = new FireMaterial();
|
|
23
|
+
|
|
24
|
+
// 火焰的颜色
|
|
25
|
+
fireColor = "#ff2200";
|
|
26
|
+
// 火焰的整体缩放值
|
|
27
|
+
fireScale = 1;
|
|
28
|
+
// 火焰的燃烧半径
|
|
29
|
+
fireRadius = 0.5;
|
|
30
|
+
// 火焰的高度
|
|
31
|
+
fireHeight = 3;
|
|
32
|
+
// 火焰的粒子数量
|
|
33
|
+
particleCount = 500;
|
|
34
|
+
// 是否是透视相机
|
|
35
|
+
isPerspectiveCamera = true;
|
|
36
|
+
//渲染器的尺寸
|
|
37
|
+
size = new Vector2();
|
|
38
|
+
|
|
39
|
+
// 缓存的参数
|
|
40
|
+
cacheProps = {
|
|
41
|
+
fireColor: "#ff2200",
|
|
42
|
+
fireScale: 0,
|
|
43
|
+
fireRadius: 0.5,
|
|
44
|
+
fireHeight: 3,
|
|
45
|
+
particleCount: 500,
|
|
46
|
+
width: 0,
|
|
47
|
+
height: 0,
|
|
48
|
+
isPerspectiveCamera: true
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 当前渲染的帧数
|
|
52
|
+
updataFrame = 0;
|
|
53
|
+
|
|
54
|
+
// 时钟对象
|
|
55
|
+
clock = new Clock();
|
|
56
|
+
|
|
57
|
+
onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry<NormalBufferAttributes>, material: Material, group: Group<Object3DEventMap>): void {
|
|
58
|
+
|
|
59
|
+
const delta = this.clock.getDelta();
|
|
60
|
+
renderer.getSize(this.size);
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
this.cacheProps.fireColor !== this.fireColor ||
|
|
64
|
+
this.cacheProps.fireScale !== this.fireScale ||
|
|
65
|
+
this.cacheProps.fireRadius !== this.fireRadius ||
|
|
66
|
+
this.cacheProps.fireHeight !== this.fireHeight ||
|
|
67
|
+
this.cacheProps.particleCount !== this.particleCount ||
|
|
68
|
+
this.cacheProps.isPerspectiveCamera !== this.isPerspectiveCamera ||
|
|
69
|
+
this.cacheProps.width !== this.size.x ||
|
|
70
|
+
this.cacheProps.height !== this.size.y
|
|
71
|
+
) {
|
|
72
|
+
this.cacheProps.fireColor = this.fireColor;
|
|
73
|
+
this.cacheProps.fireScale = this.fireScale;
|
|
74
|
+
this.cacheProps.fireRadius = this.fireRadius;
|
|
75
|
+
this.cacheProps.fireHeight = this.fireHeight;
|
|
76
|
+
this.cacheProps.particleCount = this.particleCount;
|
|
77
|
+
this.cacheProps.isPerspectiveCamera = this.isPerspectiveCamera;
|
|
78
|
+
this.cacheProps.width = this.size.x;
|
|
79
|
+
this.cacheProps.height = this.size.y;
|
|
80
|
+
|
|
81
|
+
this.geometry = new FireGromtry(this.fireRadius * this.fireScale, this.fireHeight * this.fireScale, this.particleCount);
|
|
82
|
+
|
|
83
|
+
this.material.uniforms.color.value = new Color(this.fireColor);
|
|
84
|
+
this.material.uniforms.size.value = this.fireScale * 0.4;
|
|
85
|
+
if ((camera as PerspectiveCamera).isPerspectiveCamera) {
|
|
86
|
+
this.material.uniforms.heightOfNearPlane.value = Math.abs(this.size.y / (2 * Math.tan(degToRad((camera as PerspectiveCamera).fov * 0.5))));
|
|
87
|
+
} else {
|
|
88
|
+
this.material.uniforms.heightOfNearPlane.value = 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.isPerspectiveCamera = (camera as PerspectiveCamera).isPerspectiveCamera;
|
|
94
|
+
|
|
95
|
+
this.material.uniforms.time.value = (this.material.uniforms.time.value + delta) % 1;
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const SPRITE_ROW_LENGTH = 4;
|
|
2
|
+
export declare const ONE_SPRITE_ROW_LENGTH: number;
|
|
3
|
+
import { BufferGeometry } from "three";
|
|
4
|
+
export default class FireGromtry extends BufferGeometry {
|
|
5
|
+
radius: number;
|
|
6
|
+
height: number;
|
|
7
|
+
particleCount: number;
|
|
8
|
+
constructor(radius?: number, height?: number, particleCount?: number);
|
|
9
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-06-17 02:15:58
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-06-18 18:12:37
|
|
6
|
+
*/
|
|
7
|
+
export const SPRITE_ROW_LENGTH = 4; // 粒子图片中图片数量
|
|
8
|
+
export const ONE_SPRITE_ROW_LENGTH = 1 / SPRITE_ROW_LENGTH; // 每一行的宽度
|
|
9
|
+
import { BufferAttribute, BufferGeometry } from "three";
|
|
10
|
+
// 粒子火焰顶点对象
|
|
11
|
+
export default class FireGromtry extends BufferGeometry {
|
|
12
|
+
radius = 0.5;
|
|
13
|
+
height = 3;
|
|
14
|
+
particleCount = 200;
|
|
15
|
+
constructor(radius = 0.5, height = 3, particleCount = 200) {
|
|
16
|
+
super();
|
|
17
|
+
const halfHeight = height * 0.5;
|
|
18
|
+
const position = new Float32Array(particleCount * 3);
|
|
19
|
+
const random = new Float32Array(particleCount);
|
|
20
|
+
const sprite = new Float32Array(particleCount);
|
|
21
|
+
for (let i = 0; i < particleCount; i++) {
|
|
22
|
+
const r = Math.sqrt(Math.random()) * radius;
|
|
23
|
+
const angle = Math.random() * 2 * Math.PI;
|
|
24
|
+
position[i * 3 + 0] = Math.cos(angle) * r;
|
|
25
|
+
position[i * 3 + 1] = (radius - r) / radius * halfHeight + halfHeight;
|
|
26
|
+
position[i * 3 + 2] = Math.sin(angle) * r;
|
|
27
|
+
sprite[i] = ONE_SPRITE_ROW_LENGTH * ((Math.random() * 4) | 0);
|
|
28
|
+
random[i] = Math.random();
|
|
29
|
+
if (i === 0) {
|
|
30
|
+
// to avoid going out of Frustum
|
|
31
|
+
position[i * 3 + 0] = 0;
|
|
32
|
+
position[i * 3 + 1] = 0;
|
|
33
|
+
position[i * 3 + 2] = 0;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
this.setAttribute('position', new BufferAttribute(position, 3));
|
|
37
|
+
this.setAttribute('random', new BufferAttribute(random, 1));
|
|
38
|
+
this.setAttribute('sprite', new BufferAttribute(sprite, 1));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-06-17 02:15:58
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-06-18 18:12:37
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const SPRITE_ROW_LENGTH = 4; // 粒子图片中图片数量
|
|
9
|
+
export const ONE_SPRITE_ROW_LENGTH = 1 / SPRITE_ROW_LENGTH; // 每一行的宽度
|
|
10
|
+
import { BufferAttribute, BufferGeometry } from "three";
|
|
11
|
+
|
|
12
|
+
// 粒子火焰顶点对象
|
|
13
|
+
export default class FireGromtry extends BufferGeometry {
|
|
14
|
+
|
|
15
|
+
radius = 0.5;
|
|
16
|
+
height = 3;
|
|
17
|
+
particleCount = 200;
|
|
18
|
+
|
|
19
|
+
constructor(radius: number = 0.5, height: number = 3, particleCount: number = 200) {
|
|
20
|
+
super();
|
|
21
|
+
|
|
22
|
+
const halfHeight = height * 0.5;
|
|
23
|
+
const position = new Float32Array(particleCount * 3);
|
|
24
|
+
const random = new Float32Array(particleCount);
|
|
25
|
+
const sprite = new Float32Array(particleCount);
|
|
26
|
+
|
|
27
|
+
for (let i = 0; i < particleCount; i++) {
|
|
28
|
+
|
|
29
|
+
const r = Math.sqrt(Math.random()) * radius;
|
|
30
|
+
const angle = Math.random() * 2 * Math.PI;
|
|
31
|
+
position[i * 3 + 0] = Math.cos(angle) * r;
|
|
32
|
+
position[i * 3 + 1] = (radius - r) / radius * halfHeight + halfHeight;
|
|
33
|
+
position[i * 3 + 2] = Math.sin(angle) * r;
|
|
34
|
+
sprite[i] = ONE_SPRITE_ROW_LENGTH * ((Math.random() * 4) | 0);
|
|
35
|
+
random[i] = Math.random();
|
|
36
|
+
|
|
37
|
+
if (i === 0) {
|
|
38
|
+
|
|
39
|
+
// to avoid going out of Frustum
|
|
40
|
+
position[i * 3 + 0] = 0;
|
|
41
|
+
position[i * 3 + 1] = 0;
|
|
42
|
+
position[i * 3 + 2] = 0;
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.setAttribute('position', new BufferAttribute(position, 3));
|
|
49
|
+
this.setAttribute('random', new BufferAttribute(random, 1));
|
|
50
|
+
this.setAttribute('sprite', new BufferAttribute(sprite, 1));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ShaderMaterial } from "three";
|
|
2
|
+
export default class FireMaterial extends ShaderMaterial {
|
|
3
|
+
constructor();
|
|
4
|
+
uniforms: {
|
|
5
|
+
color: {
|
|
6
|
+
value: any;
|
|
7
|
+
};
|
|
8
|
+
size: {
|
|
9
|
+
value: number;
|
|
10
|
+
};
|
|
11
|
+
map: {
|
|
12
|
+
value: import("three").Texture;
|
|
13
|
+
};
|
|
14
|
+
time: {
|
|
15
|
+
value: number;
|
|
16
|
+
};
|
|
17
|
+
heightOfNearPlane: {
|
|
18
|
+
value: number;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
vertexShader: string;
|
|
22
|
+
fragmentShader: string;
|
|
23
|
+
blending: 2;
|
|
24
|
+
depthTest: boolean;
|
|
25
|
+
depthWrite: boolean;
|
|
26
|
+
transparent: boolean;
|
|
27
|
+
fog: boolean;
|
|
28
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-06-17 02:37:46
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-06-18 20:23:31
|
|
6
|
+
*/
|
|
7
|
+
import { AdditiveBlending, ShaderChunk, ShaderMaterial } from "three";
|
|
8
|
+
import threeLoader from "../threeLoader";
|
|
9
|
+
import { ONE_SPRITE_ROW_LENGTH } from "./FireGromtry";
|
|
10
|
+
// 火焰粒子材质
|
|
11
|
+
export default class FireMaterial extends ShaderMaterial {
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
}
|
|
15
|
+
// 材质参数
|
|
16
|
+
uniforms = {
|
|
17
|
+
color: { value: null },
|
|
18
|
+
size: { value: 0.0 },
|
|
19
|
+
map: { value: threeLoader.getTexture("data:image/png;base64,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") },
|
|
20
|
+
time: { value: 0.0 },
|
|
21
|
+
heightOfNearPlane: { value: 0.0 }
|
|
22
|
+
};
|
|
23
|
+
// 顶点着色器
|
|
24
|
+
vertexShader = `
|
|
25
|
+
${ShaderChunk.common}
|
|
26
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
27
|
+
attribute float random;
|
|
28
|
+
attribute float sprite;
|
|
29
|
+
uniform float time;
|
|
30
|
+
uniform float size;
|
|
31
|
+
uniform float heightOfNearPlane;
|
|
32
|
+
|
|
33
|
+
varying float vSprite;
|
|
34
|
+
varying float vOpacity;
|
|
35
|
+
|
|
36
|
+
float quadraticIn( float t ) {
|
|
37
|
+
float tt = t * t;
|
|
38
|
+
return tt * tt;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void main() {
|
|
42
|
+
float progress = fract( time + ( 2.0 * random - 1.0 ) );
|
|
43
|
+
float progressNeg = 1.0 - progress;
|
|
44
|
+
float ease = quadraticIn( progress );
|
|
45
|
+
float influence = sin( PI * ease );
|
|
46
|
+
|
|
47
|
+
vec3 newPosition = position * vec3( 1.0, ease, 1.0 );
|
|
48
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
|
|
49
|
+
gl_PointSize = ( heightOfNearPlane * size ) / gl_Position.w;
|
|
50
|
+
|
|
51
|
+
vOpacity = min( influence * 4.0, 1.0 ) * progressNeg;
|
|
52
|
+
vSprite = sprite;
|
|
53
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
//片元着色器
|
|
57
|
+
fragmentShader = `
|
|
58
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
59
|
+
uniform vec3 color;
|
|
60
|
+
uniform sampler2D map;
|
|
61
|
+
|
|
62
|
+
varying float vSprite;
|
|
63
|
+
varying float vOpacity;
|
|
64
|
+
|
|
65
|
+
void main() {
|
|
66
|
+
vec2 texCoord = vec2(
|
|
67
|
+
gl_PointCoord.x * ${ONE_SPRITE_ROW_LENGTH} + vSprite,
|
|
68
|
+
gl_PointCoord.y
|
|
69
|
+
);
|
|
70
|
+
// gl_FragColor = vec4( texture2D( map, texCoord ).xyz * color * vOpacity, 1.0 );
|
|
71
|
+
vec4 textureColor = texture2D( map, texCoord );
|
|
72
|
+
float colorMax = max(max(textureColor.x, textureColor.y),textureColor.z);
|
|
73
|
+
vec4 newTextureColor = vec4( textureColor.xyz * (100.0) , colorMax);
|
|
74
|
+
gl_FragColor = newTextureColor * vec4(color,1.0) * vOpacity;
|
|
75
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
76
|
+
}
|
|
77
|
+
`;
|
|
78
|
+
blending = AdditiveBlending;
|
|
79
|
+
depthTest = true;
|
|
80
|
+
depthWrite = false;
|
|
81
|
+
transparent = true;
|
|
82
|
+
fog = true;
|
|
83
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-06-17 02:37:46
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2024-06-18 20:23:31
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { AdditiveBlending, LinearSRGBColorSpace, ShaderChunk, ShaderMaterial } from "three";
|
|
9
|
+
import threeLoader from "../threeLoader";
|
|
10
|
+
import { ONE_SPRITE_ROW_LENGTH } from "./FireGromtry";
|
|
11
|
+
import fireMapPNG from "./fireMap.png";
|
|
12
|
+
import fireMap2PNG from "./fireMap2.png";
|
|
13
|
+
import { map } from "lodash";
|
|
14
|
+
|
|
15
|
+
// 火焰粒子材质
|
|
16
|
+
export default class FireMaterial extends ShaderMaterial {
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 材质参数
|
|
23
|
+
uniforms = {
|
|
24
|
+
color: { value: null },
|
|
25
|
+
size: { value: 0.0 },
|
|
26
|
+
map: { value: threeLoader.getTexture("data:image/png;base64,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") },
|
|
27
|
+
time: { value: 0.0 },
|
|
28
|
+
heightOfNearPlane: { value: 0.0 }
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 顶点着色器
|
|
32
|
+
vertexShader = `
|
|
33
|
+
${ShaderChunk.common}
|
|
34
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
35
|
+
attribute float random;
|
|
36
|
+
attribute float sprite;
|
|
37
|
+
uniform float time;
|
|
38
|
+
uniform float size;
|
|
39
|
+
uniform float heightOfNearPlane;
|
|
40
|
+
|
|
41
|
+
varying float vSprite;
|
|
42
|
+
varying float vOpacity;
|
|
43
|
+
|
|
44
|
+
float quadraticIn( float t ) {
|
|
45
|
+
float tt = t * t;
|
|
46
|
+
return tt * tt;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void main() {
|
|
50
|
+
float progress = fract( time + ( 2.0 * random - 1.0 ) );
|
|
51
|
+
float progressNeg = 1.0 - progress;
|
|
52
|
+
float ease = quadraticIn( progress );
|
|
53
|
+
float influence = sin( PI * ease );
|
|
54
|
+
|
|
55
|
+
vec3 newPosition = position * vec3( 1.0, ease, 1.0 );
|
|
56
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
|
|
57
|
+
gl_PointSize = ( heightOfNearPlane * size ) / gl_Position.w;
|
|
58
|
+
|
|
59
|
+
vOpacity = min( influence * 4.0, 1.0 ) * progressNeg;
|
|
60
|
+
vSprite = sprite;
|
|
61
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
62
|
+
}
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
//片元着色器
|
|
66
|
+
fragmentShader = `
|
|
67
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
68
|
+
uniform vec3 color;
|
|
69
|
+
uniform sampler2D map;
|
|
70
|
+
|
|
71
|
+
varying float vSprite;
|
|
72
|
+
varying float vOpacity;
|
|
73
|
+
|
|
74
|
+
void main() {
|
|
75
|
+
vec2 texCoord = vec2(
|
|
76
|
+
gl_PointCoord.x * ${ONE_SPRITE_ROW_LENGTH} + vSprite,
|
|
77
|
+
gl_PointCoord.y
|
|
78
|
+
);
|
|
79
|
+
// gl_FragColor = vec4( texture2D( map, texCoord ).xyz * color * vOpacity, 1.0 );
|
|
80
|
+
vec4 textureColor = texture2D( map, texCoord );
|
|
81
|
+
float colorMax = max(max(textureColor.x, textureColor.y),textureColor.z);
|
|
82
|
+
vec4 newTextureColor = vec4( textureColor.xyz * (100.0) , colorMax);
|
|
83
|
+
gl_FragColor = newTextureColor * vec4(color,1.0) * vOpacity;
|
|
84
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
85
|
+
}
|
|
86
|
+
`
|
|
87
|
+
|
|
88
|
+
blending = AdditiveBlending
|
|
89
|
+
depthTest = true
|
|
90
|
+
depthWrite = false;
|
|
91
|
+
transparent = true
|
|
92
|
+
fog = true
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
}
|
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
```tsx
|
|
2
|
+
|
|
2
3
|
.创建一个 homeRender.ts 模块
|
|
3
4
|
import { AmbientLight, BoxGeometry, Mesh, MeshLambertMaterial, PointLight } from "three";
|
|
4
5
|
import ThreeBase from "three-base";
|
|
5
6
|
import Transition from "three-base/Transition";
|
|
6
7
|
|
|
8
|
+
//qq389652405
|
|
7
9
|
class HomeRender extends ThreeBase {
|
|
8
10
|
|
|
9
11
|
constructor() {
|
|
@@ -35,6 +37,18 @@ class HomeRender extends ThreeBase {
|
|
|
35
37
|
|
|
36
38
|
}
|
|
37
39
|
|
|
40
|
+
//火焰
|
|
41
|
+
fire = (() => {
|
|
42
|
+
const fire = new Fire();
|
|
43
|
+
fire.fireColor = "#ff2200";// 火焰的颜色
|
|
44
|
+
fire.fireScale = 1;// 火焰的整体缩放值
|
|
45
|
+
fire.fireRadius = 0.5;// 火焰的燃烧半径
|
|
46
|
+
fire.fireHeight = 3;// 火焰的高度
|
|
47
|
+
fire.position.set(0, 5, 0);
|
|
48
|
+
this.scene.add(fire);
|
|
49
|
+
return fire;
|
|
50
|
+
})();
|
|
51
|
+
|
|
38
52
|
box = (() => {
|
|
39
53
|
const geometry = new BoxGeometry(10, 10, 10);
|
|
40
54
|
const matearil = new MeshLambertMaterial({ color: 0xfff });
|
package/ThreeBase.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
51
51
|
autoRender: boolean;
|
|
52
52
|
needRender: boolean;
|
|
53
53
|
stopRender(): void;
|
|
54
|
-
|
|
54
|
+
hasPass(): boolean;
|
|
55
55
|
render(): void;
|
|
56
56
|
private renderBindThis;
|
|
57
57
|
download(fileName?: string): void;
|
package/ThreeBase.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2021-12-20 13:38:22
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time: 2024-
|
|
5
|
+
* @Last Modified time: 2024-06-18 21:03:02
|
|
6
6
|
*/
|
|
7
7
|
import { round } from "lodash";
|
|
8
8
|
import { AxesHelper, DepthFormat, DepthTexture, EventDispatcher, GridHelper, LinearFilter, MOUSE, Mesh, NoBlending, NormalBlending, OrthographicCamera, PerspectiveCamera, RGBAFormat, Scene, TOUCH, UnsignedShortType, Vector2, Vector3, WebGLRenderTarget, WebGLRenderer } from "three";
|
|
@@ -339,8 +339,8 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
339
339
|
this.renderer.domElement.style.opacity = "0";
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
|
-
// 判断是否有
|
|
343
|
-
|
|
342
|
+
// 判断是否有 发光和描边等对象 以便判断是否需要 渲染深度纹理
|
|
343
|
+
hasPass() {
|
|
344
344
|
let has_stroke_or_pass = false;
|
|
345
345
|
this.scene.traverse(obj => {
|
|
346
346
|
const { stroke_enable = false, stroke_width = 1, glow_enable = false, glow_width = 1 } = obj.userData;
|
|
@@ -364,7 +364,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
364
364
|
const distaned = this.perspectiveCamera.position.clone().sub(center).length();
|
|
365
365
|
const zoom = 1 / (Math.tan(degToRad(fov) / 2) * distaned);
|
|
366
366
|
this.orthographicCamera.zoom = zoom;
|
|
367
|
-
this.orthographicCamera.position.copy(this.perspectiveCamera.position.clone().sub(center)).setLength(
|
|
367
|
+
this.orthographicCamera.position.copy(this.perspectiveCamera.position.clone().sub(center)).setLength(2500).add(center);
|
|
368
368
|
}
|
|
369
369
|
else if (this.cameraType === "orthographicCamera") {
|
|
370
370
|
const { center } = this.getLookAt();
|
|
@@ -392,8 +392,8 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
392
392
|
}
|
|
393
393
|
// 渲染场景
|
|
394
394
|
this.dispatchEvent({ type: "beforeRender" });
|
|
395
|
-
const
|
|
396
|
-
if (
|
|
395
|
+
const hasPass = this.hasPass();
|
|
396
|
+
if (hasPass) {
|
|
397
397
|
// 把基础场景渲染到 帧缓冲区 在后期通道中会用到
|
|
398
398
|
this.renderer.setRenderTarget(this.baseRenderTarget);
|
|
399
399
|
this.renderer.clear();
|
|
@@ -403,7 +403,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
403
403
|
// 清空主画布
|
|
404
404
|
this.renderer.clear();
|
|
405
405
|
this.renderer.render(this.scene, camera);
|
|
406
|
-
if (
|
|
406
|
+
if (hasPass) {
|
|
407
407
|
// 查找需要绘制描边的对象,并且绘制描边
|
|
408
408
|
this.scene.traverseVisible(obj => {
|
|
409
409
|
stroke_pass(this.renderer, camera, obj, this.baseDepthTexture);
|
package/ThreeBase.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: xiaosihan
|
|
3
3
|
* @Date: 2021-12-20 13:38:22
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
|
-
* @Last Modified time: 2024-
|
|
5
|
+
* @Last Modified time: 2024-06-18 21:03:02
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { add, round } from "lodash";
|
|
@@ -409,8 +409,8 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
409
409
|
}
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
-
// 判断是否有
|
|
413
|
-
|
|
412
|
+
// 判断是否有 发光和描边等对象 以便判断是否需要 渲染深度纹理
|
|
413
|
+
hasPass() {
|
|
414
414
|
let has_stroke_or_pass = false;
|
|
415
415
|
|
|
416
416
|
this.scene.traverse(obj => {
|
|
@@ -438,7 +438,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
438
438
|
const distaned = this.perspectiveCamera.position.clone().sub(center).length();
|
|
439
439
|
const zoom = 1 / (Math.tan(degToRad(fov) / 2) * distaned);
|
|
440
440
|
this.orthographicCamera.zoom = zoom;
|
|
441
|
-
this.orthographicCamera.position.copy(this.perspectiveCamera.position.clone().sub(center)).setLength(
|
|
441
|
+
this.orthographicCamera.position.copy(this.perspectiveCamera.position.clone().sub(center)).setLength(2500).add(center);
|
|
442
442
|
} else if (this.cameraType === "orthographicCamera") {
|
|
443
443
|
const { center } = this.getLookAt();
|
|
444
444
|
const { fov } = this.perspectiveCamera;
|
|
@@ -472,9 +472,9 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
472
472
|
// 渲染场景
|
|
473
473
|
this.dispatchEvent({ type: "beforeRender" } as never);
|
|
474
474
|
|
|
475
|
-
const
|
|
475
|
+
const hasPass = this.hasPass();
|
|
476
476
|
|
|
477
|
-
if (
|
|
477
|
+
if (hasPass) {
|
|
478
478
|
// 把基础场景渲染到 帧缓冲区 在后期通道中会用到
|
|
479
479
|
this.renderer.setRenderTarget(this.baseRenderTarget);
|
|
480
480
|
this.renderer.clear();
|
|
@@ -486,7 +486,7 @@ export default class ThreeBase extends EventDispatcher {
|
|
|
486
486
|
this.renderer.clear();
|
|
487
487
|
this.renderer.render(this.scene, camera);
|
|
488
488
|
|
|
489
|
-
if (
|
|
489
|
+
if (hasPass) {
|
|
490
490
|
// 查找需要绘制描边的对象,并且绘制描边
|
|
491
491
|
this.scene.traverseVisible(obj => {
|
|
492
492
|
stroke_pass(this.renderer, camera, obj, this.baseDepthTexture);
|