@octanejs/drei 0.0.1

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.
Files changed (152) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/UPSTREAM.md +92 -0
  4. package/package.json +96 -0
  5. package/src/config.ts +14 -0
  6. package/src/core/AccumulativeShadows.three.tsrx +313 -0
  7. package/src/core/AdaptivePerformance.three.tsrx +49 -0
  8. package/src/core/AsciiRenderer.three.tsrx +61 -0
  9. package/src/core/Bounds.three.tsrx +323 -0
  10. package/src/core/Bvh.three.tsrx +116 -0
  11. package/src/core/CameraControls.three.tsrx +181 -0
  12. package/src/core/CameraShake.three.tsrx +104 -0
  13. package/src/core/Caustics.three.tsrx +107 -0
  14. package/src/core/Center.three.tsrx +145 -0
  15. package/src/core/Clone.three.tsrx +167 -0
  16. package/src/core/Cloud.three.tsrx +314 -0
  17. package/src/core/ComputedAttribute.three.tsrx +27 -0
  18. package/src/core/ContactShadows.three.tsrx +106 -0
  19. package/src/core/CubeTexture.three.tsrx +32 -0
  20. package/src/core/CurveModifier.three.tsrx +37 -0
  21. package/src/core/Decal.three.tsrx +132 -0
  22. package/src/core/Detailed.three.tsrx +28 -0
  23. package/src/core/DetectGPU.three.tsrx +22 -0
  24. package/src/core/Effects.three.tsrx +123 -0
  25. package/src/core/Environment.three.tsrx +220 -0
  26. package/src/core/Example.three.tsrx +56 -0
  27. package/src/core/Fbo.three.tsrx +70 -0
  28. package/src/core/Fbx.three.tsrx +25 -0
  29. package/src/core/Fisheye.three.tsrx +82 -0
  30. package/src/core/GizmoHelper.three.tsrx +115 -0
  31. package/src/core/GizmoViewcube.three.tsrx +82 -0
  32. package/src/core/GizmoViewport.three.tsrx +122 -0
  33. package/src/core/Gltf.three.tsrx +62 -0
  34. package/src/core/GradientTexture.three.tsrx +66 -0
  35. package/src/core/Grid.three.tsrx +170 -0
  36. package/src/core/Helper.three.tsrx +56 -0
  37. package/src/core/Hud.three.tsrx +52 -0
  38. package/src/core/Image.three.tsrx +146 -0
  39. package/src/core/Instances.three.tsrx +332 -0
  40. package/src/core/Ktx2.three.tsrx +59 -0
  41. package/src/core/Lightformer.three.tsrx +75 -0
  42. package/src/core/MarchingCubes.three.tsrx +125 -0
  43. package/src/core/MeshPortalMaterial.three.tsrx +103 -0
  44. package/src/core/MeshReflectorMaterial.three.tsrx +67 -0
  45. package/src/core/MeshRefractionMaterial.three.tsrx +70 -0
  46. package/src/core/MeshTransmissionMaterial.three.tsrx +71 -0
  47. package/src/core/MotionPathControls.three.tsrx +139 -0
  48. package/src/core/MultiMaterial.three.tsrx +32 -0
  49. package/src/core/Outlines.three.tsrx +162 -0
  50. package/src/core/PerformanceMonitor.three.tsrx +144 -0
  51. package/src/core/PointerLockControls.three.tsrx +84 -0
  52. package/src/core/Points.three.tsrx +242 -0
  53. package/src/core/PositionalAudio.three.tsrx +76 -0
  54. package/src/core/Preload.three.tsrx +40 -0
  55. package/src/core/Progress.three.tsrx +47 -0
  56. package/src/core/RenderCubeTexture.three.tsrx +111 -0
  57. package/src/core/RenderTexture.three.tsrx +102 -0
  58. package/src/core/Resize.three.tsrx +59 -0
  59. package/src/core/RoundedBox.three.tsrx +106 -0
  60. package/src/core/Sampler.three.tsrx +116 -0
  61. package/src/core/ScreenSizer.three.tsrx +43 -0
  62. package/src/core/ScreenSpace.three.tsrx +21 -0
  63. package/src/core/Segments.three.tsrx +119 -0
  64. package/src/core/Sky.three.tsrx +63 -0
  65. package/src/core/Sparkles.three.tsrx +145 -0
  66. package/src/core/Splat.three.tsrx +52 -0
  67. package/src/core/SpotLight.three.tsrx +350 -0
  68. package/src/core/SpriteAnimator.three.tsrx +338 -0
  69. package/src/core/Stage.three.tsrx +112 -0
  70. package/src/core/Stars.three.tsrx +103 -0
  71. package/src/core/Stats.three.tsrx +35 -0
  72. package/src/core/StatsGl.three.tsrx +60 -0
  73. package/src/core/Svg.three.tsrx +82 -0
  74. package/src/core/Text.three.tsrx +96 -0
  75. package/src/core/Text3D.three.tsrx +90 -0
  76. package/src/core/Texture.three.tsrx +72 -0
  77. package/src/core/Trail.three.tsrx +167 -0
  78. package/src/core/TrailTexture.three.tsrx +171 -0
  79. package/src/core/TransformControls.three.tsrx +155 -0
  80. package/src/core/VideoTexture.three.tsrx +116 -0
  81. package/src/core/Wireframe.three.tsrx +92 -0
  82. package/src/core/basic-controls.three.tsrx +353 -0
  83. package/src/core/calculateScaleFactor.ts +42 -0
  84. package/src/core/cameras.three.tsrx +230 -0
  85. package/src/core/catalog-resource.ts +12 -0
  86. package/src/core/catalog-textures.three.tsrx +105 -0
  87. package/src/core/compiler-slot.ts +9 -0
  88. package/src/core/effects-utils.ts +8 -0
  89. package/src/core/environment-loader.ts +87 -0
  90. package/src/core/font-resource.ts +31 -0
  91. package/src/core/gltf-loader.ts +33 -0
  92. package/src/core/gradient-types.ts +4 -0
  93. package/src/core/index.ts +295 -0
  94. package/src/core/lines.three.tsrx +329 -0
  95. package/src/core/meshBounds.ts +26 -0
  96. package/src/core/motion-materials.three.tsrx +93 -0
  97. package/src/core/octane-children.ts +18 -0
  98. package/src/core/octane-element.ts +16 -0
  99. package/src/core/resource.ts +29 -0
  100. package/src/core/scene-motion.three.tsrx +183 -0
  101. package/src/core/shaderMaterial.ts +50 -0
  102. package/src/core/shadows.three.tsrx +164 -0
  103. package/src/core/shapes.three.tsrx +170 -0
  104. package/src/core/simple-materials.three.tsrx +124 -0
  105. package/src/core/softShadows.three.tsrx +151 -0
  106. package/src/core/splat-resource.ts +598 -0
  107. package/src/core/useAnimations.three.tsrx +57 -0
  108. package/src/core/useAspect.three.tsrx +10 -0
  109. package/src/core/useBoxProjectedEnv.three.tsrx +113 -0
  110. package/src/core/useCamera.three.tsrx +26 -0
  111. package/src/core/useContextBridge.three.tsrx +25 -0
  112. package/src/core/useDepthBuffer.three.tsrx +35 -0
  113. package/src/core/useEnvironment.three.tsrx +81 -0
  114. package/src/core/useFont.three.tsrx +12 -0
  115. package/src/core/useIntersect.three.tsrx +38 -0
  116. package/src/core/useSpriteLoader.three.tsrx +249 -0
  117. package/src/core/video-texture-resource.ts +14 -0
  118. package/src/index.ts +2 -0
  119. package/src/materials/BlurPass.ts +94 -0
  120. package/src/materials/CausticsMaterials.ts +197 -0
  121. package/src/materials/ConvolutionMaterial.ts +65 -0
  122. package/src/materials/MeshReflectorMaterial.ts +180 -0
  123. package/src/materials/MeshRefractionMaterial.ts +131 -0
  124. package/src/materials/MeshTransmissionMaterial.ts +182 -0
  125. package/src/materials/PortalMaterial.ts +38 -0
  126. package/src/materials/WireframeMaterial.ts +241 -0
  127. package/src/materials/makeSDFGenerator.ts +155 -0
  128. package/src/troika-three-text.d.ts +19 -0
  129. package/src/web/CycleRaycast.three.tsrx +81 -0
  130. package/src/web/DragControls.three.tsrx +82 -0
  131. package/src/web/FaceControls.three.tsrx +178 -0
  132. package/src/web/FaceLandmarker.three.tsrx +48 -0
  133. package/src/web/Facemesh.three.tsrx +464 -0
  134. package/src/web/Html.three.tsrx +390 -0
  135. package/src/web/KeyboardControls.three.tsrx +98 -0
  136. package/src/web/Loader.tsrx +61 -0
  137. package/src/web/PresentationControls.three.tsrx +63 -0
  138. package/src/web/ScrollControls.three.tsrx +120 -0
  139. package/src/web/Select.three.tsrx +155 -0
  140. package/src/web/View.three.tsrx +46 -0
  141. package/src/web/face-landmarker-resource.ts +18 -0
  142. package/src/web/facemesh-data.ts +54 -0
  143. package/src/web/index.ts +41 -0
  144. package/src/web/keyboard-controls-types.ts +33 -0
  145. package/src/web/media-textures.three.tsrx +50 -0
  146. package/src/web/pivotControls/annotation.tsrx +17 -0
  147. package/src/web/pivotControls/context.ts +38 -0
  148. package/src/web/pivotControls/index.three.tsrx +877 -0
  149. package/src/web/scroll-html-root.tsrx +27 -0
  150. package/src/web/useCursor.three.tsrx +19 -0
  151. package/src/web/useGesture.ts +27 -0
  152. package/status.json +14 -0
@@ -0,0 +1,119 @@
1
+ /** @jsxImportSource @octanejs/three/intrinsics */
2
+ import { type Color, type ThreeRef, type Vector3 as Vector3Prop, useFrame } from '@octanejs/three';
3
+ import { useLayoutEffect, useMemo, useRef, useState } from '@octanejs/three/renderer';
4
+ import { createContext, useContext } from 'octane';
5
+ import type { OctaneNode } from 'octane';
6
+ import * as THREE from 'three';
7
+ import { Line2, LineMaterial, type LineMaterialParameters, LineSegmentsGeometry } from 'three-stdlib';
8
+
9
+ export type SegmentsProps = LineMaterialParameters & {
10
+ limit?: number;
11
+ lineWidth?: number;
12
+ children: OctaneNode;
13
+ };
14
+
15
+ export class SegmentObject {
16
+ color = new THREE.Color('white');
17
+ start = new THREE.Vector3();
18
+ end = new THREE.Vector3();
19
+ }
20
+
21
+ type SegmentRef = { current: SegmentObject | null };
22
+ type SegmentsApi = { subscribe(ref: SegmentRef): () => void };
23
+ const SegmentsContext = createContext<SegmentsApi | null>(null);
24
+
25
+ function assignRef<T>(ref: ThreeRef<T> | undefined, value: T | null): void {
26
+ if (Array.isArray(ref)) for (const item of ref) assignRef(item, value);
27
+ else if (typeof ref === 'function') ref(value);
28
+ else if (ref && 'current' in ref) ref.current = value;
29
+ }
30
+
31
+ export function Segments({
32
+ limit = 1000,
33
+ lineWidth = 1,
34
+ children,
35
+ ref,
36
+ ...rest
37
+ }: SegmentsProps & { ref?: ThreeRef<Line2> }) @{
38
+ const [segments, setSegments] = useState<SegmentRef[]>([]);
39
+ const [line] = useState(() => new Line2());
40
+ const [material] = useState(() => new LineMaterial());
41
+ const [geometry] = useState(() => new LineSegmentsGeometry());
42
+ const [resolution] = useState(() => new THREE.Vector2(512, 512));
43
+ const [positions] = useState<number[]>(() => Array(limit * 6).fill(0));
44
+ const [colors] = useState<number[]>(() => Array(limit * 6).fill(0));
45
+ const api = useMemo<SegmentsApi>(() => ({
46
+ subscribe(segmentRef) {
47
+ setSegments((current) => [...current, segmentRef]);
48
+ return () => setSegments((current) => current.filter((item) => item.current !== segmentRef.current));
49
+ },
50
+ }), []);
51
+ useFrame(() => {
52
+ for (let index = 0; index < limit; index++) {
53
+ const segment = segments[index]?.current;
54
+ if (!segment) continue;
55
+ positions[index * 6] = segment.start.x;
56
+ positions[index * 6 + 1] = segment.start.y;
57
+ positions[index * 6 + 2] = segment.start.z;
58
+ positions[index * 6 + 3] = segment.end.x;
59
+ positions[index * 6 + 4] = segment.end.y;
60
+ positions[index * 6 + 5] = segment.end.z;
61
+ colors[index * 6] = segment.color.r;
62
+ colors[index * 6 + 1] = segment.color.g;
63
+ colors[index * 6 + 2] = segment.color.b;
64
+ colors[index * 6 + 3] = segment.color.r;
65
+ colors[index * 6 + 4] = segment.color.g;
66
+ colors[index * 6 + 5] = segment.color.b;
67
+ }
68
+ geometry.setColors(colors);
69
+ geometry.setPositions(positions);
70
+ line.computeLineDistances();
71
+ });
72
+ const mergedRef = useMemo(() => (value: Line2 | null) => assignRef(ref, value), [ref]);
73
+ <primitive object={line} ref={mergedRef as any}>
74
+ <primitive object={geometry} attach="geometry" />
75
+ <primitive
76
+ object={material}
77
+ attach="material"
78
+ vertexColors={true}
79
+ resolution={resolution}
80
+ linewidth={lineWidth}
81
+ {...rest as any}
82
+ />
83
+ <SegmentsContext.Provider value={api}>{children}</SegmentsContext.Provider>
84
+ </primitive>
85
+ }
86
+
87
+ export type SegmentProps = {
88
+ start: Vector3Prop;
89
+ end: Vector3Prop;
90
+ color?: Color;
91
+ };
92
+
93
+ function normalizePosition(position: SegmentProps['start']): THREE.Vector3 {
94
+ if (position instanceof THREE.Vector3) return position;
95
+ return new THREE.Vector3(...(typeof position === 'number'
96
+ ? [position, position, position] as [number, number, number]
97
+ : position));
98
+ }
99
+
100
+ export function Segment({ color, start, end, ref }: SegmentProps & {
101
+ ref?: ThreeRef<SegmentObject>;
102
+ }) @{
103
+ const api = useContext(SegmentsContext);
104
+ if (!api) throw new Error('Segment must used inside Segments component.');
105
+ const objectRef = useRef<SegmentObject | null>(null);
106
+ const [object] = useState(() => new SegmentObject());
107
+ const mergedRef = useMemo(
108
+ () => (value: SegmentObject | null) => { objectRef.current = value; assignRef(ref, value); },
109
+ [ref],
110
+ );
111
+ useLayoutEffect(() => api.subscribe(objectRef), [api]);
112
+ <primitive
113
+ object={object}
114
+ ref={mergedRef as any}
115
+ color={color}
116
+ start={normalizePosition(start)}
117
+ end={normalizePosition(end)}
118
+ />
119
+ }
@@ -0,0 +1,63 @@
1
+ /** @jsxImportSource @octanejs/three/intrinsics */
2
+ import { type ThreeRef, type Vector3 as Vector3Prop } from '@octanejs/three';
3
+ import { useMemo, useState } from '@octanejs/three/renderer';
4
+ import * as THREE from 'three';
5
+ import { Sky as SkyImpl } from 'three-stdlib';
6
+
7
+ export type SkyProps = {
8
+ distance?: number;
9
+ sunPosition?: Vector3Prop;
10
+ inclination?: number;
11
+ azimuth?: number;
12
+ mieCoefficient?: number;
13
+ mieDirectionalG?: number;
14
+ rayleigh?: number;
15
+ turbidity?: number;
16
+ };
17
+
18
+ export function calcPosFromAngles(
19
+ inclination: number,
20
+ azimuth: number,
21
+ vector: THREE.Vector3 = new THREE.Vector3(),
22
+ ): THREE.Vector3 {
23
+ const theta = Math.PI * (inclination - 0.5);
24
+ const phi = 2 * Math.PI * (azimuth - 0.5);
25
+ vector.x = Math.cos(phi);
26
+ vector.y = Math.sin(theta);
27
+ vector.z = Math.sin(phi);
28
+ return vector;
29
+ }
30
+
31
+ function assignRef<T>(ref: ThreeRef<T> | undefined, value: T | null): void {
32
+ if (Array.isArray(ref)) for (const item of ref) assignRef(item, value);
33
+ else if (typeof ref === 'function') ref(value);
34
+ else if (ref && 'current' in ref) ref.current = value;
35
+ }
36
+
37
+ export function Sky({
38
+ inclination = 0.6,
39
+ azimuth = 0.1,
40
+ distance = 1000,
41
+ mieCoefficient = 0.005,
42
+ mieDirectionalG = 0.8,
43
+ rayleigh = 0.5,
44
+ turbidity = 10,
45
+ sunPosition = calcPosFromAngles(inclination, azimuth),
46
+ ref,
47
+ ...props
48
+ }: SkyProps & { ref?: ThreeRef<SkyImpl> }) @{
49
+ const scale = useMemo(() => new THREE.Vector3().setScalar(distance), [distance]);
50
+ const [sky] = useState(() => new SkyImpl());
51
+ const mergedRef = useMemo(() => (value: SkyImpl | null) => assignRef(ref, value), [ref]);
52
+ <primitive
53
+ object={sky}
54
+ ref={mergedRef}
55
+ material-uniforms-mieCoefficient-value={mieCoefficient}
56
+ material-uniforms-mieDirectionalG-value={mieDirectionalG}
57
+ material-uniforms-rayleigh-value={rayleigh}
58
+ material-uniforms-sunPosition-value={sunPosition}
59
+ material-uniforms-turbidity-value={turbidity}
60
+ scale={scale}
61
+ {...props}
62
+ />
63
+ }
@@ -0,0 +1,145 @@
1
+ /** @jsxImportSource @octanejs/three/intrinsics */
2
+ import { type ThreeElements, type ThreeRef, useFrame, useThree } from '@octanejs/three';
3
+ import { useMemo, useRef, useState } from '@octanejs/three/renderer';
4
+ import * as THREE from 'three';
5
+
6
+ export class SparklesImplMaterial extends THREE.ShaderMaterial {
7
+ constructor() {
8
+ super({
9
+ uniforms: { time: { value: 0 }, pixelRatio: { value: 1 } },
10
+ vertexShader: `uniform float pixelRatio;
11
+ uniform float time;
12
+ attribute float size;
13
+ attribute float speed;
14
+ attribute float opacity;
15
+ attribute vec3 noise;
16
+ attribute vec3 color;
17
+ varying vec3 vColor;
18
+ varying float vOpacity;
19
+ void main() {
20
+ vec4 modelPosition = modelMatrix * vec4(position, 1.0);
21
+ modelPosition.y += sin(time * speed + modelPosition.x * noise.x * 100.0) * 0.2;
22
+ modelPosition.z += cos(time * speed + modelPosition.x * noise.y * 100.0) * 0.2;
23
+ modelPosition.x += cos(time * speed + modelPosition.x * noise.z * 100.0) * 0.2;
24
+ vec4 viewPosition = viewMatrix * modelPosition;
25
+ gl_Position = projectionMatrix * viewPosition;
26
+ gl_PointSize = size * 25. * pixelRatio;
27
+ gl_PointSize *= (1.0 / - viewPosition.z);
28
+ vColor = color;
29
+ vOpacity = opacity;
30
+ }`,
31
+ fragmentShader: `varying vec3 vColor;
32
+ varying float vOpacity;
33
+ void main() {
34
+ float distanceToCenter = distance(gl_PointCoord, vec2(0.5));
35
+ float strength = 0.05 / distanceToCenter - 0.1;
36
+ gl_FragColor = vec4(vColor, strength * vOpacity);
37
+ #include <tonemapping_fragment>
38
+ #include <colorspace_fragment>
39
+ }`,
40
+ });
41
+ }
42
+ get time(): number { return this.uniforms.time.value; }
43
+ set time(value: number) { this.uniforms.time.value = value; }
44
+ get pixelRatio(): number { return this.uniforms.pixelRatio.value; }
45
+ set pixelRatio(value: number) { this.uniforms.pixelRatio.value = value; }
46
+ }
47
+
48
+ function isFloat32Array(value: unknown): value is Float32Array {
49
+ return Boolean(value) && (value as Float32Array).constructor === Float32Array;
50
+ }
51
+
52
+ function isVector(value: unknown): value is THREE.Vector2 | THREE.Vector3 | THREE.Vector4 {
53
+ return value instanceof THREE.Vector2 || value instanceof THREE.Vector3 || value instanceof THREE.Vector4;
54
+ }
55
+
56
+ function normalizeVector(value: unknown): number[] {
57
+ if (Array.isArray(value)) return value;
58
+ if (isVector(value)) return value.toArray();
59
+ return [value, value, value] as number[];
60
+ }
61
+
62
+ function attribute<T>(count: number, prop?: T | Float32Array, setDefault?: (value: T) => number) {
63
+ if (prop !== undefined) {
64
+ if (isFloat32Array(prop)) return prop;
65
+ if (prop instanceof THREE.Color) {
66
+ return Float32Array.from(Array.from({ length: count * 3 }, () => [prop.r, prop.g, prop.b]).flat());
67
+ }
68
+ if (isVector(prop) || Array.isArray(prop)) {
69
+ return Float32Array.from(Array.from({ length: count * 3 }, () => normalizeVector(prop)).flat());
70
+ }
71
+ return Float32Array.from({ length: count }, () => prop as number);
72
+ }
73
+ return Float32Array.from({ length: count }, setDefault!);
74
+ }
75
+
76
+ export type SparklesProps = Omit<ThreeElements['points'], 'ref' | 'scale'> & {
77
+ count?: number;
78
+ speed?: number | Float32Array;
79
+ opacity?: number | Float32Array;
80
+ color?: THREE.ColorRepresentation | Float32Array;
81
+ size?: number | Float32Array;
82
+ scale?: number | [number, number, number] | THREE.Vector3;
83
+ noise?: number | [number, number, number] | THREE.Vector3 | Float32Array;
84
+ };
85
+
86
+ function assignRef<T>(ref: ThreeRef<T> | undefined, value: T | null): void {
87
+ if (Array.isArray(ref)) for (const item of ref) assignRef(item, value);
88
+ else if (typeof ref === 'function') ref(value);
89
+ else if (ref && 'current' in ref) ref.current = value;
90
+ }
91
+
92
+ export function Sparkles({
93
+ noise = 1,
94
+ count = 100,
95
+ speed = 1,
96
+ opacity = 1,
97
+ scale = 1,
98
+ size,
99
+ color,
100
+ children,
101
+ ref,
102
+ ...props
103
+ }: SparklesProps & { ref?: ThreeRef<THREE.Points> }) @{
104
+ const localRef = useRef<THREE.Points | null>(null);
105
+ const dpr = useThree((state) => state.viewport.dpr);
106
+ const normalizedScale = normalizeVector(scale);
107
+ const positions = useMemo(
108
+ () => Float32Array.from(Array.from({ length: count }, () => normalizedScale.map(THREE.MathUtils.randFloatSpread)).flat()),
109
+ [count, ...normalizedScale],
110
+ );
111
+ const sizes = useMemo(() => attribute<number>(count, size, Math.random), [count, size]);
112
+ const opacities = useMemo(() => attribute<number>(count, opacity), [count, opacity]);
113
+ const speeds = useMemo(() => attribute<number>(count, speed), [count, speed]);
114
+ const noises = useMemo(() => attribute<typeof noise>(count * 3, noise), [count, noise]);
115
+ const colors = useMemo(
116
+ () => attribute<THREE.ColorRepresentation>(
117
+ color === undefined ? count * 3 : count,
118
+ !isFloat32Array(color) ? new THREE.Color(color) : color,
119
+ () => 1,
120
+ ),
121
+ [count, color],
122
+ );
123
+ const [material] = useState(() => new SparklesImplMaterial());
124
+ material.pixelRatio = dpr;
125
+ material.transparent = true;
126
+ material.depthWrite = false;
127
+ const mergedRef = useMemo(
128
+ () => (value: THREE.Points | null) => { localRef.current = value; assignRef(ref, value); },
129
+ [ref],
130
+ );
131
+ useFrame((state) => {
132
+ if (localRef.current?.material) (localRef.current.material as SparklesImplMaterial).time = state.clock.elapsedTime;
133
+ });
134
+ <points key={`particle-${count}-${JSON.stringify(scale)}`} {...props} ref={mergedRef}>
135
+ <bufferGeometry>
136
+ <bufferAttribute attach="attributes-position" args={[positions, 3]} />
137
+ <bufferAttribute attach="attributes-size" args={[sizes, 1]} />
138
+ <bufferAttribute attach="attributes-opacity" args={[opacities, 1]} />
139
+ <bufferAttribute attach="attributes-speed" args={[speeds, 1]} />
140
+ <bufferAttribute attach="attributes-color" args={[colors, 3]} />
141
+ <bufferAttribute attach="attributes-noise" args={[noises, 3]} />
142
+ </bufferGeometry>
143
+ {children || <primitive object={material} attach="material" />}
144
+ </points>
145
+ }
@@ -0,0 +1,52 @@
1
+ /** @jsxImportSource @octanejs/three/intrinsics */
2
+ import { extend, useFrame, useLoader, useThree } from '@octanejs/three';
3
+ import { useLayoutEffect, useRef } from '@octanejs/three/renderer';
4
+ import * as THREE from 'three';
5
+ import {
6
+ SplatLoader,
7
+ SplatMaterial,
8
+ type SharedState,
9
+ type SplatProps,
10
+ type TargetMesh,
11
+ } from './splat-resource.js';
12
+
13
+ export type { SharedState, SplatMaterialType, SplatProps, TargetMesh } from './splat-resource.js';
14
+
15
+ const SplatMaterialElement = extend(SplatMaterial);
16
+
17
+ export function Splat({
18
+ src,
19
+ toneMapped = false,
20
+ alphaTest = 0,
21
+ alphaHash = false,
22
+ chunkSize = 25000,
23
+ ...props
24
+ }: SplatProps) @{
25
+ const ref = useRef<TargetMesh | null>(null);
26
+ const gl = useThree((state) => state.gl) as unknown as THREE.WebGLRenderer;
27
+ const camera = useThree((state) => state.camera);
28
+ const shared = useLoader(SplatLoader, src, (loader) => {
29
+ loader.gl = gl;
30
+ loader.chunkSize = chunkSize;
31
+ }) as SharedState;
32
+ useLayoutEffect(() => {
33
+ if (!ref.current) return;
34
+ return shared.connect(ref.current);
35
+ }, [src]);
36
+ useFrame(() => { if (ref.current) shared.update(ref.current, camera, alphaHash); });
37
+ <mesh ref={ref} frustumCulled={false} {...props as any}>
38
+ <SplatMaterialElement {...({
39
+ key: `${src}/${alphaTest}/${alphaHash}${SplatMaterial.key}`,
40
+ transparent: !alphaHash,
41
+ depthTest: true,
42
+ alphaTest: alphaHash ? 0 : alphaTest,
43
+ centerAndScaleTexture: shared.centerAndScaleTexture,
44
+ covAndColorTexture: shared.covAndColorTexture,
45
+ depthWrite: alphaHash ? true : alphaTest > 0,
46
+ blending: alphaHash ? THREE.NormalBlending : THREE.CustomBlending,
47
+ blendSrcAlpha: THREE.OneFactor,
48
+ alphaHash: Boolean(alphaHash),
49
+ toneMapped,
50
+ } as any)} />
51
+ </mesh>
52
+ }