@damienmortini/three 0.1.183 → 0.1.185
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/LICENSE +4 -4
- package/copyExamples.js +17 -17
- package/ecs/THREEView.js +31 -31
- package/gpgpu/THREEGPGPUSystem.js +175 -175
- package/loader/THREELoader.js +117 -117
- package/loader/meshoptimizerdecoder/THREE.EXT_meshopt_compression.js +41 -41
- package/loader/meshoptimizerdecoder/meshopt_decoder.js +129 -129
- package/material/THREEBaseMaterial.js +75 -75
- package/material/THREEPBRMaterial.js +107 -107
- package/material/THREEShaderMaterial.js +97 -97
- package/object/THREELine.js +113 -113
- package/object/THREEMotionVectorObject.js +284 -284
- package/object/THREERibbon.js +49 -49
- package/object/THREESky.js +281 -281
- package/object/THREESprite.js +96 -96
- package/object/THREESpriteAnimation.js +103 -103
- package/object/THREEText.js +241 -241
- package/package.json +5 -6
- package/renderer/THREERenderer.js +123 -123
- package/renderer/THREEStereoRenderer.js +60 -60
- package/renderer/WebGLRenderTarget2D.js +63 -63
- package/shader/THREEBaseShader.js +33 -33
- package/types/index.d.ts +1 -1
- package/types/renderer/WebGLRenderTarget2D.d.ts +42 -42
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import THREEShaderMaterial from './THREEShaderMaterial.js'
|
|
2
|
-
import LightShader from '@damienmortini/core/shader/LightShader.js'
|
|
3
|
-
import RayShader from '@damienmortini/core/shader/RayShader.js'
|
|
4
|
-
import PBRShader from '@damienmortini/core/shader/PBRShader.js'
|
|
5
|
-
import { Color, Vector3, ShaderChunk } from '../../../three/src/Three.js'
|
|
6
|
-
|
|
7
|
-
export default class THREEPBRMaterial extends THREEShaderMaterial {
|
|
8
|
-
constructor({
|
|
9
|
-
webgl2 = true,
|
|
10
|
-
vertexChunks = [],
|
|
11
|
-
fragmentChunks = [],
|
|
12
|
-
uniforms = {},
|
|
13
|
-
pbrDiffuseLightFromRay = (uniforms.envMap ? `
|
|
14
|
-
vec4 texel = ${webgl2 ? 'textureLod' : 'textureCubeLodEXT'}(envMap, ray.direction, roughness * ${Math.log2(uniforms.envMap.image.width).toFixed(1)});
|
|
15
|
-
return texel.rgb;
|
|
16
|
-
` : undefined),
|
|
17
|
-
pbrReflectionFromRay = (uniforms.envMap ? `
|
|
18
|
-
vec4 texel = ${webgl2 ? 'textureLod' : 'textureCubeLodEXT'}(envMap, ray.direction, roughness * ${Math.log2(uniforms.envMap.image.width).toFixed(1)});
|
|
19
|
-
return texel.rgb;
|
|
20
|
-
` : undefined),
|
|
21
|
-
...options
|
|
22
|
-
} = {}) {
|
|
23
|
-
super({
|
|
24
|
-
lights: !!uniforms.light,
|
|
25
|
-
uniforms: {
|
|
26
|
-
baseColor: new Color('#ffffff'),
|
|
27
|
-
metalness: 0,
|
|
28
|
-
roughness: 0,
|
|
29
|
-
opacity: 1,
|
|
30
|
-
light: {
|
|
31
|
-
intensity: 0,
|
|
32
|
-
color: new Color('#ffffff'),
|
|
33
|
-
position: new Vector3(),
|
|
34
|
-
direction: new Vector3(),
|
|
35
|
-
},
|
|
36
|
-
...uniforms,
|
|
37
|
-
},
|
|
38
|
-
vertex: `
|
|
39
|
-
void main() {
|
|
40
|
-
}
|
|
41
|
-
`,
|
|
42
|
-
vertexChunks: [
|
|
43
|
-
['start', `
|
|
44
|
-
${options.skinning ? '#include <skinning_pars_vertex>' : ''}
|
|
45
|
-
|
|
46
|
-
varying vec3 vPosition;
|
|
47
|
-
varying vec3 vNormal;
|
|
48
|
-
varying vec2 vUv;
|
|
49
|
-
varying vec3 vWorldPosition;
|
|
50
|
-
varying vec3 vViewDirection;
|
|
51
|
-
`],
|
|
52
|
-
['main', `
|
|
53
|
-
vec3 pbrPosition = position;
|
|
54
|
-
vec3 pbrNormal = normal;
|
|
55
|
-
|
|
56
|
-
${options.skinning ? ShaderChunk.skinbase_vertex : ''}
|
|
57
|
-
${options.skinning ? ShaderChunk.skinnormal_vertex.replace(/objectNormal/g, 'pbrNormal') : ''}
|
|
58
|
-
${options.skinning ? ShaderChunk.skinning_vertex.replace(/transformed/g, 'pbrPosition') : ''}
|
|
59
|
-
`],
|
|
60
|
-
['end', `
|
|
61
|
-
vec3 pbrWorldPosition = (modelMatrix * vec4(pbrPosition, 1.)).xyz;
|
|
62
|
-
gl_Position = projectionMatrix * viewMatrix * vec4(pbrWorldPosition, 1.);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
vWorldPosition = pbrWorldPosition;
|
|
66
|
-
vViewDirection = normalize(pbrWorldPosition - cameraPosition);
|
|
67
|
-
vPosition = pbrPosition;
|
|
68
|
-
vNormal = normalize(mat3(modelMatrix) * pbrNormal);
|
|
69
|
-
vUv = uv;
|
|
70
|
-
`],
|
|
71
|
-
...vertexChunks,
|
|
72
|
-
],
|
|
73
|
-
fragmentChunks: [
|
|
74
|
-
['start', `
|
|
75
|
-
${LightShader.Light}
|
|
76
|
-
${RayShader.Ray}
|
|
77
|
-
${PBRShader.MetallicRoughnessMaterial}
|
|
78
|
-
|
|
79
|
-
uniform vec3 baseColor;
|
|
80
|
-
uniform float metalness;
|
|
81
|
-
uniform float roughness;
|
|
82
|
-
uniform float opacity;
|
|
83
|
-
uniform Light light;
|
|
84
|
-
${uniforms.envMap ? 'uniform samplerCube envMap;' : ''}
|
|
85
|
-
${uniforms.map ? 'uniform sampler2D map;' : ''}
|
|
86
|
-
|
|
87
|
-
varying vec3 vNormal;
|
|
88
|
-
varying vec3 vPosition;
|
|
89
|
-
varying vec2 vUv;
|
|
90
|
-
varying vec3 vWorldPosition;
|
|
91
|
-
varying vec3 vViewDirection;
|
|
92
|
-
|
|
93
|
-
${PBRShader.computePBRColor({ pbrReflectionFromRay, pbrDiffuseLightFromRay })}
|
|
94
|
-
`],
|
|
95
|
-
['main', `
|
|
96
|
-
${uniforms.map ? 'vec4 mapTexel = texture2D(map, vUv);' : ''}
|
|
97
|
-
vec4 pbrColor = computePBRColor(vViewDirection, light, vPosition, vNormal, MetallicRoughnessMaterial(vec4(${uniforms.map ? 'baseColor * pow(mapTexel.rgb, vec3(2.2))' : 'baseColor'}, ${uniforms.map ? 'opacity * mapTexel.a' : 'opacity'}), metalness, roughness));
|
|
98
|
-
`],
|
|
99
|
-
['end', `
|
|
100
|
-
gl_FragColor = pbrColor;
|
|
101
|
-
`],
|
|
102
|
-
...fragmentChunks,
|
|
103
|
-
],
|
|
104
|
-
...options,
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
}
|
|
1
|
+
import THREEShaderMaterial from './THREEShaderMaterial.js'
|
|
2
|
+
import LightShader from '@damienmortini/core/shader/LightShader.js'
|
|
3
|
+
import RayShader from '@damienmortini/core/shader/RayShader.js'
|
|
4
|
+
import PBRShader from '@damienmortini/core/shader/PBRShader.js'
|
|
5
|
+
import { Color, Vector3, ShaderChunk } from '../../../three/src/Three.js'
|
|
6
|
+
|
|
7
|
+
export default class THREEPBRMaterial extends THREEShaderMaterial {
|
|
8
|
+
constructor({
|
|
9
|
+
webgl2 = true,
|
|
10
|
+
vertexChunks = [],
|
|
11
|
+
fragmentChunks = [],
|
|
12
|
+
uniforms = {},
|
|
13
|
+
pbrDiffuseLightFromRay = (uniforms.envMap ? `
|
|
14
|
+
vec4 texel = ${webgl2 ? 'textureLod' : 'textureCubeLodEXT'}(envMap, ray.direction, roughness * ${Math.log2(uniforms.envMap.image.width).toFixed(1)});
|
|
15
|
+
return texel.rgb;
|
|
16
|
+
` : undefined),
|
|
17
|
+
pbrReflectionFromRay = (uniforms.envMap ? `
|
|
18
|
+
vec4 texel = ${webgl2 ? 'textureLod' : 'textureCubeLodEXT'}(envMap, ray.direction, roughness * ${Math.log2(uniforms.envMap.image.width).toFixed(1)});
|
|
19
|
+
return texel.rgb;
|
|
20
|
+
` : undefined),
|
|
21
|
+
...options
|
|
22
|
+
} = {}) {
|
|
23
|
+
super({
|
|
24
|
+
lights: !!uniforms.light,
|
|
25
|
+
uniforms: {
|
|
26
|
+
baseColor: new Color('#ffffff'),
|
|
27
|
+
metalness: 0,
|
|
28
|
+
roughness: 0,
|
|
29
|
+
opacity: 1,
|
|
30
|
+
light: {
|
|
31
|
+
intensity: 0,
|
|
32
|
+
color: new Color('#ffffff'),
|
|
33
|
+
position: new Vector3(),
|
|
34
|
+
direction: new Vector3(),
|
|
35
|
+
},
|
|
36
|
+
...uniforms,
|
|
37
|
+
},
|
|
38
|
+
vertex: `
|
|
39
|
+
void main() {
|
|
40
|
+
}
|
|
41
|
+
`,
|
|
42
|
+
vertexChunks: [
|
|
43
|
+
['start', `
|
|
44
|
+
${options.skinning ? '#include <skinning_pars_vertex>' : ''}
|
|
45
|
+
|
|
46
|
+
varying vec3 vPosition;
|
|
47
|
+
varying vec3 vNormal;
|
|
48
|
+
varying vec2 vUv;
|
|
49
|
+
varying vec3 vWorldPosition;
|
|
50
|
+
varying vec3 vViewDirection;
|
|
51
|
+
`],
|
|
52
|
+
['main', `
|
|
53
|
+
vec3 pbrPosition = position;
|
|
54
|
+
vec3 pbrNormal = normal;
|
|
55
|
+
|
|
56
|
+
${options.skinning ? ShaderChunk.skinbase_vertex : ''}
|
|
57
|
+
${options.skinning ? ShaderChunk.skinnormal_vertex.replace(/objectNormal/g, 'pbrNormal') : ''}
|
|
58
|
+
${options.skinning ? ShaderChunk.skinning_vertex.replace(/transformed/g, 'pbrPosition') : ''}
|
|
59
|
+
`],
|
|
60
|
+
['end', `
|
|
61
|
+
vec3 pbrWorldPosition = (modelMatrix * vec4(pbrPosition, 1.)).xyz;
|
|
62
|
+
gl_Position = projectionMatrix * viewMatrix * vec4(pbrWorldPosition, 1.);
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
vWorldPosition = pbrWorldPosition;
|
|
66
|
+
vViewDirection = normalize(pbrWorldPosition - cameraPosition);
|
|
67
|
+
vPosition = pbrPosition;
|
|
68
|
+
vNormal = normalize(mat3(modelMatrix) * pbrNormal);
|
|
69
|
+
vUv = uv;
|
|
70
|
+
`],
|
|
71
|
+
...vertexChunks,
|
|
72
|
+
],
|
|
73
|
+
fragmentChunks: [
|
|
74
|
+
['start', `
|
|
75
|
+
${LightShader.Light}
|
|
76
|
+
${RayShader.Ray}
|
|
77
|
+
${PBRShader.MetallicRoughnessMaterial}
|
|
78
|
+
|
|
79
|
+
uniform vec3 baseColor;
|
|
80
|
+
uniform float metalness;
|
|
81
|
+
uniform float roughness;
|
|
82
|
+
uniform float opacity;
|
|
83
|
+
uniform Light light;
|
|
84
|
+
${uniforms.envMap ? 'uniform samplerCube envMap;' : ''}
|
|
85
|
+
${uniforms.map ? 'uniform sampler2D map;' : ''}
|
|
86
|
+
|
|
87
|
+
varying vec3 vNormal;
|
|
88
|
+
varying vec3 vPosition;
|
|
89
|
+
varying vec2 vUv;
|
|
90
|
+
varying vec3 vWorldPosition;
|
|
91
|
+
varying vec3 vViewDirection;
|
|
92
|
+
|
|
93
|
+
${PBRShader.computePBRColor({ pbrReflectionFromRay, pbrDiffuseLightFromRay })}
|
|
94
|
+
`],
|
|
95
|
+
['main', `
|
|
96
|
+
${uniforms.map ? 'vec4 mapTexel = texture2D(map, vUv);' : ''}
|
|
97
|
+
vec4 pbrColor = computePBRColor(vViewDirection, light, vPosition, vNormal, MetallicRoughnessMaterial(vec4(${uniforms.map ? 'baseColor * pow(mapTexel.rgb, vec3(2.2))' : 'baseColor'}, ${uniforms.map ? 'opacity * mapTexel.a' : 'opacity'}), metalness, roughness));
|
|
98
|
+
`],
|
|
99
|
+
['end', `
|
|
100
|
+
gl_FragColor = pbrColor;
|
|
101
|
+
`],
|
|
102
|
+
...fragmentChunks,
|
|
103
|
+
],
|
|
104
|
+
...options,
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ShaderMaterial,
|
|
3
|
-
ShaderLib,
|
|
4
|
-
UniformsUtils,
|
|
5
|
-
} from '../../../three/src/Three.js'
|
|
6
|
-
import DEFAULT_VERTEX from '../../../three/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js'
|
|
7
|
-
import DEFAULT_FRAGMENT from '../../../three/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js'
|
|
8
|
-
|
|
9
|
-
import Shader from '@damienmortini/core/3d/Shader.js'
|
|
10
|
-
|
|
11
|
-
const toWebGL1 = (source, type) => {
|
|
12
|
-
source = source.replace(/#version.*?\n/g, '')
|
|
13
|
-
source = source.replace(/\btexture\b/g, 'texture2D')
|
|
14
|
-
if (type === 'vertex') {
|
|
15
|
-
source = source.replace(/(^\s*)\bin\b/gm, '$1attribute')
|
|
16
|
-
source = source.replace(/(^\s*)\bout\b/gm, '$1varying')
|
|
17
|
-
} else {
|
|
18
|
-
source = source.replace(/(^\s*)\bin\b/gm, '$1varying')
|
|
19
|
-
const results = /out vec4 (.*?);/.exec(source)
|
|
20
|
-
if (results) {
|
|
21
|
-
const fragColorName = results[1]
|
|
22
|
-
source = source.replace(/out.*?;/, '')
|
|
23
|
-
source = source.replace(new RegExp(`\\b${fragColorName}\\b`, 'g'), 'gl_FragColor')
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return source
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default class THREEShaderMaterial extends ShaderMaterial {
|
|
30
|
-
constructor({
|
|
31
|
-
type = '',
|
|
32
|
-
vertex = undefined,
|
|
33
|
-
fragment = undefined,
|
|
34
|
-
vertexChunks = [],
|
|
35
|
-
fragmentChunks = [],
|
|
36
|
-
uniforms = {},
|
|
37
|
-
...options
|
|
38
|
-
} = {}) {
|
|
39
|
-
const shader = new Shader({
|
|
40
|
-
vertex: vertex || (type ? ShaderLib[type].vertexShader : DEFAULT_VERTEX),
|
|
41
|
-
fragment: fragment || (type ? ShaderLib[type].fragmentShader : DEFAULT_FRAGMENT),
|
|
42
|
-
uniforms,
|
|
43
|
-
vertexChunks,
|
|
44
|
-
fragmentChunks,
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
const threeUniforms = {}
|
|
48
|
-
for (const [key, value] of Object.entries(shader.uniforms)) {
|
|
49
|
-
if (value?.value !== undefined) {
|
|
50
|
-
continue
|
|
51
|
-
}
|
|
52
|
-
threeUniforms[key] = {
|
|
53
|
-
value,
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
super({
|
|
58
|
-
fragmentShader: toWebGL1(shader.fragment, 'fragment'),
|
|
59
|
-
vertexShader: toWebGL1(shader.vertex, 'vertex'),
|
|
60
|
-
uniforms: {
|
|
61
|
-
...(type ? UniformsUtils.clone(ShaderLib[type].uniforms) : {}),
|
|
62
|
-
...threeUniforms,
|
|
63
|
-
},
|
|
64
|
-
...options,
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
this.lights = /lambert|phong|standard/.test(type)
|
|
68
|
-
|
|
69
|
-
for (const key of Object.keys(this.uniforms)) {
|
|
70
|
-
Object.defineProperty(this, key, {
|
|
71
|
-
configurable: true,
|
|
72
|
-
get: function () {
|
|
73
|
-
return this.uniforms[key].value
|
|
74
|
-
},
|
|
75
|
-
set: function (value) {
|
|
76
|
-
this.uniforms[key].value = value
|
|
77
|
-
},
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
clone() {
|
|
83
|
-
const clone = super.clone()
|
|
84
|
-
for (const key of Object.keys(clone.uniforms)) {
|
|
85
|
-
Object.defineProperty(clone, key, {
|
|
86
|
-
configurable: true,
|
|
87
|
-
get: function () {
|
|
88
|
-
return this.uniforms[key].value
|
|
89
|
-
},
|
|
90
|
-
set: function (value) {
|
|
91
|
-
this.uniforms[key].value = value
|
|
92
|
-
},
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
return clone
|
|
96
|
-
}
|
|
97
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
ShaderMaterial,
|
|
3
|
+
ShaderLib,
|
|
4
|
+
UniformsUtils,
|
|
5
|
+
} from '../../../three/src/Three.js'
|
|
6
|
+
import DEFAULT_VERTEX from '../../../three/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js'
|
|
7
|
+
import DEFAULT_FRAGMENT from '../../../three/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js'
|
|
8
|
+
|
|
9
|
+
import Shader from '@damienmortini/core/3d/Shader.js'
|
|
10
|
+
|
|
11
|
+
const toWebGL1 = (source, type) => {
|
|
12
|
+
source = source.replace(/#version.*?\n/g, '')
|
|
13
|
+
source = source.replace(/\btexture\b/g, 'texture2D')
|
|
14
|
+
if (type === 'vertex') {
|
|
15
|
+
source = source.replace(/(^\s*)\bin\b/gm, '$1attribute')
|
|
16
|
+
source = source.replace(/(^\s*)\bout\b/gm, '$1varying')
|
|
17
|
+
} else {
|
|
18
|
+
source = source.replace(/(^\s*)\bin\b/gm, '$1varying')
|
|
19
|
+
const results = /out vec4 (.*?);/.exec(source)
|
|
20
|
+
if (results) {
|
|
21
|
+
const fragColorName = results[1]
|
|
22
|
+
source = source.replace(/out.*?;/, '')
|
|
23
|
+
source = source.replace(new RegExp(`\\b${fragColorName}\\b`, 'g'), 'gl_FragColor')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return source
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default class THREEShaderMaterial extends ShaderMaterial {
|
|
30
|
+
constructor({
|
|
31
|
+
type = '',
|
|
32
|
+
vertex = undefined,
|
|
33
|
+
fragment = undefined,
|
|
34
|
+
vertexChunks = [],
|
|
35
|
+
fragmentChunks = [],
|
|
36
|
+
uniforms = {},
|
|
37
|
+
...options
|
|
38
|
+
} = {}) {
|
|
39
|
+
const shader = new Shader({
|
|
40
|
+
vertex: vertex || (type ? ShaderLib[type].vertexShader : DEFAULT_VERTEX),
|
|
41
|
+
fragment: fragment || (type ? ShaderLib[type].fragmentShader : DEFAULT_FRAGMENT),
|
|
42
|
+
uniforms,
|
|
43
|
+
vertexChunks,
|
|
44
|
+
fragmentChunks,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const threeUniforms = {}
|
|
48
|
+
for (const [key, value] of Object.entries(shader.uniforms)) {
|
|
49
|
+
if (value?.value !== undefined) {
|
|
50
|
+
continue
|
|
51
|
+
}
|
|
52
|
+
threeUniforms[key] = {
|
|
53
|
+
value,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
super({
|
|
58
|
+
fragmentShader: toWebGL1(shader.fragment, 'fragment'),
|
|
59
|
+
vertexShader: toWebGL1(shader.vertex, 'vertex'),
|
|
60
|
+
uniforms: {
|
|
61
|
+
...(type ? UniformsUtils.clone(ShaderLib[type].uniforms) : {}),
|
|
62
|
+
...threeUniforms,
|
|
63
|
+
},
|
|
64
|
+
...options,
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
this.lights = /lambert|phong|standard/.test(type)
|
|
68
|
+
|
|
69
|
+
for (const key of Object.keys(this.uniforms)) {
|
|
70
|
+
Object.defineProperty(this, key, {
|
|
71
|
+
configurable: true,
|
|
72
|
+
get: function () {
|
|
73
|
+
return this.uniforms[key].value
|
|
74
|
+
},
|
|
75
|
+
set: function (value) {
|
|
76
|
+
this.uniforms[key].value = value
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
clone() {
|
|
83
|
+
const clone = super.clone()
|
|
84
|
+
for (const key of Object.keys(clone.uniforms)) {
|
|
85
|
+
Object.defineProperty(clone, key, {
|
|
86
|
+
configurable: true,
|
|
87
|
+
get: function () {
|
|
88
|
+
return this.uniforms[key].value
|
|
89
|
+
},
|
|
90
|
+
set: function (value) {
|
|
91
|
+
this.uniforms[key].value = value
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
return clone
|
|
96
|
+
}
|
|
97
|
+
}
|
package/object/THREELine.js
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
import FrenetSerretFrame from '@damienmortini/core/math/FrenetSerretFrame.js'
|
|
2
|
-
|
|
3
|
-
import THREEShaderMaterial from './THREEShaderMaterial.js'
|
|
4
|
-
|
|
5
|
-
export default class THREELine extends THREE.Mesh {
|
|
6
|
-
constructor({
|
|
7
|
-
points = [new THREE.Vector3(0, -1, 0), new THREE.Vector3(0, 1, 0)],
|
|
8
|
-
material = new THREEShaderMaterial(),
|
|
9
|
-
detail = 3,
|
|
10
|
-
thickness = .1,
|
|
11
|
-
geometry = new THREE.CylinderBufferGeometry(1, 1, points.length - 1, detail, points.length - 1),
|
|
12
|
-
} = {}) {
|
|
13
|
-
super(geometry, material)
|
|
14
|
-
|
|
15
|
-
this.points = points
|
|
16
|
-
|
|
17
|
-
this.userData._thickness = thickness
|
|
18
|
-
this.userData._lineNormals = new Float32Array(this.points.length * 3)
|
|
19
|
-
this.userData._linePositions = new Float32Array(this.points.length * 3)
|
|
20
|
-
|
|
21
|
-
this.frustumCulled = false
|
|
22
|
-
|
|
23
|
-
const positions = this.geometry.getAttribute('position').array
|
|
24
|
-
const verticesNumber = positions.length / 3
|
|
25
|
-
const ids = new Float32Array(verticesNumber)
|
|
26
|
-
const offsetY = (points.length - 1) / 2
|
|
27
|
-
for (let i = 0; i < verticesNumber; i++) {
|
|
28
|
-
ids[i] = positions[i * 3 + 1] + offsetY
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
this.geometry.addAttribute('linePointId', new THREE.BufferAttribute(ids, 1))
|
|
32
|
-
|
|
33
|
-
if (!material.linePositions) {
|
|
34
|
-
material.add({
|
|
35
|
-
vertexShaderChunks: [
|
|
36
|
-
['start', `
|
|
37
|
-
uniform float lineThickness;
|
|
38
|
-
uniform vec3 linePositions[${this.points.length}];
|
|
39
|
-
uniform vec3 lineNormals[${this.points.length}];
|
|
40
|
-
|
|
41
|
-
attribute float linePointId;
|
|
42
|
-
`],
|
|
43
|
-
['main', `
|
|
44
|
-
vec3 position = position;
|
|
45
|
-
vec3 normal = normal;
|
|
46
|
-
|
|
47
|
-
vec3 linePosition = linePositions[int(linePointId)];
|
|
48
|
-
vec3 lineDirection = normalize(linePointId == ${this.points.length - 1}. ? linePosition - linePositions[int(linePointId) - 1] : linePositions[int(linePointId) + 1] - linePosition);
|
|
49
|
-
vec3 lineNormal = lineNormals[int(linePointId)];
|
|
50
|
-
vec3 lineBinormal = cross(lineNormal, lineDirection);
|
|
51
|
-
|
|
52
|
-
mat3 lineRotationMatrix = mat3(
|
|
53
|
-
lineNormal,
|
|
54
|
-
lineDirection,
|
|
55
|
-
lineBinormal
|
|
56
|
-
);
|
|
57
|
-
position.y = 0.;
|
|
58
|
-
position = linePosition + lineRotationMatrix * position * lineThickness;
|
|
59
|
-
normal = lineRotationMatrix * normal;
|
|
60
|
-
`],
|
|
61
|
-
],
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this.update()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
onBeforeRender(renderer, scene, camera, geometry, material, group) {
|
|
69
|
-
this.material.lineThickness = this.userData._thickness
|
|
70
|
-
this.material.lineNormals = this.userData._lineNormals
|
|
71
|
-
this.material.linePositions = this.userData._linePositions
|
|
72
|
-
|
|
73
|
-
const threeProgram = renderer.properties.get(material).program
|
|
74
|
-
|
|
75
|
-
if (!threeProgram) {
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const gl = renderer.getContext()
|
|
80
|
-
const uniforms = threeProgram.getUniforms()
|
|
81
|
-
|
|
82
|
-
gl.useProgram(threeProgram.program)
|
|
83
|
-
uniforms.setValue(gl, 'lineThickness', this.userData._thickness)
|
|
84
|
-
uniforms.setValue(gl, 'lineNormals', this.userData._lineNormals)
|
|
85
|
-
uniforms.setValue(gl, 'linePositions', this.userData._linePositions)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
set thickness(value) {
|
|
89
|
-
this.userData._thickness = value
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
get thickness() {
|
|
93
|
-
return this.userData._thickness
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
update({
|
|
97
|
-
range = [0, this.points.length - 1],
|
|
98
|
-
} = {}) {
|
|
99
|
-
const end = range[1]
|
|
100
|
-
for (let i = range[0]; i <= end; i++) {
|
|
101
|
-
const point = this.points[i]
|
|
102
|
-
this.userData._linePositions[i * 3] = point.x
|
|
103
|
-
this.userData._linePositions[i * 3 + 1] = point.y
|
|
104
|
-
this.userData._linePositions[i * 3 + 2] = point.z
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
FrenetSerretFrame.compute({
|
|
108
|
-
positions: this.userData._linePositions,
|
|
109
|
-
normals: this.userData._lineNormals,
|
|
110
|
-
range,
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
}
|
|
1
|
+
import FrenetSerretFrame from '@damienmortini/core/math/FrenetSerretFrame.js'
|
|
2
|
+
|
|
3
|
+
import THREEShaderMaterial from './THREEShaderMaterial.js'
|
|
4
|
+
|
|
5
|
+
export default class THREELine extends THREE.Mesh {
|
|
6
|
+
constructor({
|
|
7
|
+
points = [new THREE.Vector3(0, -1, 0), new THREE.Vector3(0, 1, 0)],
|
|
8
|
+
material = new THREEShaderMaterial(),
|
|
9
|
+
detail = 3,
|
|
10
|
+
thickness = .1,
|
|
11
|
+
geometry = new THREE.CylinderBufferGeometry(1, 1, points.length - 1, detail, points.length - 1),
|
|
12
|
+
} = {}) {
|
|
13
|
+
super(geometry, material)
|
|
14
|
+
|
|
15
|
+
this.points = points
|
|
16
|
+
|
|
17
|
+
this.userData._thickness = thickness
|
|
18
|
+
this.userData._lineNormals = new Float32Array(this.points.length * 3)
|
|
19
|
+
this.userData._linePositions = new Float32Array(this.points.length * 3)
|
|
20
|
+
|
|
21
|
+
this.frustumCulled = false
|
|
22
|
+
|
|
23
|
+
const positions = this.geometry.getAttribute('position').array
|
|
24
|
+
const verticesNumber = positions.length / 3
|
|
25
|
+
const ids = new Float32Array(verticesNumber)
|
|
26
|
+
const offsetY = (points.length - 1) / 2
|
|
27
|
+
for (let i = 0; i < verticesNumber; i++) {
|
|
28
|
+
ids[i] = positions[i * 3 + 1] + offsetY
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.geometry.addAttribute('linePointId', new THREE.BufferAttribute(ids, 1))
|
|
32
|
+
|
|
33
|
+
if (!material.linePositions) {
|
|
34
|
+
material.add({
|
|
35
|
+
vertexShaderChunks: [
|
|
36
|
+
['start', `
|
|
37
|
+
uniform float lineThickness;
|
|
38
|
+
uniform vec3 linePositions[${this.points.length}];
|
|
39
|
+
uniform vec3 lineNormals[${this.points.length}];
|
|
40
|
+
|
|
41
|
+
attribute float linePointId;
|
|
42
|
+
`],
|
|
43
|
+
['main', `
|
|
44
|
+
vec3 position = position;
|
|
45
|
+
vec3 normal = normal;
|
|
46
|
+
|
|
47
|
+
vec3 linePosition = linePositions[int(linePointId)];
|
|
48
|
+
vec3 lineDirection = normalize(linePointId == ${this.points.length - 1}. ? linePosition - linePositions[int(linePointId) - 1] : linePositions[int(linePointId) + 1] - linePosition);
|
|
49
|
+
vec3 lineNormal = lineNormals[int(linePointId)];
|
|
50
|
+
vec3 lineBinormal = cross(lineNormal, lineDirection);
|
|
51
|
+
|
|
52
|
+
mat3 lineRotationMatrix = mat3(
|
|
53
|
+
lineNormal,
|
|
54
|
+
lineDirection,
|
|
55
|
+
lineBinormal
|
|
56
|
+
);
|
|
57
|
+
position.y = 0.;
|
|
58
|
+
position = linePosition + lineRotationMatrix * position * lineThickness;
|
|
59
|
+
normal = lineRotationMatrix * normal;
|
|
60
|
+
`],
|
|
61
|
+
],
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.update()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
onBeforeRender(renderer, scene, camera, geometry, material, group) {
|
|
69
|
+
this.material.lineThickness = this.userData._thickness
|
|
70
|
+
this.material.lineNormals = this.userData._lineNormals
|
|
71
|
+
this.material.linePositions = this.userData._linePositions
|
|
72
|
+
|
|
73
|
+
const threeProgram = renderer.properties.get(material).program
|
|
74
|
+
|
|
75
|
+
if (!threeProgram) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const gl = renderer.getContext()
|
|
80
|
+
const uniforms = threeProgram.getUniforms()
|
|
81
|
+
|
|
82
|
+
gl.useProgram(threeProgram.program)
|
|
83
|
+
uniforms.setValue(gl, 'lineThickness', this.userData._thickness)
|
|
84
|
+
uniforms.setValue(gl, 'lineNormals', this.userData._lineNormals)
|
|
85
|
+
uniforms.setValue(gl, 'linePositions', this.userData._linePositions)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
set thickness(value) {
|
|
89
|
+
this.userData._thickness = value
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get thickness() {
|
|
93
|
+
return this.userData._thickness
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
update({
|
|
97
|
+
range = [0, this.points.length - 1],
|
|
98
|
+
} = {}) {
|
|
99
|
+
const end = range[1]
|
|
100
|
+
for (let i = range[0]; i <= end; i++) {
|
|
101
|
+
const point = this.points[i]
|
|
102
|
+
this.userData._linePositions[i * 3] = point.x
|
|
103
|
+
this.userData._linePositions[i * 3 + 1] = point.y
|
|
104
|
+
this.userData._linePositions[i * 3 + 2] = point.z
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
FrenetSerretFrame.compute({
|
|
108
|
+
positions: this.userData._linePositions,
|
|
109
|
+
normals: this.userData._lineNormals,
|
|
110
|
+
range,
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|