Favivon - Correção

This commit is contained in:
2026-05-30 19:59:39 -03:00
parent 76ddaa815d
commit d7dfd221f0
32859 changed files with 5459654 additions and 404 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 react-spring
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+852
View File
@@ -0,0 +1,852 @@
[![Storybook](https://img.shields.io/static/v1?message=Storybook&style=flat&colorA=000000&colorB=000000&label=&logo=storybook&logoColor=ffffff)](https://drei.pmnd.rs/)
[![Version](https://img.shields.io/npm/v/@react-three/drei?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/@react-three/drei)
[![Downloads](https://img.shields.io/npm/dt/@react-three/drei.svg?style=flat&colorA=000000&colorB=000000)](https://www.npmjs.com/package/@react-three/drei)
[![Discord Shield](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=ffffff)](https://discord.com/channels/740090768164651008/741751532592038022)
[![Open in GitHub Codespaces](https://img.shields.io/static/v1?&message=Open%20in%20%20Codespaces&style=flat&colorA=000000&colorB=000000&label=GitHub&logo=github&logoColor=ffffff)](https://github.com/codespaces/new?template_repository=pmndrs%2Fdrei)
[![logo](docs/logo.jpg)](https://codesandbox.io/s/bfplr)
A growing collection of useful helpers and fully functional, ready-made abstractions for [@react-three/fiber](https://github.com/pmndrs/react-three-fiber).
If you make a component that is generic enough to be useful to others, think about [CONTRIBUTING](CONTRIBUTING.md)!
```bash
npm install @react-three/drei
```
> [!IMPORTANT]
> this package is using the stand-alone [`three-stdlib`](https://github.com/pmndrs/three-stdlib) instead of [`three/examples/jsm`](https://github.com/mrdoob/three.js/tree/master/examples/jsm).
## Basic usage
```jsx
import { PerspectiveCamera, PositionalAudio, ... } from '@react-three/drei'
```
## React-native
```jsx
import { PerspectiveCamera, PositionalAudio, ... } from '@react-three/drei/native'
```
The `native` route of the library **does not** export `Html` or `Loader`. The default export of the library is `web` which **does** export `Html` and `Loader`.
## Documentation
https://pmndrs.github.io/drei
<details>
<summary>Old doc</summary>
> [!WARNING]
> Below is an archive of the anchors links with their new respective locations to the documentation website.
> Do not update the links below, they are for reference only.
<!-- <table>
<tr>
<td valign="top">
<ul>
<li><a href="#cameras">Cameras</a></li>
<ul>
<li><a href="#perspectivecamera">PerspectiveCamera</a></li>
<li><a href="#orthographiccamera">OrthographicCamera</a></li>
<li><a href="#cubecamera">CubeCamera</a></li>
</ul>
<li><a href="#controls">Controls</a></li>
<ul>
<li><a href="#cameracontrols">CameraControls</a></li>
<li><a href="#controls">FlyControls</a></li>
<li><a href="#controls">MapControls</a></li>
<li><a href="#controls">DeviceOrientationControls</a></li>
<li><a href="#controls">TrackballControls</a></li>
<li><a href="#controls">ArcballControls</a></li>
<li><a href="#controls">PointerLockControls</a></li>
<li><a href="#controls">FirstPersonControls</a></li>
<li><a href="#scrollcontrols">ScrollControls</a></li>
<li><a href="#presentationcontrols">PresentationControls</a></li>
<li><a href="#keyboardcontrols">KeyboardControls</a></li>
<li><a href="#FaceControls">FaceControls</a></li>
<li><a href="#motionpathcontrols">MotionPathControls</a></li>
</ul>
<li><a href="#gizmos">Gizmos</a></li>
<ul>
<li><a href="#gizmohelper">GizmoHelper</a></li>
<li><a href="#pivotcontrols">PivotControls</a></li>
<li><a href="#dragcontrols">DragControls</a></li>
<li><a href="#transformcontrols">TransformControls</a></li>
<li><a href="#grid">Grid</a></li>
<li><a href="#helper--usehelper">Helper / useHelper</a></li>
<li><a href="#helper">Helper</a></li>
</ul>
<li><a href="#abstractions">Abstractions</a></li>
<ul>
<li><a href="#image">Image</a></li>
<li><a href="#text">Text</a></li>
<li><a href="#text3d">Text3D</a></li>
<li><a href="#positionalaudio">PositionalAudio</a></li>
<li><a href="#billboard">Billboard</a></li>
<li><a href="#screenspace">ScreenSpace</a></li>
<li><a href="#screensizer">ScreenSizer</a></li>
<li><a href="#effects">Effects</a></li>
<li><a href="#gradienttexture">GradientTexture</a></li>
<li><a href="#edges">Edges</a></li>
<li><a href="#outlines">Outlines</a></li>
<li><a href="#trail">Trail</a></li>
<li><a href="#sampler">Sampler</a></li>
<li><a href="#computedattribute">ComputedAttribute</a></li>
<li><a href="#clone">Clone</a></li>
<li><a href="#useanimations">useAnimations</a></li>
<li><a href="#marchingcubes">MarchingCubes</a></li>
<li><a href="#decal">Decal</a></li>
<li><a href="#svg">Svg</a></li>
<li><a href="#gltf">Gltf</a></li>
<li><a href="#asciirenderer">AsciiRenderer</a></li>
<li><a href="#splat">Splat</a></li>
</ul>
<li><a href="#shaders">Shaders</a></li>
<ul>
<li><a href="#meshreflectormaterial">MeshReflectorMaterial</a></li>
<li><a href="#meshwobblematerial">MeshWobbleMaterial</a></li>
<li><a href="#meshdistortmaterial">MeshDistortMaterial</a></li>
<li><a href="#meshrefractionmaterial">MeshRefractionMaterial</a></li>
<li><a href="#meshtransmissionmaterial">MeshTransmissionMaterial</a></li>
<li><a href="#meshdiscardmaterial">MeshDiscardMaterial</a></li>
<li><a href="#pointmaterial">PointMaterial</a></li>
<li><a href="#softshadows">SoftShadows</a></li>
<li><a href="#shadermaterial">shaderMaterial</a></li>
</ul>
</ul>
</td>
<td valign="top">
<ul>
<li><a href="#misc">Misc</a></li>
<ul>
<li><a href="#example">Example</a></li>
<li><a href="#html">Html</a></li>
<li><a href="#cycleraycast">CycleRaycast</a></li>
<li><a href="#select">Select</a></li>
<li><a href="#sprite-animator">Sprite Animator</a></li>
<li><a href="#stats">Stats</a></li>
<li><a href="#stats-gl">StatsGl</a></li>
<li><a href="#wireframe">Wireframe</a></li>
<li><a href="#usedepthbuffer">useDepthBuffer</a></li>
<li><a href="#usecontextbridge">useContextBridge</a></li>
<li><a href="#fbo--usefbo">Fbo / useFBO</a></li>
<li><a href="#usecamera">useCamera</a></li>
<li><a href="#cubecamera--usecubecamera">CubeCamera / useCubeCamera</a></li>
<li><a href="#detectgpu--usedetectgpu">DetectGPU / useDetectGPU</a></li>
<li><a href="#useaspect">useAspect</a></li>
<li><a href="#usecursor">useCursor</a></li>
<li><a href="#useintersect">useIntersect</a></li>
<li><a href="#useboxprojectedenv">useBoxProjectedEnv</a></li>
<li><a href="#trail--useTrail">Trail / useTrail</a></li>
<li><a href="#useSurfaceSampler">useSurfaceSampler</a></li>
<li><a href="#facelandmarker">FaceLandmarker</a></li>
</ul>
<li><a href="#loading">Loaders</a></li>
<ul>
<li><a href="#loader">Loader</a></li>
<li><a href="#progress--useprogress">Progress / useProgress</a></li>
<li><a href="#gltf--usegltf">Gltf / useGLTF</a></li>
<li><a href="#fbx--usefbx">FBX / useFBX</a></li>
<li><a href="#texture--usetexture">Texture / useTexture</a></li>
<li><a href="#ktx2--usektx2">Ktx2 / useKTX2</a></li>
<li><a href="#cubetexture--usecubetexture">CubeTexture / useCubeTexture</a></li>
<li><a href="#videotexture--usevideotexture">VideoTexture / useVideoTexture</a></li>
<li><a href="#trailtexture--usetrailtexture">TrailTexture / useTrailTexture</a></li>
<li><a href="#usefont">useFont</a></li>
<li><a href="#usespriteloader">useSpriteLoader</a></li>
</ul>
<li><a href="#performance">Performance</a></li>
<ul>
<li><a href="#instances">Instances</a></li>
<li><a href="#merged">Merged</a></li>
<li><a href="#points">Points</a></li>
<li><a href="#segments">Segments</a></li>
<li><a href="#detailed">Detailed</a></li>
<li><a href="#preload">Preload</a></li>
<li><a href="#bakeshadows">BakeShadows</a></li>
<li><a href="#meshbounds">meshBounds</a></li>
<li><a href="#adaptivedpr">AdaptiveDpr</a></li>
<li><a href="#adaptiveevents">AdaptiveEvents</a></li>
<li><a href="#bvh">Bvh</a></li>
<li><a href="#performancemonitor">PerformanceMonitor</a></li>
</ul>
<li><a href="#portals">Portals</a></li>
<ul>
<li><a href="#hud">Hud</a></li>
<li><a href="#view">View</a></li>
<li><a href="#rendertexture">RenderTexture</a></li>
<li><a href="#rendercubetexture">RenderCubeTexture</a></li>
<li><a href="#fisheye">Fisheye</a></li>
<li><a href="#mask">Mask</a></li>
<li><a href="#meshportalmaterial">MeshPortalMaterial</a></li>
</ul>
<li><a href="#modifiers">Modifiers</a></li>
<ul>
<li><a href="#curvemodifier">CurveModifier</a></li>
</ul>
</ul>
</td>
<td valign="top">
<ul>
<li><a href="#shapes">Shapes</a></li>
<ul>
<li><a href="#shapes">Plane</a></li>
<li><a href="#shapes">Box</a></li>
<li><a href="#shapes">Sphere</a></li>
<li><a href="#shapes">Circle</a></li>
<li><a href="#shapes">Cone</a></li>
<li><a href="#shapes">Cylinder</a></li>
<li><a href="#shapes">Tube</a></li>
<li><a href="#shapes">Torus</a></li>
<li><a href="#shapes">TorusKnot</a></li>
<li><a href="#shapes">Ring</a></li>
<li><a href="#shapes">Tetrahedron</a></li>
<li><a href="#shapes">Polyhedron</a></li>
<li><a href="#shapes">Icosahedron</a></li>
<li><a href="#shapes">Octahedron</a></li>
<li><a href="#shapes">Dodecahedron</a></li>
<li><a href="#shapes">Extrude</a></li>
<li><a href="#shapes">Lathe</a></li>
<li><a href="#shapes">Shape</a></li>
<li><a href="#roundedbox">RoundedBox</a></li>
<li><a href="#screenquad">Screenquad</a></li>
<li><a href="#line">Line</a></li>
<li><a href="#quadraticbezierline">QuadraticBezierLine</a></li>
<li><a href="#cubicbezierline">CubicBezierLine</a></li>
<li><a href="#catmullromline">CatmullRomLine</a></li>
<li><a href="#facemesh">Facemesh</a></li>
</ul>
<li><a href="#staging">Staging</a></li>
<ul>
<li><a href="#center">Center</a></li>
<li><a href="#resize">Resize</a></li>
<li><a href="#BBAnchor">BBAnchor</a></li>
<li><a href="#bounds">Bounds</a></li>
<li><a href="#camerashake">CameraShake</a></li>
<li><a href="#float">Float</a></li>
<li><a href="#stage">Stage</a></li>
<li><a href="#backdrop">Backdrop</a></li>
<li><a href="#environment">Environment</a></li>
<li><a href="#lightformer">Lightformer</a></li>
<li><a href="#spotlight">SpotLight</a></li>
<li><a href="#spotlightshadow">SpotLightShadow</a></li>
<li><a href="#shadow">Shadow</a></li>
<li><a href="#caustics">Caustics</a></li>
<li><a href="#contactshadows">ContactShadows</a></li>
<li><a href="#randomizedlight">RandomizedLight</a></li>
<li><a href="#accumulativeshadows">AccumulativeShadows</a></li>
<li><a href="#sky">Sky</a></li>
<li><a href="#stars">Stars</a></li>
<li><a href="#sparkles">Sparkles</a></li>
<li><a href="#cloud">Cloud</a></li>
<li><a href="#useenvironment">useEnvironment</a></li>
<li><a href="#matcaptexture--usematcaptexture">MatcapTexture / useMatcapTexture</a></li>
<li><a href="#normaltexture--usenormaltexture">NormalTexture / useNormalTexture</a></li>
<li><a href="#shadowalpha">ShadowAlpha</a></li>
</ul>
</ul>
</td>
</tr>
</table> -->
### Cameras
#### PerspectiveCamera
[Documentation has moved here](https://pmndrs.github.io/drei/cameras/perspective-camera)
#### OrthographicCamera
[Documentation has moved here](https://pmndrs.github.io/drei/cameras/orthographic-camera)
#### CubeCamera
[Documentation has moved here](https://pmndrs.github.io/drei/cameras/cube-camera)
### Controls
#### CameraControls
[Documentation has moved here](https://pmndrs.github.io/drei/controls/camera-controls)
#### ScrollControls
[Documentation has moved here](https://pmndrs.github.io/drei/controls/scroll-controls)
#### PresentationControls
[Documentation has moved here](https://pmndrs.github.io/drei/controls/presentation-controls)
#### KeyboardControls
[Documentation has moved here](https://pmndrs.github.io/drei/controls/keyboard-controls)
#### FaceControls
[Documentation has moved here](https://pmndrs.github.io/drei/controls/face-controls)
#### MotionPathControls
[Documentation has moved here](https://pmndrs.github.io/drei/controls/motion-path-controls)
### Gizmos
#### GizmoHelper
[Documentation has moved here](https://pmndrs.github.io/drei/gizmos/gizmo-helper)
#### PivotControls
[Documentation has moved here](https://pmndrs.github.io/drei/gizmos/pivot-controls)
#### DragControls
[Documentation has moved here](https://pmndrs.github.io/drei/gizmos/drag-controls)
#### TransformControls
[Documentation has moved here](https://pmndrs.github.io/drei/gizmos/transform-controls)
#### Grid
[Documentation has moved here](https://pmndrs.github.io/drei/gizmos/grid)
#### Helper / useHelper
[Documentation has moved here](https://pmndrs.github.io/drei/gizmos/helper-use-helper)
### Shapes
#### Plane, Box, Sphere, Circle, Cone, Cylinder, Tube, Torus, TorusKnot, Ring, Tetrahedron, Polyhedron, Icosahedron, Octahedron, Dodecahedron, Extrude, Lathe, Shape
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/mesh)
#### RoundedBox
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/rounded-box)
#### ScreenQuad
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/screen-quad)
#### Line
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/line)
#### QuadraticBezierLine
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/quadratic-bezier-line)
#### CubicBezierLine
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/cubic-bezier-line)
#### CatmullRomLine
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/catmull-rom-line)
#### Facemesh
[Documentation has moved here](https://pmndrs.github.io/drei/shapes/facemesh)
### Abstractions
#### Image
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/image)
#### Text
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/text)
#### Text3D
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/text3d)
#### Effects
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/effects)
#### PositionalAudio
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/positional-audio)
#### Billboard
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/billboard)
#### ScreenSpace
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/screen-space)
#### ScreenSizer
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/screen-sizer)
#### GradientTexture
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/gradient-texture)
#### Edges
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/edges)
#### Outlines
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/outlines)
#### Trail
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/trail)
#### Sampler
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/sampler)
#### ComputedAttribute
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/computed-attribute)
#### Clone
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/clone)
#### useAnimations
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/use-animations)
#### MarchingCubes
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/marching-cubes)
#### Decal
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/decal)
#### Svg
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/svg)
#### AsciiRenderer
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/ascii-renderer)
#### Splat
[Documentation has moved here](https://pmndrs.github.io/drei/abstractions/splat)
### Shaders
#### MeshReflectorMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/mesh-reflector-material)
#### MeshWobbleMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/mesh-wobble-material)
#### MeshDistortMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/mesh-distort-material)
#### MeshRefractionMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/mesh-refraction-material)
#### MeshTransmissionMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/mesh-transmission-material)
#### MeshDiscardMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/mesh-discard-material)
#### PointMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/point-material)
#### SoftShadows
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/soft-shadows)
#### shaderMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/shaders/shader-material)
### Modifiers
#### CurveModifier
[Documentation has moved here](https://pmndrs.github.io/drei/modifiers/curve-modifier)
### Misc
#### useContextBridge
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-context-bridge)
#### Example
[Documentation has moved here](https://pmndrs.github.io/drei/misc/example)
#### Html
[Documentation has moved here](https://pmndrs.github.io/drei/misc/html)
#### CycleRaycast
[Documentation has moved here](https://pmndrs.github.io/drei/misc/cycle-raycast)
#### Select
[Documentation has moved here](https://pmndrs.github.io/drei/misc/select)
#### Sprite Animator
[Documentation has moved here](https://pmndrs.github.io/drei/misc/sprite-animator)
#### Stats
[Documentation has moved here](https://pmndrs.github.io/drei/misc/stats)
#### StatsGl
[Documentation has moved here](https://pmndrs.github.io/drei/misc/stats-gl)
#### Wireframe
[Documentation has moved here](https://pmndrs.github.io/drei/misc/wireframe)
#### useDepthBuffer
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-depth-buffer)
#### Fbo / useFBO
[Documentation has moved here](https://pmndrs.github.io/drei/misc/fbo-use-fbo)
#### useCamera
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-camera)
#### CubeCamera / useCubeCamera
[Documentation has moved here](https://pmndrs.github.io/drei/misc/cube-camera-use-cube-camera)
#### DetectGPU / useDetectGPU
[Documentation has moved here](https://pmndrs.github.io/drei/misc/detect-gpu-use-detect-gpu)
#### useAspect
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-aspect)
#### useCursor
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-cursor)
#### useIntersect
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-intersect)
#### useBoxProjectedEnv
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-box-projected-env)
#### Trail / useTrail
[Documentation has moved here](https://pmndrs.github.io/drei/misc/trail-use-trail)
#### useSurfaceSampler
[Documentation has moved here](https://pmndrs.github.io/drei/misc/use-surface-sampler)
#### FaceLandmarker
[Documentation has moved here](https://pmndrs.github.io/drei/misc/face-landmarker)
### Loading
#### Loader
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/loader)
#### Progress / useProgress
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/progress-use-progress)
#### Gltf / useGLTF
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/gltf-use-gltf)
#### Fbx / useFBX
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/fbx-use-fbx)
#### Texture / useTexture
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/texture-use-texture)
#### Ktx2 / useKTX2
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/ktx2-use-ktx2)
#### CubeTexture / useCubeTexture
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/cube-texture-use-cube-texture)
#### VideoTexture / useVideoTexture
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/video-texture-use-video-texture)
#### TrailTexture / useTrailTexture
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/trail-texture-use-trail-texture)
#### useFont
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/use-font)
#### useSpriteLoader
[Documentation has moved here](https://pmndrs.github.io/drei/loaders/use-sprite-loader)
### Performance
#### Instances
[Documentation has moved here](https://pmndrs.github.io/drei/performances/instances)
#### Merged
[Documentation has moved here](https://pmndrs.github.io/drei/performances/merged)
#### Points
[Documentation has moved here](https://pmndrs.github.io/drei/performances/points)
#### Segments
[Documentation has moved here](https://pmndrs.github.io/drei/performances/segments)
#### Detailed
[Documentation has moved here](https://pmndrs.github.io/drei/performances/detailed)
#### Preload
[Documentation has moved here](https://pmndrs.github.io/drei/performances/preload)
#### BakeShadows
[Documentation has moved here](https://pmndrs.github.io/drei/performances/bake-shadows)
#### meshBounds
[Documentation has moved here](https://pmndrs.github.io/drei/performances/mesh-bounds)
#### AdaptiveDpr
[Documentation has moved here](https://pmndrs.github.io/drei/performances/adaptive-dpr)
#### AdaptiveEvents
[Documentation has moved here](https://pmndrs.github.io/drei/performances/adaptive-events)
#### Bvh
[Documentation has moved here](https://pmndrs.github.io/drei/performances/bvh)
#### PerformanceMonitor
[Documentation has moved here](https://pmndrs.github.io/drei/performances/performance-monitor)
### Portals
#### Hud
[Documentation has moved here](https://pmndrs.github.io/drei/portals/hud)
#### View
[Documentation has moved here](https://pmndrs.github.io/drei/portals/view)
#### RenderTexture
[Documentation has moved here](https://pmndrs.github.io/drei/portals/render-texture)
#### RenderCubeTexture
[Documentation has moved here](https://pmndrs.github.io/drei/portals/render-cube-texture)
#### Fisheye
[Documentation has moved here](https://pmndrs.github.io/drei/portals/fisheye)
#### Mask
[Documentation has moved here](https://pmndrs.github.io/drei/portals/mask)
#### MeshPortalMaterial
[Documentation has moved here](https://pmndrs.github.io/drei/portals/mesh-portal-material)
### Staging
#### Center
[Documentation has moved here](https://pmndrs.github.io/drei/staging/center)
#### Resize
[Documentation has moved here](https://pmndrs.github.io/drei/staging/resize)
#### BBAnchor
[Documentation has moved here](https://pmndrs.github.io/drei/staging/bb-anchor)
#### Bounds
[Documentation has moved here](https://pmndrs.github.io/drei/staging/bounds)
#### CameraShake
[Documentation has moved here](https://pmndrs.github.io/drei/staging/camera-shake)
#### Float
[Documentation has moved here](https://pmndrs.github.io/drei/staging/float)
#### Stage
[Documentation has moved here](https://pmndrs.github.io/drei/staging/stage)
#### Backdrop
[Documentation has moved here](https://pmndrs.github.io/drei/staging/backdrop)
#### Shadow
[Documentation has moved here](https://pmndrs.github.io/drei/staging/shadow)
#### Caustics
[Documentation has moved here](https://pmndrs.github.io/drei/staging/caustics)
#### ContactShadows
[Documentation has moved here](https://pmndrs.github.io/drei/staging/contact-shadows)
#### RandomizedLight
[Documentation has moved here](https://pmndrs.github.io/drei/staging/randomized-light)
#### AccumulativeShadows
[Documentation has moved here](https://pmndrs.github.io/drei/staging/accumulative-shadows)
#### SpotLight
[Documentation has moved here](https://pmndrs.github.io/drei/staging/spot-light)
#### SpotLightShadow
[Documentation has moved here](https://pmndrs.github.io/drei/staging/spot-light-shadow)
#### Environment
[Documentation has moved here](https://pmndrs.github.io/drei/staging/environment)
#### Lightformer
[Documentation has moved here](https://pmndrs.github.io/drei/staging/lightformer)
#### Sky
[Documentation has moved here](https://pmndrs.github.io/drei/staging/sky)
#### Stars
[Documentation has moved here](https://pmndrs.github.io/drei/staging/stars)
#### Sparkles
[Documentation has moved here](https://pmndrs.github.io/drei/staging/sparkles)
#### Cloud
[Documentation has moved here](https://pmndrs.github.io/drei/staging/cloud)
#### useEnvironment
[Documentation has moved here](https://pmndrs.github.io/drei/staging/use-environment)
#### MatcapTexture / useMatcapTexture
[Documentation has moved here](https://pmndrs.github.io/drei/staging/matcap-texture-use-matcap-texture)
#### NormalTexture / useNormalTexture
[Documentation has moved here](https://pmndrs.github.io/drei/staging/normal-texture-use-normal-texture)
#### ShadowAlpha
[Documentation has moved here](https://pmndrs.github.io/drei/staging/shadow-alpha)
</details>
## Dev
### INSTALL
```sh
$ corepack enable
$ yarn install
```
### Test
#### Local
Pre-requisites:
- ```sh
$ npx playwright install
```
To run visual tests locally:
```sh
$ yarn build
$ yarn test
```
To update a snapshot:
```sh
$ PLAYWRIGHT_UPDATE_SNAPSHOTS=1 yarn test
```
#### Docker
> [!IMPORTANT]
> Snapshots are system-dependent, so to run playwright in the same environment as the CI:
```sh
$ docker run --init --rm \
-v $(pwd):/app -w /app \
ghcr.io/pmndrs/playwright:drei \
sh -c "corepack enable && yarn install && yarn build && yarn test"
```
To update a snapshot:
```sh
$ docker run --init --rm \
-v $(pwd):/app -w /app \
-e PLAYWRIGHT_UPDATE_SNAPSHOTS=1 \
ghcr.io/pmndrs/playwright:drei \
sh -c "corepack enable && yarn install && yarn build && yarn test"
```
File diff suppressed because one or more lines are too long
+59
View File
@@ -0,0 +1,59 @@
import * as THREE from 'three';
import * as React from 'react';
import { ReactThreeFiber, ThreeElements } from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type AccumulativeShadowsProps = Omit<ThreeElements['group'], 'ref'> & {
frames?: number;
blend?: number;
limit?: number;
scale?: number;
temporal?: boolean;
opacity?: number;
alphaTest?: number;
color?: string;
colorBlend?: number;
resolution?: number;
toneMapped?: boolean;
};
interface AccumulativeContext {
lights: Map<any, any>;
temporal: boolean;
frames: number;
blend: number;
count: number;
getMesh: () => THREE.Mesh<THREE.PlaneGeometry, SoftShadowMaterialProps & THREE.ShaderMaterial>;
reset: () => void;
update: (frames?: number) => void;
}
interface AccumulativeLightContext {
update: () => void;
}
type SoftShadowMaterialProps = {
map: THREE.Texture;
color?: ReactThreeFiber.Color;
alphaTest?: number;
blend?: number;
};
declare module '@react-three/fiber' {
interface ThreeElements {
softShadowMaterial: ThreeElements['shaderMaterial'] & SoftShadowMaterialProps;
}
}
export declare const accumulativeContext: React.Context<AccumulativeContext>;
export declare const AccumulativeShadows: ForwardRefComponent<AccumulativeShadowsProps, AccumulativeContext>;
export type RandomizedLightProps = Omit<ThreeElements['group'], 'ref'> & {
frames?: number;
position?: [x: number, y: number, z: number];
radius?: number;
amount?: number;
intensity?: number;
ambient?: number;
castShadow?: boolean;
bias?: number;
mapSize?: number;
size?: number;
near?: number;
far?: number;
};
export declare const RandomizedLight: ForwardRefComponent<RandomizedLightProps, AccumulativeLightContext>;
export {};
+310
View File
@@ -0,0 +1,310 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as THREE from 'three';
import * as React from 'react';
import { extend, useThree, useFrame } from '@react-three/fiber';
import { shaderMaterial } from './shaderMaterial.js';
import { DiscardMaterial } from '../materials/DiscardMaterial.js';
import { version } from '../helpers/constants.js';
function isLight(object) {
return object.isLight;
}
function isGeometry(object) {
return !!object.geometry;
}
const accumulativeContext = /* @__PURE__ */React.createContext(null);
const SoftShadowMaterial = /* @__PURE__ */shaderMaterial({
color: /* @__PURE__ */new THREE.Color(),
blend: 2.0,
alphaTest: 0.75,
opacity: 0,
map: null
}, `varying vec2 vUv;
void main() {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);
vUv = uv;
}`, `varying vec2 vUv;
uniform sampler2D map;
uniform vec3 color;
uniform float opacity;
uniform float alphaTest;
uniform float blend;
void main() {
vec4 sampledDiffuseColor = texture2D(map, vUv);
gl_FragColor = vec4(color * sampledDiffuseColor.r * blend, max(0.0, (1.0 - (sampledDiffuseColor.r + sampledDiffuseColor.g + sampledDiffuseColor.b) / alphaTest)) * opacity);
#include <tonemapping_fragment>
#include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}>
}`);
const AccumulativeShadows = /* @__PURE__ */React.forwardRef(({
children,
temporal,
frames = 40,
limit = Infinity,
blend = 20,
scale = 10,
opacity = 1,
alphaTest = 0.75,
color = 'black',
colorBlend = 2,
resolution = 1024,
toneMapped = true,
...props
}, forwardRef) => {
extend({
SoftShadowMaterial
});
const gl = useThree(state => state.gl);
const scene = useThree(state => state.scene);
const camera = useThree(state => state.camera);
const invalidate = useThree(state => state.invalidate);
const gPlane = React.useRef(null);
const gLights = React.useRef(null);
const [plm] = React.useState(() => new ProgressiveLightMap(gl, scene, resolution));
React.useLayoutEffect(() => {
plm.configure(gPlane.current);
}, []);
const api = React.useMemo(() => ({
lights: new Map(),
temporal: !!temporal,
frames: Math.max(2, frames),
blend: Math.max(2, frames === Infinity ? blend : frames),
count: 0,
getMesh: () => gPlane.current,
reset: () => {
// Clear buffers, reset opacities, set frame count to 0
plm.clear();
const material = gPlane.current.material;
material.opacity = 0;
material.alphaTest = 0;
api.count = 0;
},
update: (frames = 1) => {
// Adapt the opacity-blend ratio to the number of frames
const material = gPlane.current.material;
if (!api.temporal) {
material.opacity = opacity;
material.alphaTest = alphaTest;
} else {
material.opacity = Math.min(opacity, material.opacity + opacity / api.blend);
material.alphaTest = Math.min(alphaTest, material.alphaTest + alphaTest / api.blend);
}
// Switch accumulative lights on
gLights.current.visible = true;
// Collect scene lights and meshes
plm.prepare();
// Update the lightmap and the accumulative lights
for (let i = 0; i < frames; i++) {
api.lights.forEach(light => light.update());
plm.update(camera, api.blend);
}
// Switch lights off
gLights.current.visible = false;
// Restore lights and meshes
plm.finish();
}
}), [plm, camera, scene, temporal, frames, blend, opacity, alphaTest]);
React.useLayoutEffect(() => {
// Reset internals, buffers, ...
api.reset();
// Update lightmap
if (!api.temporal && api.frames !== Infinity) api.update(api.blend);
});
// Expose api, allow children to set itself as the main light source
React.useImperativeHandle(forwardRef, () => api, [api]);
useFrame(() => {
if ((api.temporal || api.frames === Infinity) && api.count < api.frames && api.count < limit) {
invalidate();
api.update();
api.count++;
}
});
return /*#__PURE__*/React.createElement("group", props, /*#__PURE__*/React.createElement("group", {
traverse: () => null,
ref: gLights
}, /*#__PURE__*/React.createElement(accumulativeContext.Provider, {
value: api
}, children)), /*#__PURE__*/React.createElement("mesh", {
receiveShadow: true,
ref: gPlane,
scale: scale,
rotation: [-Math.PI / 2, 0, 0]
}, /*#__PURE__*/React.createElement("planeGeometry", null), /*#__PURE__*/React.createElement("softShadowMaterial", {
transparent: true,
depthWrite: false,
toneMapped: toneMapped,
color: color,
blend: colorBlend,
map: plm.progressiveLightMap2.texture
})));
});
const RandomizedLight = /* @__PURE__ */React.forwardRef(({
castShadow = true,
bias = 0.001,
mapSize = 512,
size = 5,
near = 0.5,
far = 500,
frames = 1,
position = [0, 0, 0],
radius = 1,
amount = 8,
intensity = version >= 155 ? Math.PI : 1,
ambient = 0.5,
...props
}, forwardRef) => {
const gLights = React.useRef(null);
const length = new THREE.Vector3(...position).length();
const parent = React.useContext(accumulativeContext);
const update = React.useCallback(() => {
let light;
if (gLights.current) {
for (let l = 0; l < gLights.current.children.length; l++) {
light = gLights.current.children[l];
if (Math.random() > ambient) {
light.position.set(position[0] + THREE.MathUtils.randFloatSpread(radius), position[1] + THREE.MathUtils.randFloatSpread(radius), position[2] + THREE.MathUtils.randFloatSpread(radius));
} else {
let lambda = Math.acos(2 * Math.random() - 1) - Math.PI / 2.0;
let phi = 2 * Math.PI * Math.random();
light.position.set(Math.cos(lambda) * Math.cos(phi) * length, Math.abs(Math.cos(lambda) * Math.sin(phi) * length), Math.sin(lambda) * length);
}
}
}
}, [radius, ambient, length, ...position]);
const api = React.useMemo(() => ({
update
}), [update]);
React.useImperativeHandle(forwardRef, () => api, [api]);
React.useLayoutEffect(() => {
var _parent$lights;
const group = gLights.current;
if (parent) (_parent$lights = parent.lights) == null || _parent$lights.set(group.uuid, api);
return () => {
var _parent$lights2;
return void (parent == null || (_parent$lights2 = parent.lights) == null ? void 0 : _parent$lights2.delete(group.uuid));
};
}, [parent, api]);
return /*#__PURE__*/React.createElement("group", _extends({
ref: gLights
}, props), Array.from({
length: amount
}, (_, index) => /*#__PURE__*/React.createElement("directionalLight", {
key: index,
castShadow: castShadow,
"shadow-bias": bias,
"shadow-mapSize": [mapSize, mapSize],
intensity: intensity / amount
}, /*#__PURE__*/React.createElement("orthographicCamera", {
attach: "shadow-camera",
args: [-size, size, size, -size, near, far]
}))));
});
// Based on "Progressive Light Map Accumulator", by [zalo](https://github.com/zalo/)
class ProgressiveLightMap {
constructor(renderer, scene, res = 1024) {
this.renderer = renderer;
this.res = res;
this.scene = scene;
this.buffer1Active = false;
this.lights = [];
this.meshes = [];
this.object = null;
this.clearColor = new THREE.Color();
this.clearAlpha = 0;
// Create the Progressive LightMap Texture
const textureParams = {
type: THREE.HalfFloatType,
magFilter: THREE.NearestFilter,
minFilter: THREE.NearestFilter
};
this.progressiveLightMap1 = new THREE.WebGLRenderTarget(this.res, this.res, textureParams);
this.progressiveLightMap2 = new THREE.WebGLRenderTarget(this.res, this.res, textureParams);
// Inject some spicy new logic into a standard phong material
this.discardMat = new DiscardMaterial();
this.targetMat = new THREE.MeshLambertMaterial({
fog: false
});
this.previousShadowMap = {
value: this.progressiveLightMap1.texture
};
this.averagingWindow = {
value: 100
};
this.targetMat.onBeforeCompile = shader => {
// Vertex Shader: Set Vertex Positions to the Unwrapped UV Positions
shader.vertexShader = 'varying vec2 vUv;\n' + shader.vertexShader.slice(0, -1) + 'vUv = uv; gl_Position = vec4((uv - 0.5) * 2.0, 1.0, 1.0); }';
// Fragment Shader: Set Pixels to average in the Previous frame's Shadows
const bodyStart = shader.fragmentShader.indexOf('void main() {');
shader.fragmentShader = 'varying vec2 vUv;\n' + shader.fragmentShader.slice(0, bodyStart) + 'uniform sampler2D previousShadowMap;\n uniform float averagingWindow;\n' + shader.fragmentShader.slice(bodyStart - 1, -1) + `\nvec3 texelOld = texture2D(previousShadowMap, vUv).rgb;
gl_FragColor.rgb = mix(texelOld, gl_FragColor.rgb, 1.0/ averagingWindow);
}`;
// Set the Previous Frame's Texture Buffer and Averaging Window
shader.uniforms.previousShadowMap = this.previousShadowMap;
shader.uniforms.averagingWindow = this.averagingWindow;
};
}
clear() {
this.renderer.getClearColor(this.clearColor);
this.clearAlpha = this.renderer.getClearAlpha();
this.renderer.setClearColor('black', 1);
this.renderer.setRenderTarget(this.progressiveLightMap1);
this.renderer.clear();
this.renderer.setRenderTarget(this.progressiveLightMap2);
this.renderer.clear();
this.renderer.setRenderTarget(null);
this.renderer.setClearColor(this.clearColor, this.clearAlpha);
this.lights = [];
this.meshes = [];
this.scene.traverse(object => {
if (isGeometry(object)) {
this.meshes.push({
object,
material: object.material
});
} else if (isLight(object)) {
this.lights.push({
object,
intensity: object.intensity
});
}
});
}
prepare() {
this.lights.forEach(light => light.object.intensity = 0);
this.meshes.forEach(mesh => mesh.object.material = this.discardMat);
}
finish() {
this.lights.forEach(light => light.object.intensity = light.intensity);
this.meshes.forEach(mesh => mesh.object.material = mesh.material);
}
configure(object) {
this.object = object;
}
update(camera, blendWindow = 100) {
if (!this.object) return;
// Set each object's material to the UV Unwrapped Surface Mapping Version
this.averagingWindow.value = blendWindow;
this.object.material = this.targetMat;
// Ping-pong two surface buffers for reading/writing
const activeMap = this.buffer1Active ? this.progressiveLightMap1 : this.progressiveLightMap2;
const inactiveMap = this.buffer1Active ? this.progressiveLightMap2 : this.progressiveLightMap1;
// Render the object's surface maps
const oldBg = this.scene.background;
this.scene.background = null;
this.renderer.setRenderTarget(activeMap);
this.previousShadowMap.value = inactiveMap.texture;
this.buffer1Active = !this.buffer1Active;
this.renderer.render(this.scene, camera);
this.renderer.setRenderTarget(null);
this.scene.background = oldBg;
}
}
export { AccumulativeShadows, RandomizedLight, accumulativeContext };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("@react-three/fiber");function t(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var n=t(e);exports.AdaptiveDpr=function({pixelated:e}){const t=r.useThree((e=>e.gl)),u=r.useThree((e=>e.internal.active)),i=r.useThree((e=>e.performance.current)),a=r.useThree((e=>e.viewport.initialDpr)),c=r.useThree((e=>e.setDpr));return n.useEffect((()=>{const r=t.domElement;return()=>{u&&c(a),e&&r&&(r.style.imageRendering="auto")}}),[]),n.useEffect((()=>{c(i*a),e&&t.domElement&&(t.domElement.style.imageRendering=1===i?"auto":"pixelated")}),[i]),null};
+3
View File
@@ -0,0 +1,3 @@
export declare function AdaptiveDpr({ pixelated }: {
pixelated?: boolean;
}): null;
+28
View File
@@ -0,0 +1,28 @@
import * as React from 'react';
import { useThree } from '@react-three/fiber';
function AdaptiveDpr({
pixelated
}) {
const gl = useThree(state => state.gl);
const active = useThree(state => state.internal.active);
const current = useThree(state => state.performance.current);
const initialDpr = useThree(state => state.viewport.initialDpr);
const setDpr = useThree(state => state.setDpr);
// Restore initial pixelratio on unmount
React.useEffect(() => {
const domElement = gl.domElement;
return () => {
if (active) setDpr(initialDpr);
if (pixelated && domElement) domElement.style.imageRendering = 'auto';
};
}, []);
// Set adaptive pixelratio
React.useEffect(() => {
setDpr(current * initialDpr);
if (pixelated && gl.domElement) gl.domElement.style.imageRendering = current === 1 ? 'auto' : 'pixelated';
}, [current]);
return null;
}
export { AdaptiveDpr };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("@react-three/fiber");function t(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var n=t(e);exports.AdaptiveEvents=function(){const e=r.useThree((e=>e.get)),t=r.useThree((e=>e.setEvents)),u=r.useThree((e=>e.performance.current));return n.useEffect((()=>{const r=e().events.enabled;return()=>t({enabled:r})}),[]),n.useEffect((()=>t({enabled:1===u})),[u]),null};
+1
View File
@@ -0,0 +1 @@
export declare function AdaptiveEvents(): null;
+20
View File
@@ -0,0 +1,20 @@
import * as React from 'react';
import { useThree } from '@react-three/fiber';
function AdaptiveEvents() {
const get = useThree(state => state.get);
const setEvents = useThree(state => state.setEvents);
const current = useThree(state => state.performance.current);
React.useEffect(() => {
const enabled = get().events.enabled;
return () => setEvents({
enabled
});
}, []);
React.useEffect(() => setEvents({
enabled: current === 1
}), [current]);
return null;
}
export { AdaptiveEvents };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("@react-three/fiber"),t=require("react"),n=require("three-stdlib");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var a=s(e),u=o(t);const c=t.forwardRef((({camera:e,makeDefault:s,regress:o,domElement:c,onChange:i,onStart:l,onEnd:f,...d},m)=>{const v=r.useThree((e=>e.invalidate)),b=r.useThree((e=>e.camera)),h=r.useThree((e=>e.gl)),E=r.useThree((e=>e.events)),p=r.useThree((e=>e.set)),g=r.useThree((e=>e.get)),j=r.useThree((e=>e.performance)),O=e||b,T=c||E.connected||h.domElement,L=t.useMemo((()=>new n.ArcballControls(O)),[O]);return r.useFrame((()=>{L.enabled&&L.update()}),-1),t.useEffect((()=>(L.connect(T),()=>{L.dispose()})),[T,o,L,v]),t.useEffect((()=>{const e=e=>{v(),o&&j.regress(),i&&i(e)};return L.addEventListener("change",e),l&&L.addEventListener("start",l),f&&L.addEventListener("end",f),()=>{L.removeEventListener("change",e),l&&L.removeEventListener("start",l),f&&L.removeEventListener("end",f)}}),[i,l,f]),t.useEffect((()=>{if(s){const e=g().controls;return p({controls:L}),()=>p({controls:e})}}),[s,L]),u.createElement("primitive",a.default({ref:m,object:L},d))}));exports.ArcballControls=c;
+15
View File
@@ -0,0 +1,15 @@
import { ReactThreeFiber, ThreeElement } from '@react-three/fiber';
import { ArcballControls as ArcballControlsImpl } from 'three-stdlib';
import type { Event, OrthographicCamera, PerspectiveCamera } from 'three';
import { ForwardRefComponent, Overwrite } from '../helpers/ts-utils';
export type ArcballControlsProps = Omit<Overwrite<ThreeElement<typeof ArcballControlsImpl>, {
target?: ReactThreeFiber.Vector3;
camera?: OrthographicCamera | PerspectiveCamera;
domElement?: HTMLElement;
regress?: boolean;
makeDefault?: boolean;
onChange?: (e?: Event) => void;
onStart?: (e?: Event) => void;
onEnd?: (e?: Event) => void;
}>, 'ref' | 'args'>;
export declare const ArcballControls: ForwardRefComponent<ArcballControlsProps, ArcballControlsImpl>;
+67
View File
@@ -0,0 +1,67 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import { useThree, useFrame } from '@react-three/fiber';
import * as React from 'react';
import { forwardRef, useMemo, useEffect } from 'react';
import { ArcballControls as ArcballControls$1 } from 'three-stdlib';
const ArcballControls = /* @__PURE__ */forwardRef(({
camera,
makeDefault,
regress,
domElement,
onChange,
onStart,
onEnd,
...restProps
}, ref) => {
const invalidate = useThree(state => state.invalidate);
const defaultCamera = useThree(state => state.camera);
const gl = useThree(state => state.gl);
const events = useThree(state => state.events);
const set = useThree(state => state.set);
const get = useThree(state => state.get);
const performance = useThree(state => state.performance);
const explCamera = camera || defaultCamera;
const explDomElement = domElement || events.connected || gl.domElement;
const controls = useMemo(() => new ArcballControls$1(explCamera), [explCamera]);
useFrame(() => {
if (controls.enabled) controls.update();
}, -1);
useEffect(() => {
controls.connect(explDomElement);
return () => void controls.dispose();
}, [explDomElement, regress, controls, invalidate]);
useEffect(() => {
const callback = e => {
invalidate();
if (regress) performance.regress();
if (onChange) onChange(e);
};
controls.addEventListener('change', callback);
if (onStart) controls.addEventListener('start', onStart);
if (onEnd) controls.addEventListener('end', onEnd);
return () => {
controls.removeEventListener('change', callback);
if (onStart) controls.removeEventListener('start', onStart);
if (onEnd) controls.removeEventListener('end', onEnd);
};
}, [onChange, onStart, onEnd]);
useEffect(() => {
if (makeDefault) {
const old = get().controls;
// @ts-ignore https://github.com/three-types/three-ts-types/pull/1398
set({
controls
});
return () => set({
controls: old
});
}
}, [makeDefault, controls]);
return /*#__PURE__*/React.createElement("primitive", _extends({
ref: ref,
object: controls
}, restProps));
});
export { ArcballControls };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("@react-three/fiber"),r=require("three-stdlib");function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var n=o(e);exports.AsciiRenderer=function({renderIndex:e=1,bgColor:o="black",fgColor:l="white",characters:c=" .:-+*=%@#",invert:s=!0,color:i=!1,resolution:u=.15}){const{size:m,gl:d,scene:a,camera:f}=t.useThree(),E=n.useMemo((()=>{const e=new r.AsciiEffect(d,c,{invert:s,color:i,resolution:u});return e.domElement.style.position="absolute",e.domElement.style.top="0px",e.domElement.style.left="0px",e.domElement.style.pointerEvents="none",e}),[c,s,i,u]);return n.useLayoutEffect((()=>{E.domElement.style.color=l,E.domElement.style.backgroundColor=o}),[l,o]),n.useEffect((()=>(d.domElement.style.opacity="0",d.domElement.parentNode.appendChild(E.domElement),()=>{d.domElement.style.opacity="1",d.domElement.parentNode.removeChild(E.domElement)})),[E]),n.useEffect((()=>{E.setSize(m.width,m.height)}),[E,m]),t.useFrame((e=>{E.render(a,f)}),e),n.createElement(n.Fragment,null)};
+11
View File
@@ -0,0 +1,11 @@
import * as React from 'react';
export type AsciiRendererProps = {
renderIndex?: number;
bgColor?: string;
fgColor?: string;
characters?: string;
invert?: boolean;
color?: boolean;
resolution?: number;
};
export declare function AsciiRenderer({ renderIndex, bgColor, fgColor, characters, invert, color, resolution, }: AsciiRendererProps): React.JSX.Element;
+66
View File
@@ -0,0 +1,66 @@
import * as React from 'react';
import { useThree, useFrame } from '@react-three/fiber';
import { AsciiEffect } from 'three-stdlib';
function AsciiRenderer({
renderIndex = 1,
bgColor = 'black',
fgColor = 'white',
characters = ' .:-+*=%@#',
invert = true,
color = false,
resolution = 0.15
}) {
// Reactive state
const {
size,
gl,
scene,
camera
} = useThree();
// Create effect
const effect = React.useMemo(() => {
const effect = new AsciiEffect(gl, characters, {
invert,
color,
resolution
});
effect.domElement.style.position = 'absolute';
effect.domElement.style.top = '0px';
effect.domElement.style.left = '0px';
effect.domElement.style.pointerEvents = 'none';
return effect;
}, [characters, invert, color, resolution]);
// Styling
React.useLayoutEffect(() => {
effect.domElement.style.color = fgColor;
effect.domElement.style.backgroundColor = bgColor;
}, [fgColor, bgColor]);
// Append on mount, remove on unmount
React.useEffect(() => {
gl.domElement.style.opacity = '0';
gl.domElement.parentNode.appendChild(effect.domElement);
return () => {
gl.domElement.style.opacity = '1';
gl.domElement.parentNode.removeChild(effect.domElement);
};
}, [effect]);
// Set size
React.useEffect(() => {
effect.setSize(size.width, size.height);
}, [effect, size]);
// Take over render-loop (that is what the index is for)
useFrame(state => {
effect.render(scene, camera);
}, renderIndex);
// return something to not break type signatures
return /*#__PURE__*/React.createElement(React.Fragment, null);
}
export { AsciiRenderer };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("three"),n=require("@react-three/fiber");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function c(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var a=u(e),o=c(r),i=c(t);const s=new i.Box3,f=new i.Vector3;exports.BBAnchor=({anchor:e,...r})=>{const t=o.useRef(null),u=o.useRef(null);return o.useEffect((()=>{var e;null!=(e=t.current)&&null!=(e=e.parent)&&e.parent&&(u.current=t.current.parent,t.current.parent.parent.add(t.current))}),[]),n.useFrame((()=>{u.current&&(s.setFromObject(u.current),s.getSize(f),t.current.position.set(u.current.position.x+f.x*(Array.isArray(e)?e[0]:e.x)/2,u.current.position.y+f.y*(Array.isArray(e)?e[1]:e.y)/2,u.current.position.z+f.z*(Array.isArray(e)?e[2]:e.z)/2))})),o.createElement("group",a.default({ref:t},r))};
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
import * as THREE from 'three';
import { ThreeElements } from '@react-three/fiber';
export type BBAnchorProps = ThreeElements['group'] & {
anchor: THREE.Vector3 | [number, number, number];
};
export declare const BBAnchor: ({ anchor, ...props }: BBAnchorProps) => React.JSX.Element;
+37
View File
@@ -0,0 +1,37 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import * as THREE from 'three';
import { useFrame } from '@react-three/fiber';
const boundingBox = /* @__PURE__ */new THREE.Box3();
const boundingBoxSize = /* @__PURE__ */new THREE.Vector3();
const BBAnchor = ({
anchor,
...props
}) => {
const ref = React.useRef(null);
const parentRef = React.useRef(null);
// Reattach group created by this component to the parent's parent,
// so it becomes a sibling of its initial parent.
// We do that so the children have no impact on a bounding box of a parent.
React.useEffect(() => {
var _ref$current;
if ((_ref$current = ref.current) != null && (_ref$current = _ref$current.parent) != null && _ref$current.parent) {
parentRef.current = ref.current.parent;
ref.current.parent.parent.add(ref.current);
}
}, []);
useFrame(() => {
if (parentRef.current) {
boundingBox.setFromObject(parentRef.current);
boundingBox.getSize(boundingBoxSize);
ref.current.position.set(parentRef.current.position.x + boundingBoxSize.x * (Array.isArray(anchor) ? anchor[0] : anchor.x) / 2, parentRef.current.position.y + boundingBoxSize.y * (Array.isArray(anchor) ? anchor[1] : anchor.y) / 2, parentRef.current.position.z + boundingBoxSize.z * (Array.isArray(anchor) ? anchor[2] : anchor.z) / 2);
}
});
return /*#__PURE__*/React.createElement("group", _extends({
ref: ref
}, props));
};
export { BBAnchor };
+1
View File
@@ -0,0 +1 @@
"use strict";function e(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("react"));const r=e=>0===e?0:Math.pow(2,10*e-10);exports.Backdrop=function({children:e,floor:o=.25,segments:n=20,receiveShadow:c,...a}){const u=t.useRef(null);return t.useLayoutEffect((()=>{let e=0;const t=n/n/2,c=u.current.attributes.position;for(let a=0;a<n+1;a++)for(let u=0;u<n+1;u++)c.setXYZ(e++,a/n-t+(0===a?-o:0),u/n-t,r(a/n));c.needsUpdate=!0,u.current.computeVertexNormals()}),[n,o]),t.createElement("group",a,t.createElement("mesh",{receiveShadow:c,rotation:[-Math.PI/2,0,Math.PI/2]},t.createElement("planeGeometry",{ref:u,args:[1,1,n,n]}),e))};
+15
View File
@@ -0,0 +1,15 @@
import { ThreeElements } from '@react-three/fiber';
import * as React from 'react';
export type BackdropProps = ThreeElements['group'] & {
floor?: number;
segments?: number;
receiveShadow?: boolean;
children?: React.ReactNode;
};
export declare function Backdrop({ children, floor, segments, receiveShadow, ...props }: {
[x: string]: any;
children: any;
floor?: number | undefined;
segments?: number | undefined;
receiveShadow: any;
}): React.JSX.Element;
+33
View File
@@ -0,0 +1,33 @@
import * as React from 'react';
const easeInExpo = x => x === 0 ? 0 : Math.pow(2, 10 * x - 10);
function Backdrop({
children,
floor = 0.25,
segments = 20,
receiveShadow,
...props
}) {
const ref = React.useRef(null);
React.useLayoutEffect(() => {
let i = 0;
const offset = segments / segments / 2;
const position = ref.current.attributes.position;
for (let x = 0; x < segments + 1; x++) {
for (let y = 0; y < segments + 1; y++) {
position.setXYZ(i++, x / segments - offset + (x === 0 ? -floor : 0), y / segments - offset, easeInExpo(x / segments));
}
}
position.needsUpdate = true;
ref.current.computeVertexNormals();
}, [segments, floor]);
return /*#__PURE__*/React.createElement("group", props, /*#__PURE__*/React.createElement("mesh", {
receiveShadow: receiveShadow,
rotation: [-Math.PI / 2, 0, Math.PI / 2]
}, /*#__PURE__*/React.createElement("planeGeometry", {
ref: ref,
args: [1, 1, segments, segments]
}), children));
}
export { Backdrop };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),a=require("@react-three/fiber");exports.BakeShadows=function(){const t=a.useThree((e=>e.gl));return e.useEffect((()=>(t.shadowMap.autoUpdate=!1,t.shadowMap.needsUpdate=!0,()=>{t.shadowMap.autoUpdate=t.shadowMap.needsUpdate=!0})),[t.shadowMap]),null};
+1
View File
@@ -0,0 +1 @@
export declare function BakeShadows(): null;
+16
View File
@@ -0,0 +1,16 @@
import { useEffect } from 'react';
import { useThree } from '@react-three/fiber';
function BakeShadows() {
const gl = useThree(state => state.gl);
useEffect(() => {
gl.shadowMap.autoUpdate = false;
gl.shadowMap.needsUpdate = true;
return () => {
gl.shadowMap.autoUpdate = gl.shadowMap.needsUpdate = true;
};
}, [gl.shadowMap]);
return null;
}
export { BakeShadows };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("three"),n=require("@react-three/fiber");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var c=u(e),a=o(r);const i=a.forwardRef((function({children:e,follow:r=!0,lockX:u=!1,lockY:o=!1,lockZ:i=!1,...l},f){const d=a.useRef(null),s=a.useRef(null),p=new t.Quaternion;return n.useFrame((({camera:e})=>{if(!r||!s.current)return;const t=d.current.rotation.clone();s.current.updateMatrix(),s.current.updateWorldMatrix(!1,!1),s.current.getWorldQuaternion(p),e.getWorldQuaternion(d.current.quaternion).premultiply(p.invert()),u&&(d.current.rotation.x=t.x),o&&(d.current.rotation.y=t.y),i&&(d.current.rotation.z=t.z)})),a.useImperativeHandle(f,(()=>s.current),[]),a.createElement("group",c.default({ref:s},l),a.createElement("group",{ref:d},e))}));exports.Billboard=i;
+10
View File
@@ -0,0 +1,10 @@
import { Group } from 'three';
import { ThreeElements } from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type BillboardProps = Omit<ThreeElements['group'], 'ref'> & {
follow?: boolean;
lockX?: boolean;
lockY?: boolean;
lockZ?: boolean;
};
export declare const Billboard: ForwardRefComponent<BillboardProps, Group>;
+53
View File
@@ -0,0 +1,53 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { Quaternion } from 'three';
import { useFrame } from '@react-three/fiber';
/**
* Wraps children in a billboarded group. Sample usage:
*
* ```js
* <Billboard>
* <Text>hi</Text>
* </Billboard>
* ```
*/
const Billboard = /* @__PURE__ */React.forwardRef(function Billboard({
children,
follow = true,
lockX = false,
lockY = false,
lockZ = false,
...props
}, fref) {
const inner = React.useRef(null);
const localRef = React.useRef(null);
const q = new Quaternion();
useFrame(({
camera
}) => {
if (!follow || !localRef.current) return;
// save previous rotation in case we're locking an axis
const prevRotation = inner.current.rotation.clone();
// always face the camera
localRef.current.updateMatrix();
localRef.current.updateWorldMatrix(false, false);
localRef.current.getWorldQuaternion(q);
camera.getWorldQuaternion(inner.current.quaternion).premultiply(q.invert());
// readjust any axis that is locked
if (lockX) inner.current.rotation.x = prevRotation.x;
if (lockY) inner.current.rotation.y = prevRotation.y;
if (lockZ) inner.current.rotation.z = prevRotation.z;
});
React.useImperativeHandle(fref, () => localRef.current, []);
return /*#__PURE__*/React.createElement("group", _extends({
ref: localRef
}, props), /*#__PURE__*/React.createElement("group", {
ref: inner
}, children));
});
export { Billboard };
File diff suppressed because one or more lines are too long
+36
View File
@@ -0,0 +1,36 @@
import * as React from 'react';
import * as THREE from 'three';
import { ThreeElements } from '@react-three/fiber';
export type SizeProps = {
box: THREE.Box3;
size: THREE.Vector3;
center: THREE.Vector3;
distance: number;
};
export type BoundsApi = {
getSize: () => SizeProps;
refresh(object?: THREE.Object3D | THREE.Box3): BoundsApi;
reset(): BoundsApi;
moveTo(position: THREE.Vector3 | [number, number, number]): BoundsApi;
lookAt({ target, up, }: {
target?: THREE.Vector3 | [number, number, number];
up?: THREE.Vector3 | [number, number, number];
}): BoundsApi;
to({ position, target }: {
position: [number, number, number];
target: [number, number, number];
}): BoundsApi;
fit(): BoundsApi;
clip(): BoundsApi;
};
export type BoundsProps = Omit<ThreeElements['group'], 'ref'> & {
maxDuration?: number;
margin?: number;
observe?: boolean;
fit?: boolean;
clip?: boolean;
interpolateFunc?: (t: number) => number;
onFit?: (data: SizeProps) => void;
};
export declare function Bounds({ children, maxDuration, margin, observe, fit, clip, interpolateFunc, onFit, }: BoundsProps): React.JSX.Element;
export declare function useBounds(): BoundsApi;
+254
View File
@@ -0,0 +1,254 @@
import * as React from 'react';
import * as THREE from 'three';
import { useThree, useFrame } from '@react-three/fiber';
var AnimationState = /*#__PURE__*/function (AnimationState) {
AnimationState[AnimationState["NONE"] = 0] = "NONE";
AnimationState[AnimationState["START"] = 1] = "START";
AnimationState[AnimationState["ACTIVE"] = 2] = "ACTIVE";
return AnimationState;
}(AnimationState || {});
const isOrthographic = def => def && def.isOrthographicCamera;
const isBox3 = def => def && def.isBox3;
const interpolateFuncDefault = t => {
// Imitates the previously used THREE.MathUtils.damp
return 1 - Math.exp(-5 * t) + 0.007 * t;
};
const context = /*#__PURE__*/React.createContext(null);
function Bounds({
children,
maxDuration = 1.0,
margin = 1.2,
observe,
fit,
clip,
interpolateFunc = interpolateFuncDefault,
onFit
}) {
const ref = React.useRef(null);
const {
camera,
size,
invalidate
} = useThree();
const controls = useThree(state => state.controls);
const onFitRef = React.useRef(onFit);
onFitRef.current = onFit;
const origin = React.useRef({
camPos: new THREE.Vector3(),
camRot: new THREE.Quaternion(),
camZoom: 1
});
const goal = React.useRef({
camPos: undefined,
camRot: undefined,
camZoom: undefined,
camUp: undefined,
target: undefined
});
const animationState = React.useRef(AnimationState.NONE);
const t = React.useRef(0); // represent animation state from 0 to 1
const [box] = React.useState(() => new THREE.Box3());
const api = React.useMemo(() => {
function getSize() {
const boxSize = box.getSize(new THREE.Vector3());
const center = box.getCenter(new THREE.Vector3());
const maxSize = Math.max(boxSize.x, boxSize.y, boxSize.z);
const fitHeightDistance = isOrthographic(camera) ? maxSize * 4 : maxSize / (2 * Math.atan(Math.PI * camera.fov / 360));
const fitWidthDistance = isOrthographic(camera) ? maxSize * 4 : fitHeightDistance / camera.aspect;
const distance = margin * Math.max(fitHeightDistance, fitWidthDistance);
return {
box,
size: boxSize,
center,
distance
};
}
return {
getSize,
refresh(object) {
if (isBox3(object)) box.copy(object);else {
const target = object || ref.current;
if (!target) return this;
target.updateWorldMatrix(true, true);
box.setFromObject(target);
}
if (box.isEmpty()) {
const max = camera.position.length() || 10;
box.setFromCenterAndSize(new THREE.Vector3(), new THREE.Vector3(max, max, max));
}
origin.current.camPos.copy(camera.position);
origin.current.camRot.copy(camera.quaternion);
isOrthographic(camera) && (origin.current.camZoom = camera.zoom);
goal.current.camPos = undefined;
goal.current.camRot = undefined;
goal.current.camZoom = undefined;
goal.current.camUp = undefined;
goal.current.target = undefined;
return this;
},
reset() {
const {
center,
distance
} = getSize();
const direction = camera.position.clone().sub(center).normalize();
goal.current.camPos = center.clone().addScaledVector(direction, distance);
goal.current.target = center.clone();
const mCamRot = new THREE.Matrix4().lookAt(goal.current.camPos, goal.current.target, camera.up);
goal.current.camRot = new THREE.Quaternion().setFromRotationMatrix(mCamRot);
animationState.current = AnimationState.START;
t.current = 0;
return this;
},
moveTo(position) {
goal.current.camPos = Array.isArray(position) ? new THREE.Vector3(...position) : position.clone();
animationState.current = AnimationState.START;
t.current = 0;
return this;
},
lookAt({
target,
up
}) {
goal.current.target = Array.isArray(target) ? new THREE.Vector3(...target) : target.clone();
if (up) {
goal.current.camUp = Array.isArray(up) ? new THREE.Vector3(...up) : up.clone();
} else {
goal.current.camUp = camera.up.clone();
}
const mCamRot = new THREE.Matrix4().lookAt(goal.current.camPos || camera.position, goal.current.target, goal.current.camUp);
goal.current.camRot = new THREE.Quaternion().setFromRotationMatrix(mCamRot);
animationState.current = AnimationState.START;
t.current = 0;
return this;
},
/**
* @deprecated Use moveTo and lookAt instead
*/
to({
position,
target
}) {
return this.moveTo(position).lookAt({
target
});
},
fit() {
if (!isOrthographic(camera)) {
// For non-orthographic cameras, fit should behave exactly like reset
return this.reset();
}
// For orthographic cameras, fit should only modify the zoom value
let maxHeight = 0,
maxWidth = 0;
const vertices = [new THREE.Vector3(box.min.x, box.min.y, box.min.z), new THREE.Vector3(box.min.x, box.max.y, box.min.z), new THREE.Vector3(box.min.x, box.min.y, box.max.z), new THREE.Vector3(box.min.x, box.max.y, box.max.z), new THREE.Vector3(box.max.x, box.max.y, box.max.z), new THREE.Vector3(box.max.x, box.max.y, box.min.z), new THREE.Vector3(box.max.x, box.min.y, box.max.z), new THREE.Vector3(box.max.x, box.min.y, box.min.z)];
// Transform the center and each corner to camera space
const pos = goal.current.camPos || camera.position;
const target = goal.current.target || (controls == null ? void 0 : controls.target);
const up = goal.current.camUp || camera.up;
const mCamWInv = target ? new THREE.Matrix4().lookAt(pos, target, up).setPosition(pos).invert() : camera.matrixWorldInverse;
for (const v of vertices) {
v.applyMatrix4(mCamWInv);
maxHeight = Math.max(maxHeight, Math.abs(v.y));
maxWidth = Math.max(maxWidth, Math.abs(v.x));
}
maxHeight *= 2;
maxWidth *= 2;
const zoomForHeight = (camera.top - camera.bottom) / maxHeight;
const zoomForWidth = (camera.right - camera.left) / maxWidth;
goal.current.camZoom = Math.min(zoomForHeight, zoomForWidth) / margin;
animationState.current = AnimationState.START;
t.current = 0;
onFitRef.current && onFitRef.current(this.getSize());
return this;
},
clip() {
const {
distance
} = getSize();
camera.near = distance / 100;
camera.far = distance * 100;
camera.updateProjectionMatrix();
if (controls) {
controls.maxDistance = distance * 10;
controls.update();
}
invalidate();
return this;
}
};
}, [box, camera, controls, margin, invalidate]);
React.useLayoutEffect(() => {
if (controls) {
// Try to prevent drag hijacking
const callback = () => {
if (controls && goal.current.target && animationState.current !== AnimationState.NONE) {
const front = new THREE.Vector3().setFromMatrixColumn(camera.matrix, 2);
const d0 = origin.current.camPos.distanceTo(controls.target);
const d1 = (goal.current.camPos || origin.current.camPos).distanceTo(goal.current.target);
const d = (1 - t.current) * d0 + t.current * d1;
controls.target.copy(camera.position).addScaledVector(front, -d);
controls.update();
}
animationState.current = AnimationState.NONE;
};
controls.addEventListener('start', callback);
return () => controls.removeEventListener('start', callback);
}
}, [controls]);
// Scale pointer on window resize
const count = React.useRef(0);
React.useLayoutEffect(() => {
if (observe || count.current++ === 0) {
api.refresh();
if (fit) api.reset().fit();
if (clip) api.clip();
}
}, [size, clip, fit, observe, camera, controls]);
useFrame((state, delta) => {
// This [additional animation step START] is needed to guarantee that delta used in animation isn't absurdly high (2-3 seconds) which is actually possible if rendering happens on demand...
if (animationState.current === AnimationState.START) {
animationState.current = AnimationState.ACTIVE;
invalidate();
} else if (animationState.current === AnimationState.ACTIVE) {
t.current += delta / maxDuration;
if (t.current >= 1) {
goal.current.camPos && camera.position.copy(goal.current.camPos);
goal.current.camRot && camera.quaternion.copy(goal.current.camRot);
goal.current.camUp && camera.up.copy(goal.current.camUp);
goal.current.camZoom && isOrthographic(camera) && (camera.zoom = goal.current.camZoom);
camera.updateMatrixWorld();
camera.updateProjectionMatrix();
if (controls && goal.current.target) {
controls.target.copy(goal.current.target);
controls.update();
}
animationState.current = AnimationState.NONE;
} else {
const k = interpolateFunc(t.current);
goal.current.camPos && camera.position.lerpVectors(origin.current.camPos, goal.current.camPos, k);
goal.current.camRot && camera.quaternion.slerpQuaternions(origin.current.camRot, goal.current.camRot, k);
goal.current.camUp && camera.up.set(0, 1, 0).applyQuaternion(camera.quaternion);
goal.current.camZoom && isOrthographic(camera) && (camera.zoom = (1 - k) * origin.current.camZoom + k * goal.current.camZoom);
camera.updateMatrixWorld();
camera.updateProjectionMatrix();
}
invalidate();
}
});
return /*#__PURE__*/React.createElement("group", {
ref: ref
}, /*#__PURE__*/React.createElement(context.Provider, {
value: api
}, children));
}
function useBounds() {
return React.useContext(context);
}
export { Bounds, useBounds };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("@react-three/fiber"),t=require("react"),s=require("three"),o=require("three-mesh-bvh");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var s=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,s.get?s:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var a=n(e),c=u(t);const i=e=>e.isMesh;const d=c.forwardRef((({enabled:e=!0,firstHitOnly:t=!1,children:n,strategy:u=o.SAH,verbose:d=!1,setBoundingBox:f=!0,maxDepth:p=40,maxLeafTris:y=10,indirect:l=!1,...m},B)=>{const b=c.useRef(null),T=r.useThree((e=>e.raycaster));return c.useImperativeHandle(B,(()=>b.current),[]),c.useEffect((()=>{if(e){const e={strategy:u,verbose:d,setBoundingBox:f,maxDepth:p,maxLeafTris:y,indirect:l},r=b.current;return T.firstHitOnly=t,r.traverse((r=>{i(r)&&!r.geometry.boundsTree&&r.raycast===s.Mesh.prototype.raycast&&(r.raycast=o.acceleratedRaycast,r.geometry.computeBoundsTree=o.computeBoundsTree,r.geometry.disposeBoundsTree=o.disposeBoundsTree,r.geometry.computeBoundsTree(e))})),()=>{delete T.firstHitOnly,r.traverse((e=>{i(e)&&e.geometry.boundsTree&&(e.geometry.disposeBoundsTree(),e.raycast=s.Mesh.prototype.raycast)}))}}}),[]),c.createElement("group",a.default({ref:b},m),n)}));exports.Bvh=d,exports.useBVH=function(e,r){r={strategy:o.SAH,verbose:!1,setBoundingBox:!0,maxDepth:40,maxLeafTris:10,indirect:!1,...r},c.useEffect((()=>{if(e.current){e.current.raycast=o.acceleratedRaycast;const t=e.current.geometry;return t.computeBoundsTree=o.computeBoundsTree,t.disposeBoundsTree=o.disposeBoundsTree,t.computeBoundsTree(r),()=>{t.boundsTree&&t.disposeBoundsTree()}}}),[e,JSON.stringify(r)])};
+19
View File
@@ -0,0 +1,19 @@
import { ThreeElements } from '@react-three/fiber';
import * as React from 'react';
import { Mesh, Group } from 'three';
import { SplitStrategy } from 'three-mesh-bvh';
import { ForwardRefComponent } from '../helpers/ts-utils';
export interface BVHOptions {
strategy?: SplitStrategy;
verbose?: boolean;
setBoundingBox?: boolean;
maxDepth?: number;
maxLeafTris?: number;
indirect?: boolean;
}
export type BvhProps = BVHOptions & ThreeElements['group'] & {
enabled?: boolean;
firstHitOnly?: boolean;
};
export declare function useBVH(mesh: React.RefObject<Mesh | undefined>, options?: BVHOptions): void;
export declare const Bvh: ForwardRefComponent<BvhProps, Group>;
+92
View File
@@ -0,0 +1,92 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import { useThree } from '@react-three/fiber';
import * as React from 'react';
import { Mesh } from 'three';
import { SAH, acceleratedRaycast, computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh';
const isMesh = child => child.isMesh;
/**
* @deprecated Use the Bvh component instead
*/
function useBVH(mesh, options) {
options = {
strategy: SAH,
verbose: false,
setBoundingBox: true,
maxDepth: 40,
maxLeafTris: 10,
indirect: false,
...options
};
React.useEffect(() => {
if (mesh.current) {
mesh.current.raycast = acceleratedRaycast;
const geometry = mesh.current.geometry;
geometry.computeBoundsTree = computeBoundsTree;
geometry.disposeBoundsTree = disposeBoundsTree;
geometry.computeBoundsTree(options);
return () => {
if (geometry.boundsTree) {
geometry.disposeBoundsTree();
}
};
}
}, [mesh, JSON.stringify(options)]);
}
const Bvh = /* @__PURE__ */React.forwardRef(({
enabled = true,
firstHitOnly = false,
children,
strategy = SAH,
verbose = false,
setBoundingBox = true,
maxDepth = 40,
maxLeafTris = 10,
indirect = false,
...props
}, fref) => {
const ref = React.useRef(null);
const raycaster = useThree(state => state.raycaster);
React.useImperativeHandle(fref, () => ref.current, []);
React.useEffect(() => {
if (enabled) {
const options = {
strategy,
verbose,
setBoundingBox,
maxDepth,
maxLeafTris,
indirect
};
const group = ref.current;
// This can only safely work if the component is used once, but there is no alternative.
// Hijacking the raycast method to do it for individual meshes is not an option as it would
// cost too much memory ...
raycaster.firstHitOnly = firstHitOnly;
group.traverse(child => {
// Only include meshes that do not yet have a boundsTree and whose raycast is standard issue
if (isMesh(child) && !child.geometry.boundsTree && child.raycast === Mesh.prototype.raycast) {
child.raycast = acceleratedRaycast;
child.geometry.computeBoundsTree = computeBoundsTree;
child.geometry.disposeBoundsTree = disposeBoundsTree;
child.geometry.computeBoundsTree(options);
}
});
return () => {
delete raycaster.firstHitOnly;
group.traverse(child => {
if (isMesh(child) && child.geometry.boundsTree) {
child.geometry.disposeBoundsTree();
child.raycast = Mesh.prototype.raycast;
}
});
};
}
}, []);
return /*#__PURE__*/React.createElement("group", _extends({
ref: ref
}, props), children);
});
export { Bvh, useBVH };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react"),n=require("@react-three/fiber"),o=require("camera-controls");function l(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function a(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var s=l(e),u=a(r),c=l(o);const i=r.forwardRef(((e,o)=>{const{impl:l,camera:a,domElement:i,makeDefault:d,onControlStart:f,onControl:m,onControlEnd:v,onTransitionStart:p,onUpdate:E,onWake:h,onRest:L,onSleep:b,onStart:C,onEnd:T,onChange:g,regress:j,...x}=e,y=null!=l?l:c.default;r.useMemo((()=>{const e={Box3:t.Box3,MathUtils:{clamp:t.MathUtils.clamp},Matrix4:t.Matrix4,Quaternion:t.Quaternion,Raycaster:t.Raycaster,Sphere:t.Sphere,Spherical:t.Spherical,Vector2:t.Vector2,Vector3:t.Vector3,Vector4:t.Vector4};y.install({THREE:e}),n.extend({CameraControlsImpl:y})}),[y]);const M=n.useThree((e=>e.camera)),O=n.useThree((e=>e.gl)),S=n.useThree((e=>e.invalidate)),V=n.useThree((e=>e.events)),k=n.useThree((e=>e.setEvents)),q=n.useThree((e=>e.set)),w=n.useThree((e=>e.get)),R=n.useThree((e=>e.performance)),P=a||M,_=i||V.connected||O.domElement,U=r.useMemo((()=>new y(P)),[y,P]);return n.useFrame(((e,t)=>{U.update(t)}),-1),r.useEffect((()=>(U.connect(_),()=>{U.disconnect()})),[_,U]),r.useEffect((()=>{function e(){S(),j&&R.regress()}const t=t=>{e(),null==f||f(t),null==C||C(t)},r=t=>{e(),null==m||m(t),null==g||g(t)},n=e=>{null==v||v(e),null==T||T(e)},o=t=>{e(),null==p||p(t),null==g||g(t)},l=t=>{e(),null==E||E(t),null==g||g(t)},a=t=>{e(),null==h||h(t),null==g||g(t)},s=e=>{null==L||L(e)},u=e=>{null==b||b(e)};return U.addEventListener("controlstart",t),U.addEventListener("control",r),U.addEventListener("controlend",n),U.addEventListener("transitionstart",o),U.addEventListener("update",l),U.addEventListener("wake",a),U.addEventListener("rest",s),U.addEventListener("sleep",u),()=>{U.removeEventListener("controlstart",t),U.removeEventListener("control",r),U.removeEventListener("controlend",n),U.removeEventListener("transitionstart",o),U.removeEventListener("update",l),U.removeEventListener("wake",a),U.removeEventListener("rest",s),U.removeEventListener("sleep",u)}}),[U,S,k,j,R,f,m,v,p,E,h,L,b,g,C,T]),r.useEffect((()=>{if(d){const e=w().controls;return q({controls:U}),()=>q({controls:e})}}),[d,U]),u.createElement("primitive",s.default({ref:o,object:U},x))}));Object.defineProperty(exports,"CameraControlsImpl",{enumerable:!0,get:function(){return c.default}}),exports.CameraControls=i;
+48
View File
@@ -0,0 +1,48 @@
import { EventDispatcher, OrthographicCamera, PerspectiveCamera } from 'three';
import { ThreeElement } from '@react-three/fiber';
import CameraControlsImpl from 'camera-controls';
import { ForwardRefComponent, Overwrite } from '../helpers/ts-utils';
export type CameraControlsProps = Omit<Overwrite<ThreeElement<typeof CameraControlsImpl>, {
impl?: typeof CameraControlsImpl;
camera?: PerspectiveCamera | OrthographicCamera;
domElement?: HTMLElement;
makeDefault?: boolean;
onControlStart?: (e?: {
type: 'controlstart';
}) => void;
onControl?: (e?: {
type: 'control';
}) => void;
onControlEnd?: (e?: {
type: 'controlend';
}) => void;
onTransitionStart?: (e?: {
type: 'transitionstart';
}) => void;
onUpdate?: (e?: {
type: 'update';
}) => void;
onWake?: (e?: {
type: 'wake';
}) => void;
onRest?: (e?: {
type: 'rest';
}) => void;
onSleep?: (e?: {
type: 'sleep';
}) => void;
onStart?: (e?: {
type: 'controlstart';
}) => void;
onEnd?: (e?: {
type: 'controlend';
}) => void;
onChange?: (e?: {
type: string;
}) => void;
events?: boolean;
regress?: boolean;
}>, 'ref' | 'args' | keyof EventDispatcher>;
export declare const CameraControls: ForwardRefComponent<CameraControlsProps, CameraControlsImpl>;
export type CameraControls = CameraControlsImpl;
export { CameraControlsImpl };
+151
View File
@@ -0,0 +1,151 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import { Box3, MathUtils, Matrix4, Quaternion, Raycaster, Sphere, Spherical, Vector2, Vector3, Vector4 } from 'three';
import * as React from 'react';
import { forwardRef, useMemo, useEffect } from 'react';
import { extend, useThree, useFrame } from '@react-three/fiber';
import CameraControlsImpl from 'camera-controls';
export { default as CameraControlsImpl } from 'camera-controls';
const CameraControls = /* @__PURE__ */forwardRef((props, ref) => {
const {
impl: SubclassImpl,
camera,
domElement,
makeDefault,
onControlStart,
onControl,
onControlEnd,
onTransitionStart,
onUpdate,
onWake,
onRest,
onSleep,
onStart,
onEnd,
onChange,
regress,
...restProps
} = props;
const Impl = SubclassImpl !== null && SubclassImpl !== void 0 ? SubclassImpl : CameraControlsImpl;
// useMemo is used here instead of useEffect, otherwise the useMemo below runs first and throws
useMemo(() => {
// to allow for tree shaking, we only import the subset of THREE that is used by camera-controls
// see https://github.com/yomotsu/camera-controls#important
const subsetOfTHREE = {
Box3,
MathUtils: {
clamp: MathUtils.clamp
},
Matrix4,
Quaternion,
Raycaster,
Sphere,
Spherical,
Vector2,
Vector3,
Vector4
};
Impl.install({
THREE: subsetOfTHREE
});
extend({
CameraControlsImpl: Impl
});
}, [Impl]);
const defaultCamera = useThree(state => state.camera);
const gl = useThree(state => state.gl);
const invalidate = useThree(state => state.invalidate);
const events = useThree(state => state.events);
const setEvents = useThree(state => state.setEvents);
const set = useThree(state => state.set);
const get = useThree(state => state.get);
const performance = useThree(state => state.performance);
const explCamera = camera || defaultCamera;
const explDomElement = domElement || events.connected || gl.domElement;
const controls = useMemo(() => new Impl(explCamera), [Impl, explCamera]);
useFrame((state, delta) => {
controls.update(delta);
}, -1);
useEffect(() => {
controls.connect(explDomElement);
return () => void controls.disconnect();
}, [explDomElement, controls]);
useEffect(() => {
function invalidateAndRegress() {
invalidate();
if (regress) performance.regress();
}
const handleControlStart = e => {
invalidateAndRegress();
onControlStart == null || onControlStart(e);
onStart == null || onStart(e); // backwards compatibility
};
const handleControl = e => {
invalidateAndRegress();
onControl == null || onControl(e);
onChange == null || onChange(e); // backwards compatibility
};
const handleControlEnd = e => {
onControlEnd == null || onControlEnd(e);
onEnd == null || onEnd(e); // backwards compatibility
};
const handleTransitionStart = e => {
invalidateAndRegress();
onTransitionStart == null || onTransitionStart(e);
onChange == null || onChange(e); // backwards compatibility
};
const handleUpdate = e => {
invalidateAndRegress();
onUpdate == null || onUpdate(e);
onChange == null || onChange(e); // backwards compatibility
};
const handleWake = e => {
invalidateAndRegress();
onWake == null || onWake(e);
onChange == null || onChange(e); // backwards compatibility
};
const handleRest = e => {
onRest == null || onRest(e);
};
const handleSleep = e => {
onSleep == null || onSleep(e);
};
controls.addEventListener('controlstart', handleControlStart);
controls.addEventListener('control', handleControl);
controls.addEventListener('controlend', handleControlEnd);
controls.addEventListener('transitionstart', handleTransitionStart);
controls.addEventListener('update', handleUpdate);
controls.addEventListener('wake', handleWake);
controls.addEventListener('rest', handleRest);
controls.addEventListener('sleep', handleSleep);
return () => {
controls.removeEventListener('controlstart', handleControlStart);
controls.removeEventListener('control', handleControl);
controls.removeEventListener('controlend', handleControlEnd);
controls.removeEventListener('transitionstart', handleTransitionStart);
controls.removeEventListener('update', handleUpdate);
controls.removeEventListener('wake', handleWake);
controls.removeEventListener('rest', handleRest);
controls.removeEventListener('sleep', handleSleep);
};
}, [controls, invalidate, setEvents, regress, performance, onControlStart, onControl, onControlEnd, onTransitionStart, onUpdate, onWake, onRest, onSleep, onChange, onStart, onEnd]);
useEffect(() => {
if (makeDefault) {
const old = get().controls;
set({
controls: controls
});
return () => set({
controls: old
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [makeDefault, controls]);
return /*#__PURE__*/React.createElement("primitive", _extends({
ref: ref,
object: controls
}, restProps));
});
export { CameraControls };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("@react-three/fiber"),t=require("three-stdlib");function n(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var c=n(e);const u=c.forwardRef((({intensity:e=1,decay:n,decayRate:u=.65,maxYaw:a=.1,maxPitch:o=.1,maxRoll:s=.1,yawFrequency:i=.1,pitchFrequency:l=.1,rollFrequency:f=.1},d)=>{const m=r.useThree((e=>e.camera)),p=r.useThree((e=>e.controls)),y=c.useRef(e),h=c.useRef(m.rotation.clone()),[b]=c.useState((()=>new t.SimplexNoise)),[v]=c.useState((()=>new t.SimplexNoise)),[x]=c.useState((()=>new t.SimplexNoise)),w=()=>{(y.current<0||y.current>1)&&(y.current=y.current<0?0:1)};return c.useImperativeHandle(d,(()=>({getIntensity:()=>y.current,setIntensity:e=>{y.current=e,w()}})),[]),c.useEffect((()=>{if(p){const e=()=>{h.current=m.rotation.clone()};return p.addEventListener("change",e),e(),()=>{p.removeEventListener("change",e)}}}),[m,p]),r.useFrame(((e,r)=>{const t=Math.pow(y.current,2),c=a*t*b.noise(e.clock.elapsedTime*i,1),d=o*t*v.noise(e.clock.elapsedTime*l,1),p=s*t*x.noise(e.clock.elapsedTime*f,1);m.rotation.set(h.current.x+d,h.current.y+c,h.current.z+p),n&&y.current>0&&(y.current-=u*r,w())})),null}));exports.CameraShake=u;
+17
View File
@@ -0,0 +1,17 @@
import { ForwardRefComponent } from '../helpers/ts-utils';
export interface ShakeController {
getIntensity: () => number;
setIntensity: (val: number) => void;
}
export interface CameraShakeProps {
intensity?: number;
decay?: boolean;
decayRate?: number;
maxYaw?: number;
maxPitch?: number;
maxRoll?: number;
yawFrequency?: number;
pitchFrequency?: number;
rollFrequency?: number;
}
export declare const CameraShake: ForwardRefComponent<CameraShakeProps, ShakeController | undefined>;
+57
View File
@@ -0,0 +1,57 @@
import * as React from 'react';
import { useThree, useFrame } from '@react-three/fiber';
import { SimplexNoise } from 'three-stdlib';
const CameraShake = /* @__PURE__ */React.forwardRef(({
intensity = 1,
decay,
decayRate = 0.65,
maxYaw = 0.1,
maxPitch = 0.1,
maxRoll = 0.1,
yawFrequency = 0.1,
pitchFrequency = 0.1,
rollFrequency = 0.1
}, ref) => {
const camera = useThree(state => state.camera);
const defaultControls = useThree(state => state.controls);
const intensityRef = React.useRef(intensity);
const initialRotation = React.useRef(camera.rotation.clone());
const [yawNoise] = React.useState(() => new SimplexNoise());
const [pitchNoise] = React.useState(() => new SimplexNoise());
const [rollNoise] = React.useState(() => new SimplexNoise());
const constrainIntensity = () => {
if (intensityRef.current < 0 || intensityRef.current > 1) {
intensityRef.current = intensityRef.current < 0 ? 0 : 1;
}
};
React.useImperativeHandle(ref, () => ({
getIntensity: () => intensityRef.current,
setIntensity: val => {
intensityRef.current = val;
constrainIntensity();
}
}), []);
React.useEffect(() => {
if (defaultControls) {
const callback = () => void (initialRotation.current = camera.rotation.clone());
defaultControls.addEventListener('change', callback);
callback();
return () => void defaultControls.removeEventListener('change', callback);
}
}, [camera, defaultControls]);
useFrame((state, delta) => {
const shake = Math.pow(intensityRef.current, 2);
const yaw = maxYaw * shake * yawNoise.noise(state.clock.elapsedTime * yawFrequency, 1);
const pitch = maxPitch * shake * pitchNoise.noise(state.clock.elapsedTime * pitchFrequency, 1);
const roll = maxRoll * shake * rollNoise.noise(state.clock.elapsedTime * rollFrequency, 1);
camera.rotation.set(initialRotation.current.x + pitch, initialRotation.current.y + yaw, initialRotation.current.z + roll);
if (decay && intensityRef.current > 0) {
intensityRef.current -= decayRate * delta;
constrainIntensity();
}
});
return null;
});
export { CameraShake };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three"),n=require("./Line.cjs.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@react-three/fiber"),require("three-stdlib");var s=o(e),c=u(t);const l=c.forwardRef((function({points:e,closed:t=!1,curveType:o="centripetal",tension:u=.5,segments:l=20,vertexColors:i,...f},a){const p=c.useMemo((()=>{const n=e.map((e=>e instanceof r.Vector3?e:new r.Vector3(...e)));return new r.CatmullRomCurve3(n,t,o,u)}),[e,t,o,u]),d=c.useMemo((()=>p.getPoints(l)),[p,l]),h=c.useMemo((()=>{if(!i||i.length<2)return;if(i.length===l+1)return i;const e=i.map((e=>e instanceof r.Color?e:new r.Color(...e)));t&&e.push(e[0].clone());const n=[e[0]],o=l/(e.length-1);for(let t=1;t<l;t++){const r=t%o/o,u=Math.floor(t/o);n.push(e[u].clone().lerp(e[u+1],r))}return n.push(e[e.length-1]),n}),[i,l]);return c.createElement(n.Line,s.default({ref:a,points:d,vertexColors:h},f))}));exports.CatmullRomLine=l;
+10
View File
@@ -0,0 +1,10 @@
import { Line2 } from 'three-stdlib';
import { LineProps } from './Line';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type CatmullRomLineProps = Omit<LineProps, 'ref' | 'segments'> & {
closed?: boolean;
curveType?: 'centripetal' | 'chordal' | 'catmullrom';
tension?: number;
segments?: number;
};
export declare const CatmullRomLine: ForwardRefComponent<CatmullRomLineProps, Line2>;
+42
View File
@@ -0,0 +1,42 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { Vector3, CatmullRomCurve3, Color } from 'three';
import { Line } from './Line.js';
const CatmullRomLine = /* @__PURE__ */React.forwardRef(function CatmullRomLine({
points,
closed = false,
curveType = 'centripetal',
tension = 0.5,
segments = 20,
vertexColors,
...rest
}, ref) {
const curve = React.useMemo(() => {
const mappedPoints = points.map(pt => pt instanceof Vector3 ? pt : new Vector3(...pt));
return new CatmullRomCurve3(mappedPoints, closed, curveType, tension);
}, [points, closed, curveType, tension]);
const segmentedPoints = React.useMemo(() => curve.getPoints(segments), [curve, segments]);
const interpolatedVertexColors = React.useMemo(() => {
if (!vertexColors || vertexColors.length < 2) return undefined;
if (vertexColors.length === segments + 1) return vertexColors;
const mappedColors = vertexColors.map(color => color instanceof Color ? color : new Color(...color));
if (closed) mappedColors.push(mappedColors[0].clone());
const iColors = [mappedColors[0]];
const divisions = segments / (mappedColors.length - 1);
for (let i = 1; i < segments; i++) {
const alpha = i % divisions / divisions;
const colorIndex = Math.floor(i / divisions);
iColors.push(mappedColors[colorIndex].clone().lerp(mappedColors[colorIndex + 1], alpha));
}
iColors.push(mappedColors[mappedColors.length - 1]);
return iColors;
}, [vertexColors, segments]);
return /*#__PURE__*/React.createElement(Line, _extends({
ref: ref,
points: segmentedPoints,
vertexColors: interpolatedVertexColors
}, rest));
});
export { CatmullRomLine };
File diff suppressed because one or more lines are too long
+32
View File
@@ -0,0 +1,32 @@
import * as THREE from 'three';
import * as React from 'react';
import { ReactThreeFiber, ThreeElements } from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type CausticsProps = Omit<ThreeElements['group'], 'ref'> & {
frames?: number;
debug?: boolean;
causticsOnly: boolean;
backside: boolean;
ior?: number;
backsideIOR?: number;
worldRadius?: number;
intensity?: number;
color?: ReactThreeFiber.Color;
resolution?: number;
lightSource?: [x: number, y: number, z: number] | React.RefObject<THREE.Object3D>;
};
declare module '@react-three/fiber' {
interface ThreeElements {
causticsProjectionMaterial: ThreeElements['meshNormalMaterial'] & {
viewMatrix?: {
value: THREE.Matrix4;
};
color?: ReactThreeFiber.Color;
causticsTexture?: THREE.Texture;
causticsTextureB?: THREE.Texture;
lightProjMatrix?: THREE.Matrix4;
lightViewMatrix?: THREE.Matrix4;
};
}
}
export declare const Caustics: ForwardRefComponent<CausticsProps, THREE.Group>;
+388
View File
@@ -0,0 +1,388 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as THREE from 'three';
import * as React from 'react';
import { extend, useThree, useFrame } from '@react-three/fiber';
import { useFBO } from './Fbo.js';
import { useHelper } from './Helper.js';
import { shaderMaterial } from './shaderMaterial.js';
import { Edges } from './Edges.js';
import { FullScreenQuad } from 'three-stdlib';
import { version } from '../helpers/constants.js';
function createNormalMaterial(side = THREE.FrontSide) {
const viewMatrix = {
value: new THREE.Matrix4()
};
return Object.assign(new THREE.MeshNormalMaterial({
side
}), {
viewMatrix,
onBeforeCompile: shader => {
shader.uniforms.viewMatrix = viewMatrix;
shader.fragmentShader = `vec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {
return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );
}\n` + shader.fragmentShader.replace('#include <normal_fragment_maps>', `#include <normal_fragment_maps>
normal = inverseTransformDirection( normal, viewMatrix );\n`);
}
});
}
const CausticsProjectionMaterial = /* @__PURE__ */shaderMaterial({
causticsTexture: null,
causticsTextureB: null,
color: /* @__PURE__ */new THREE.Color(),
lightProjMatrix: /* @__PURE__ */new THREE.Matrix4(),
lightViewMatrix: /* @__PURE__ */new THREE.Matrix4()
}, `varying vec3 vWorldPosition;
void main() {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.);
vec4 worldPosition = modelMatrix * vec4(position, 1.);
vWorldPosition = worldPosition.xyz;
}`, `varying vec3 vWorldPosition;
uniform vec3 color;
uniform sampler2D causticsTexture;
uniform sampler2D causticsTextureB;
uniform mat4 lightProjMatrix;
uniform mat4 lightViewMatrix;
void main() {
// Apply caustics
vec4 lightSpacePos = lightProjMatrix * lightViewMatrix * vec4(vWorldPosition, 1.0);
lightSpacePos.xyz /= lightSpacePos.w;
lightSpacePos.xyz = lightSpacePos.xyz * 0.5 + 0.5;
vec3 front = texture2D(causticsTexture, lightSpacePos.xy).rgb;
vec3 back = texture2D(causticsTextureB, lightSpacePos.xy).rgb;
gl_FragColor = vec4((front + back) * color, 1.0);
#include <tonemapping_fragment>
#include <${version >= 154 ? 'colorspace_fragment' : 'encodings_fragment'}>
}`);
const CausticsMaterial = /* @__PURE__ */shaderMaterial({
cameraMatrixWorld: /* @__PURE__ */new THREE.Matrix4(),
cameraProjectionMatrixInv: /* @__PURE__ */new THREE.Matrix4(),
normalTexture: null,
depthTexture: null,
lightDir: /* @__PURE__ */new THREE.Vector3(0, 1, 0),
lightPlaneNormal: /* @__PURE__ */new THREE.Vector3(0, 1, 0),
lightPlaneConstant: 0,
near: 0.1,
far: 100,
modelMatrix: /* @__PURE__ */new THREE.Matrix4(),
worldRadius: 1 / 40,
ior: 1.1,
bounces: 0,
resolution: 1024,
size: 10,
intensity: 0.5
}, /* glsl */`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}`, /* glsl */`
uniform mat4 cameraMatrixWorld;
uniform mat4 cameraProjectionMatrixInv;
uniform vec3 lightDir;
uniform vec3 lightPlaneNormal;
uniform float lightPlaneConstant;
uniform float near;
uniform float far;
uniform float time;
uniform float worldRadius;
uniform float resolution;
uniform float size;
uniform float intensity;
uniform float ior;
precision highp isampler2D;
precision highp usampler2D;
uniform sampler2D normalTexture;
uniform sampler2D depthTexture;
uniform float bounces;
varying vec2 vUv;
vec3 WorldPosFromDepth(float depth, vec2 coord) {
float z = depth * 2.0 - 1.0;
vec4 clipSpacePosition = vec4(coord * 2.0 - 1.0, z, 1.0);
vec4 viewSpacePosition = cameraProjectionMatrixInv * clipSpacePosition;
// Perspective division
viewSpacePosition /= viewSpacePosition.w;
vec4 worldSpacePosition = cameraMatrixWorld * viewSpacePosition;
return worldSpacePosition.xyz;
}
float sdPlane( vec3 p, vec3 n, float h ) {
// n must be normalized
return dot(p,n) + h;
}
float planeIntersect( vec3 ro, vec3 rd, vec4 p ) {
return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);
}
vec3 totalInternalReflection(vec3 ro, vec3 rd, vec3 pos, vec3 normal, float ior, out vec3 rayOrigin, out vec3 rayDirection) {
rayOrigin = ro;
rayDirection = rd;
rayDirection = refract(rayDirection, normal, 1.0 / ior);
rayOrigin = pos + rayDirection * 0.1;
return rayDirection;
}
void main() {
// Each sample consists of random offset in the x and y direction
float caustic = 0.0;
float causticTexelSize = (1.0 / resolution) * size * 2.0;
float texelsNeeded = worldRadius / causticTexelSize;
float sampleRadius = texelsNeeded / resolution;
float sum = 0.0;
if (texture2D(depthTexture, vUv).x == 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
vec2 offset1 = vec2(-0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);
vec2 offset2 = vec2(-0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);
vec2 offset3 = vec2(0.5, 0.5);//vec2(rand() - 0.5, rand() - 0.5);
vec2 offset4 = vec2(0.5, -0.5);//vec2(rand() - 0.5, rand() - 0.5);
vec2 uv1 = vUv + offset1 * sampleRadius;
vec2 uv2 = vUv + offset2 * sampleRadius;
vec2 uv3 = vUv + offset3 * sampleRadius;
vec2 uv4 = vUv + offset4 * sampleRadius;
vec3 normal1 = texture2D(normalTexture, uv1, -10.0).rgb * 2.0 - 1.0;
vec3 normal2 = texture2D(normalTexture, uv2, -10.0).rgb * 2.0 - 1.0;
vec3 normal3 = texture2D(normalTexture, uv3, -10.0).rgb * 2.0 - 1.0;
vec3 normal4 = texture2D(normalTexture, uv4, -10.0).rgb * 2.0 - 1.0;
float depth1 = texture2D(depthTexture, uv1, -10.0).x;
float depth2 = texture2D(depthTexture, uv2, -10.0).x;
float depth3 = texture2D(depthTexture, uv3, -10.0).x;
float depth4 = texture2D(depthTexture, uv4, -10.0).x;
// Sanity check the depths
if (depth1 == 1.0 || depth2 == 1.0 || depth3 == 1.0 || depth4 == 1.0) {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
vec3 pos1 = WorldPosFromDepth(depth1, uv1);
vec3 pos2 = WorldPosFromDepth(depth2, uv2);
vec3 pos3 = WorldPosFromDepth(depth3, uv3);
vec3 pos4 = WorldPosFromDepth(depth4, uv4);
vec3 originPos1 = WorldPosFromDepth(0.0, uv1);
vec3 originPos2 = WorldPosFromDepth(0.0, uv2);
vec3 originPos3 = WorldPosFromDepth(0.0, uv3);
vec3 originPos4 = WorldPosFromDepth(0.0, uv4);
vec3 endPos1, endPos2, endPos3, endPos4;
vec3 endDir1, endDir2, endDir3, endDir4;
totalInternalReflection(originPos1, lightDir, pos1, normal1, ior, endPos1, endDir1);
totalInternalReflection(originPos2, lightDir, pos2, normal2, ior, endPos2, endDir2);
totalInternalReflection(originPos3, lightDir, pos3, normal3, ior, endPos3, endDir3);
totalInternalReflection(originPos4, lightDir, pos4, normal4, ior, endPos4, endDir4);
float lightPosArea = length(cross(originPos2 - originPos1, originPos3 - originPos1)) + length(cross(originPos3 - originPos1, originPos4 - originPos1));
float t1 = planeIntersect(endPos1, endDir1, vec4(lightPlaneNormal, lightPlaneConstant));
float t2 = planeIntersect(endPos2, endDir2, vec4(lightPlaneNormal, lightPlaneConstant));
float t3 = planeIntersect(endPos3, endDir3, vec4(lightPlaneNormal, lightPlaneConstant));
float t4 = planeIntersect(endPos4, endDir4, vec4(lightPlaneNormal, lightPlaneConstant));
vec3 finalPos1 = endPos1 + endDir1 * t1;
vec3 finalPos2 = endPos2 + endDir2 * t2;
vec3 finalPos3 = endPos3 + endDir3 * t3;
vec3 finalPos4 = endPos4 + endDir4 * t4;
float finalArea = length(cross(finalPos2 - finalPos1, finalPos3 - finalPos1)) + length(cross(finalPos3 - finalPos1, finalPos4 - finalPos1));
caustic += intensity * (lightPosArea / finalArea);
// Calculate the area of the triangle in light spaces
gl_FragColor = vec4(vec3(max(caustic, 0.0)), 1.0);
}`);
const NORMALPROPS = {
depth: true,
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
type: THREE.UnsignedByteType
};
const CAUSTICPROPS = {
minFilter: THREE.LinearMipmapLinearFilter,
magFilter: THREE.LinearFilter,
type: THREE.FloatType,
generateMipmaps: true
};
const Caustics = /* @__PURE__ */React.forwardRef(({
debug,
children,
frames = 1,
ior = 1.1,
color = 'white',
causticsOnly = false,
backside = false,
backsideIOR = 1.1,
worldRadius = 0.3125,
intensity = 0.05,
resolution = 2024,
lightSource = [5, 5, 5],
...props
}, fref) => {
extend({
CausticsProjectionMaterial
});
const ref = React.useRef(null);
const camera = React.useRef(null);
const scene = React.useRef(null);
const plane = React.useRef(null);
const gl = useThree(state => state.gl);
const helper = useHelper(debug && camera, THREE.CameraHelper);
// Buffers for front and back faces
const normalTarget = useFBO(resolution, resolution, NORMALPROPS);
const normalTargetB = useFBO(resolution, resolution, NORMALPROPS);
const causticsTarget = useFBO(resolution, resolution, CAUSTICPROPS);
const causticsTargetB = useFBO(resolution, resolution, CAUSTICPROPS);
// Normal materials for front and back faces
const [normalMat] = React.useState(() => createNormalMaterial());
const [normalMatB] = React.useState(() => createNormalMaterial(THREE.BackSide));
// The quad that catches the caustics
const [causticsMaterial] = React.useState(() => new CausticsMaterial());
const [causticsQuad] = React.useState(() => new FullScreenQuad(causticsMaterial));
React.useLayoutEffect(() => {
ref.current.updateWorldMatrix(false, true);
});
let count = 0;
const v = new THREE.Vector3();
const lpF = new THREE.Frustum();
const lpM = new THREE.Matrix4();
const lpP = new THREE.Plane();
const lightDir = new THREE.Vector3();
const lightDirInv = new THREE.Vector3();
const bounds = new THREE.Box3();
const focusPos = new THREE.Vector3();
const boundsVertices = [];
const worldVerts = [];
const projectedVerts = [];
const lightDirs = [];
const cameraPos = new THREE.Vector3();
for (let i = 0; i < 8; i++) {
boundsVertices.push(new THREE.Vector3());
worldVerts.push(new THREE.Vector3());
projectedVerts.push(new THREE.Vector3());
lightDirs.push(new THREE.Vector3());
}
useFrame(() => {
if (frames === Infinity || count++ < frames) {
var _scene$current$parent, _helper$current;
if (Array.isArray(lightSource)) lightDir.fromArray(lightSource).normalize();else lightDir.copy(ref.current.worldToLocal(lightSource.current.getWorldPosition(v)).normalize());
lightDirInv.copy(lightDir).multiplyScalar(-1);
(_scene$current$parent = scene.current.parent) == null || _scene$current$parent.matrixWorld.identity();
bounds.setFromObject(scene.current, true);
boundsVertices[0].set(bounds.min.x, bounds.min.y, bounds.min.z);
boundsVertices[1].set(bounds.min.x, bounds.min.y, bounds.max.z);
boundsVertices[2].set(bounds.min.x, bounds.max.y, bounds.min.z);
boundsVertices[3].set(bounds.min.x, bounds.max.y, bounds.max.z);
boundsVertices[4].set(bounds.max.x, bounds.min.y, bounds.min.z);
boundsVertices[5].set(bounds.max.x, bounds.min.y, bounds.max.z);
boundsVertices[6].set(bounds.max.x, bounds.max.y, bounds.min.z);
boundsVertices[7].set(bounds.max.x, bounds.max.y, bounds.max.z);
for (let i = 0; i < 8; i++) {
worldVerts[i].copy(boundsVertices[i]);
}
bounds.getCenter(focusPos);
boundsVertices.map(v => v.sub(focusPos));
const lightPlane = lpP.set(lightDirInv, 0);
boundsVertices.map((v, i) => lightPlane.projectPoint(v, projectedVerts[i]));
const centralVert = projectedVerts.reduce((a, b) => a.add(b), v.set(0, 0, 0)).divideScalar(projectedVerts.length);
const radius = projectedVerts.map(v => v.distanceTo(centralVert)).reduce((a, b) => Math.max(a, b));
const dirLength = boundsVertices.map(x => x.dot(lightDir)).reduce((a, b) => Math.max(a, b));
// Shadows
camera.current.position.copy(cameraPos.copy(lightDir).multiplyScalar(dirLength).add(focusPos));
camera.current.lookAt(scene.current.localToWorld(focusPos));
const dirMatrix = lpM.lookAt(camera.current.position, focusPos, v.set(0, 1, 0));
camera.current.left = -radius;
camera.current.right = radius;
camera.current.top = radius;
camera.current.bottom = -radius;
const yOffset = v.set(0, radius, 0).applyMatrix4(dirMatrix);
const yTime = (camera.current.position.y + yOffset.y) / lightDir.y;
camera.current.near = 0.1;
camera.current.far = yTime;
camera.current.updateProjectionMatrix();
camera.current.updateMatrixWorld();
// Now find size of ground plane
const groundProjectedCoords = worldVerts.map((v, i) => v.add(lightDirs[i].copy(lightDir).multiplyScalar(-v.y / lightDir.y)));
const centerPos = groundProjectedCoords.reduce((a, b) => a.add(b), v.set(0, 0, 0)).divideScalar(groundProjectedCoords.length);
const maxSize = 2 * groundProjectedCoords.map(v => Math.hypot(v.x - centerPos.x, v.z - centerPos.z)).reduce((a, b) => Math.max(a, b));
plane.current.scale.setScalar(maxSize);
plane.current.position.copy(centerPos);
if (debug) (_helper$current = helper.current) == null || _helper$current.update();
// Inject uniforms
normalMatB.viewMatrix.value = normalMat.viewMatrix.value = camera.current.matrixWorldInverse;
const dirLightNearPlane = lpF.setFromProjectionMatrix(lpM.multiplyMatrices(camera.current.projectionMatrix, camera.current.matrixWorldInverse)).planes[4];
causticsMaterial.cameraMatrixWorld = camera.current.matrixWorld;
causticsMaterial.cameraProjectionMatrixInv = camera.current.projectionMatrixInverse;
causticsMaterial.lightDir = lightDirInv;
causticsMaterial.lightPlaneNormal = dirLightNearPlane.normal;
causticsMaterial.lightPlaneConstant = dirLightNearPlane.constant;
causticsMaterial.near = camera.current.near;
causticsMaterial.far = camera.current.far;
causticsMaterial.resolution = resolution;
causticsMaterial.size = radius;
causticsMaterial.intensity = intensity;
causticsMaterial.worldRadius = worldRadius;
// Switch the scene on
scene.current.visible = true;
// Render front face normals
gl.setRenderTarget(normalTarget);
gl.clear();
scene.current.overrideMaterial = normalMat;
gl.render(scene.current, camera.current);
// Render back face normals, if enabled
gl.setRenderTarget(normalTargetB);
gl.clear();
if (backside) {
scene.current.overrideMaterial = normalMatB;
gl.render(scene.current, camera.current);
}
// Remove the override material
scene.current.overrideMaterial = null;
// Render front face caustics
causticsMaterial.ior = ior;
plane.current.material.lightProjMatrix = camera.current.projectionMatrix;
plane.current.material.lightViewMatrix = camera.current.matrixWorldInverse;
causticsMaterial.normalTexture = normalTarget.texture;
causticsMaterial.depthTexture = normalTarget.depthTexture;
gl.setRenderTarget(causticsTarget);
gl.clear();
causticsQuad.render(gl);
// Render back face caustics, if enabled
causticsMaterial.ior = backsideIOR;
causticsMaterial.normalTexture = normalTargetB.texture;
causticsMaterial.depthTexture = normalTargetB.depthTexture;
gl.setRenderTarget(causticsTargetB);
gl.clear();
if (backside) causticsQuad.render(gl);
// Reset render target
gl.setRenderTarget(null);
// Switch the scene off if caustics is all that's wanted
if (causticsOnly) scene.current.visible = false;
}
});
React.useImperativeHandle(fref, () => ref.current, []);
return /*#__PURE__*/React.createElement("group", _extends({
ref: ref
}, props), /*#__PURE__*/React.createElement("scene", {
ref: scene
}, /*#__PURE__*/React.createElement("orthographicCamera", {
ref: camera,
up: [0, 1, 0]
}), children), /*#__PURE__*/React.createElement("mesh", {
renderOrder: 2,
ref: plane,
"rotation-x": -Math.PI / 2
}, /*#__PURE__*/React.createElement("planeGeometry", null), /*#__PURE__*/React.createElement("causticsProjectionMaterial", {
transparent: true,
color: color,
causticsTexture: causticsTarget.texture,
causticsTextureB: causticsTargetB.texture,
blending: THREE.CustomBlending,
blendSrc: THREE.OneFactor,
blendDst: THREE.SrcAlphaFactor,
depthWrite: false
}), debug && /*#__PURE__*/React.createElement(Edges, null, /*#__PURE__*/React.createElement("lineBasicMaterial", {
color: "#ffff00",
toneMapped: false
}))));
});
export { Caustics };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=n(e),i=u(r);const c=i.forwardRef((function({children:e,object:r,disable:n,disableX:u,disableY:c,disableZ:a,left:l,right:s,top:f,bottom:d,front:p,back:b,onCentered:m,precise:g=!0,cacheKey:h=0,...x},y){const j=i.useRef(null),O=i.useRef(null),v=i.useRef(null),[w]=i.useState((()=>new t.Box3)),[S]=i.useState((()=>new t.Vector3)),[z]=i.useState((()=>new t.Sphere));return i.useLayoutEffect((()=>{O.current.matrixWorld.identity(),w.setFromObject(null!=r?r:v.current,g);const e=w.max.x-w.min.x,t=w.max.y-w.min.y,o=w.max.z-w.min.z;w.getCenter(S),w.getBoundingSphere(z);const i=f?t/2:d?-t/2:0,h=l?-e/2:s?e/2:0,x=p?o/2:b?-o/2:0;O.current.position.set(n||u?0:-S.x+h,n||c?0:-S.y+i,n||a?0:-S.z+x),null==m||m({parent:j.current.parent,container:j.current,width:e,height:t,depth:o,boundingBox:w,boundingSphere:z,center:S,verticalAlignment:i,horizontalAlignment:h,depthAlignment:x})}),[h,m,f,l,p,n,u,c,a,r,g,s,d,b,w,S,z]),i.useImperativeHandle(y,(()=>j.current),[]),i.createElement("group",o.default({ref:j},x),i.createElement("group",{ref:O},i.createElement("group",{ref:v},e)))}));exports.Center=c;
+33
View File
@@ -0,0 +1,33 @@
import { Box3, Vector3, Sphere, Group, Object3D } from 'three';
import { ThreeElements } from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type OnCenterCallbackProps = {
parent: Object3D;
container: Object3D;
width: number;
height: number;
depth: number;
boundingBox: Box3;
boundingSphere: Sphere;
center: Vector3;
verticalAlignment: number;
horizontalAlignment: number;
depthAlignment: number;
};
export type CenterProps = Omit<ThreeElements['group'], 'ref'> & {
top?: boolean;
right?: boolean;
bottom?: boolean;
left?: boolean;
front?: boolean;
back?: boolean;
disable?: boolean;
disableX?: boolean;
disableY?: boolean;
disableZ?: boolean;
object?: Object3D | null;
precise?: boolean;
onCentered?: (props: OnCenterCallbackProps) => void;
cacheKey?: any;
};
export declare const Center: ForwardRefComponent<CenterProps, Group>;
+67
View File
@@ -0,0 +1,67 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import { Box3, Vector3, Sphere } from 'three';
import * as React from 'react';
const Center = /* @__PURE__ */React.forwardRef(function Center({
children,
object,
disable,
disableX,
disableY,
disableZ,
left,
right,
top,
bottom,
front,
back,
onCentered,
precise = true,
cacheKey = 0,
...props
}, fRef) {
const ref = React.useRef(null);
const outer = React.useRef(null);
const inner = React.useRef(null);
const [box3] = React.useState(() => new Box3());
const [center] = React.useState(() => new Vector3());
const [sphere] = React.useState(() => new Sphere());
React.useLayoutEffect(() => {
outer.current.matrixWorld.identity();
box3.setFromObject(object !== null && object !== void 0 ? object : inner.current, precise);
const width = box3.max.x - box3.min.x;
const height = box3.max.y - box3.min.y;
const depth = box3.max.z - box3.min.z;
box3.getCenter(center);
box3.getBoundingSphere(sphere);
const vAlign = top ? height / 2 : bottom ? -height / 2 : 0;
const hAlign = left ? -width / 2 : right ? width / 2 : 0;
const dAlign = front ? depth / 2 : back ? -depth / 2 : 0;
outer.current.position.set(disable || disableX ? 0 : -center.x + hAlign, disable || disableY ? 0 : -center.y + vAlign, disable || disableZ ? 0 : -center.z + dAlign);
// Only fire onCentered if the bounding box has changed
onCentered == null || onCentered({
parent: ref.current.parent,
container: ref.current,
width,
height,
depth,
boundingBox: box3,
boundingSphere: sphere,
center: center,
verticalAlignment: vAlign,
horizontalAlignment: hAlign,
depthAlignment: dAlign
});
}, [cacheKey, onCentered, top, left, front, disable, disableX, disableY, disableZ, object, precise, right, bottom, back, box3, center, sphere]);
React.useImperativeHandle(fRef, () => ref.current, []);
return /*#__PURE__*/React.createElement("group", _extends({
ref: ref
}, props), /*#__PURE__*/React.createElement("group", {
ref: outer
}, /*#__PURE__*/React.createElement("group", {
ref: inner
}, children)));
});
export { Center };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("three"),r=require("react"),n=require("three-stdlib");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=a(e),c=i(t),l=i(r);const s=l.forwardRef((({isChild:e=!1,object:t,children:r,deep:a,castShadow:i,receiveShadow:d,inject:u,keys:f,...y},m)=>{const h={keys:f,deep:a,inject:u,castShadow:i,receiveShadow:d};if(t=l.useMemo((()=>{if(!1===e&&!Array.isArray(t)){let e=!1;if(t.traverse((t=>{t.isSkinnedMesh&&(e=!0)})),e)return n.SkeletonUtils.clone(t)}return t}),[t,e]),Array.isArray(t))return l.createElement("group",o.default({},y,{ref:m}),t.map((e=>l.createElement(s,o.default({key:e.uuid,object:e},h)))),r);const{children:p,...b}=function(e,{keys:t=["near","far","color","distance","decay","penumbra","angle","intensity","skeleton","visible","castShadow","receiveShadow","morphTargetDictionary","morphTargetInfluences","name","geometry","material","position","rotation","scale","up","userData","bindMode","bindMatrix","bindMatrixInverse","skeleton"],deep:r,inject:n,castShadow:a,receiveShadow:i}){let o={};for(const r of t)o[r]=e[r];return r&&(o.geometry&&"materialsOnly"!==r&&(o.geometry=o.geometry.clone()),o.material&&"geometriesOnly"!==r&&(o.material=o.material.clone())),n&&(o="function"==typeof n?{...o,children:n(e)}:l.isValidElement(n)?{...o,children:n}:{...o,...n}),e instanceof c.Mesh&&(a&&(o.castShadow=!0),i&&(o.receiveShadow=!0)),o}(t,h),j=t.type[0].toLowerCase()+t.type.slice(1);return l.createElement(j,o.default({},b,y,{ref:m}),t.children.map((e=>"Bone"===e.type?l.createElement("primitive",o.default({key:e.uuid,object:e},h)):l.createElement(s,o.default({key:e.uuid,object:e},h,{isChild:!0})))),r,p)}));exports.Clone=s;
+15
View File
@@ -0,0 +1,15 @@
import * as THREE from 'three';
import * as React from 'react';
import { ForwardRefComponent } from '../helpers/ts-utils';
import { ThreeElements } from '@react-three/fiber';
export type CloneProps = Omit<ThreeElements['group'], 'ref' | 'children'> & {
object: THREE.Object3D | THREE.Object3D[];
children?: React.ReactNode;
deep?: boolean | 'materialsOnly' | 'geometriesOnly';
keys?: string[];
inject?: ThreeElements['mesh'] | React.ReactNode | ((object: THREE.Object3D) => React.ReactNode);
castShadow?: boolean;
receiveShadow?: boolean;
isChild?: boolean;
};
export declare const Clone: ForwardRefComponent<CloneProps, THREE.Group>;
+100
View File
@@ -0,0 +1,100 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as THREE from 'three';
import * as React from 'react';
import { SkeletonUtils } from 'three-stdlib';
function createSpread(child, {
keys = ['near', 'far', 'color', 'distance', 'decay', 'penumbra', 'angle', 'intensity', 'skeleton', 'visible', 'castShadow', 'receiveShadow', 'morphTargetDictionary', 'morphTargetInfluences', 'name', 'geometry', 'material', 'position', 'rotation', 'scale', 'up', 'userData', 'bindMode', 'bindMatrix', 'bindMatrixInverse', 'skeleton'],
deep,
inject,
castShadow,
receiveShadow
}) {
let spread = {};
for (const key of keys) {
spread[key] = child[key];
}
if (deep) {
if (spread.geometry && deep !== 'materialsOnly') spread.geometry = spread.geometry.clone();
if (spread.material && deep !== 'geometriesOnly') spread.material = spread.material.clone();
}
if (inject) {
if (typeof inject === 'function') spread = {
...spread,
children: inject(child)
};else if (/*#__PURE__*/React.isValidElement(inject)) spread = {
...spread,
children: inject
};else spread = {
...spread,
...inject
};
}
if (child instanceof THREE.Mesh) {
if (castShadow) spread.castShadow = true;
if (receiveShadow) spread.receiveShadow = true;
}
return spread;
}
const Clone = /* @__PURE__ */React.forwardRef(({
isChild = false,
object,
children,
deep,
castShadow,
receiveShadow,
inject,
keys,
...props
}, forwardRef) => {
const config = {
keys,
deep,
inject,
castShadow,
receiveShadow
};
object = React.useMemo(() => {
if (isChild === false && !Array.isArray(object)) {
let isSkinned = false;
object.traverse(object => {
if (object.isSkinnedMesh) isSkinned = true;
});
if (isSkinned) return SkeletonUtils.clone(object);
}
return object;
}, [object, isChild]);
// Deal with arrayed clones
if (Array.isArray(object)) {
return /*#__PURE__*/React.createElement("group", _extends({}, props, {
ref: forwardRef
}), object.map(o => /*#__PURE__*/React.createElement(Clone, _extends({
key: o.uuid,
object: o
}, config))), children);
}
// Singleton clones
const {
children: injectChildren,
...spread
} = createSpread(object, config);
const Element = object.type[0].toLowerCase() + object.type.slice(1);
return /*#__PURE__*/React.createElement(Element, _extends({}, spread, props, {
ref: forwardRef
}), object.children.map(child => {
if (child.type === 'Bone') return /*#__PURE__*/React.createElement("primitive", _extends({
key: child.uuid,
object: child
}, config));
return /*#__PURE__*/React.createElement(Clone, _extends({
key: child.uuid,
object: child
}, config, {
isChild: true
}));
}), children, injectChildren);
});
export { Clone };
File diff suppressed because one or more lines are too long
+97
View File
@@ -0,0 +1,97 @@
import * as React from 'react';
import { Color, Group, Vector3, Material, MeshLambertMaterial, Matrix4 } from 'three';
import { ReactThreeFiber, ThreeElement, ThreeElements } from '@react-three/fiber';
declare module '@react-three/fiber' {
interface ThreeElements {
cloudMaterial: ThreeElement<typeof MeshLambertMaterial>;
}
}
type CloudState = {
uuid: string;
index: number;
segments: number;
dist: number;
matrix: Matrix4;
bounds: Vector3;
position: Vector3;
volume: number;
length: number;
ref: React.RefObject<Group>;
speed: number;
growth: number;
opacity: number;
fade: number;
density: number;
rotation: number;
rotationFactor: number;
color: Color;
};
export type CloudsProps = Omit<ThreeElements['group'], 'ref'> & {
texture?: string;
limit?: number;
range?: number;
material?: typeof Material;
frustumCulled?: boolean;
};
export type CloudProps = Omit<ThreeElements['group'], 'ref'> & {
seed?: number;
segments?: number;
bounds?: ReactThreeFiber.Vector3;
concentrate?: 'random' | 'inside' | 'outside';
scale?: ReactThreeFiber.Vector3;
volume?: number;
smallestVolume?: number;
distribute?: (cloud: CloudState, index: number) => {
point: Vector3;
volume?: number;
};
growth?: number;
speed?: number;
fade?: number;
opacity?: number;
color?: ReactThreeFiber.Color;
};
export declare const Clouds: React.ForwardRefExoticComponent<Omit<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Group<import("three").Object3DEventMap>, ReactThreeFiber.MathProps<Group<import("three").Object3DEventMap>> & ReactThreeFiber.ReactProps<Group<import("three").Object3DEventMap>> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<Group<import("three").Object3DEventMap>, typeof Group>, "object">>>, "ref"> & {
texture?: string;
limit?: number;
range?: number;
material?: typeof Material;
frustumCulled?: boolean;
} & React.RefAttributes<Group<import("three").Object3DEventMap>>>;
export declare const CloudInstance: React.ForwardRefExoticComponent<Omit<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Group<import("three").Object3DEventMap>, ReactThreeFiber.MathProps<Group<import("three").Object3DEventMap>> & ReactThreeFiber.ReactProps<Group<import("three").Object3DEventMap>> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<Group<import("three").Object3DEventMap>, typeof Group>, "object">>>, "ref"> & {
seed?: number;
segments?: number;
bounds?: ReactThreeFiber.Vector3;
concentrate?: "random" | "inside" | "outside";
scale?: ReactThreeFiber.Vector3;
volume?: number;
smallestVolume?: number;
distribute?: (cloud: CloudState, index: number) => {
point: Vector3;
volume?: number;
};
growth?: number;
speed?: number;
fade?: number;
opacity?: number;
color?: ReactThreeFiber.Color;
} & React.RefAttributes<Group<import("three").Object3DEventMap>>>;
export declare const Cloud: React.ForwardRefExoticComponent<Omit<import("@react-three/fiber/dist/declarations/src/core/utils").Mutable<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Partial<import("@react-three/fiber/dist/declarations/src/core/utils").Overwrite<Group<import("three").Object3DEventMap>, ReactThreeFiber.MathProps<Group<import("three").Object3DEventMap>> & ReactThreeFiber.ReactProps<Group<import("three").Object3DEventMap>> & Partial<import("@react-three/fiber").EventHandlers>>>, Omit<import("@react-three/fiber").InstanceProps<Group<import("three").Object3DEventMap>, typeof Group>, "object">>>, "ref"> & {
seed?: number;
segments?: number;
bounds?: ReactThreeFiber.Vector3;
concentrate?: "random" | "inside" | "outside";
scale?: ReactThreeFiber.Vector3;
volume?: number;
smallestVolume?: number;
distribute?: (cloud: CloudState, index: number) => {
point: Vector3;
volume?: number;
};
growth?: number;
speed?: number;
fade?: number;
opacity?: number;
color?: ReactThreeFiber.Color;
} & React.RefAttributes<Group<import("three").Object3DEventMap>>>;
export {};
+231
View File
@@ -0,0 +1,231 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { REVISION, Quaternion, Vector3, DynamicDrawUsage, MeshLambertMaterial, Matrix4, Color } from 'three';
import { extend, useFrame, applyProps } from '@react-three/fiber';
import { useTexture } from './Texture.js';
import { setUpdateRange } from '../helpers/deprecated.js';
const CLOUD_URL = 'https://rawcdn.githack.com/pmndrs/drei-assets/9225a9f1fbd449d9411125c2f419b843d0308c9f/cloud.png';
const parentMatrix = /* @__PURE__ */new Matrix4();
const translation = /* @__PURE__ */new Vector3();
const rotation = /* @__PURE__ */new Quaternion();
const cpos = /* @__PURE__ */new Vector3();
const cquat = /* @__PURE__ */new Quaternion();
const scale = /* @__PURE__ */new Vector3();
const context = /* @__PURE__ */React.createContext(null);
const Clouds = /* @__PURE__ */React.forwardRef(({
children,
material = MeshLambertMaterial,
texture = CLOUD_URL,
range,
limit = 200,
frustumCulled,
...props
}, fref) => {
var _image$width, _image$height;
const CloudMaterial = React.useMemo(() => {
return class extends material {
constructor() {
super();
const opaque_fragment = parseInt(REVISION.replace(/\D+/g, '')) >= 154 ? 'opaque_fragment' : 'output_fragment';
this.onBeforeCompile = shader => {
shader.vertexShader = `attribute float cloudOpacity;
varying float vOpacity;
` + shader.vertexShader.replace('#include <fog_vertex>', `#include <fog_vertex>
vOpacity = cloudOpacity;
`);
shader.fragmentShader = `varying float vOpacity;
` + shader.fragmentShader.replace(`#include <${opaque_fragment}>`, `#include <${opaque_fragment}>
gl_FragColor = vec4(outgoingLight, diffuseColor.a * vOpacity);
`);
};
}
};
}, [material]);
extend({
CloudMaterial
});
const instance = React.useRef(null);
const clouds = React.useRef([]);
const opacities = React.useMemo(() => new Float32Array(Array.from({
length: limit
}, () => 1)), [limit]);
const colors = React.useMemo(() => new Float32Array(Array.from({
length: limit
}, () => [1, 1, 1]).flat()), [limit]);
const cloudTexture = useTexture(texture);
let t = 0;
let index = 0;
let config;
const qat = new Quaternion();
const dir = new Vector3(0, 0, 1);
const pos = new Vector3();
useFrame((state, delta) => {
t = state.clock.elapsedTime;
parentMatrix.copy(instance.current.matrixWorld).invert();
state.camera.matrixWorld.decompose(cpos, cquat, scale);
for (index = 0; index < clouds.current.length; index++) {
config = clouds.current[index];
config.ref.current.matrixWorld.decompose(translation, rotation, scale);
translation.add(pos.copy(config.position).applyQuaternion(rotation).multiply(scale));
rotation.copy(cquat).multiply(qat.setFromAxisAngle(dir, config.rotation += delta * config.rotationFactor));
scale.multiplyScalar(config.volume + (1 + Math.sin(t * config.density * config.speed)) / 2 * config.growth);
config.matrix.compose(translation, rotation, scale).premultiply(parentMatrix);
config.dist = translation.distanceTo(cpos);
}
// Depth-sort. Instances have no specific draw order, w/o sorting z would be random
clouds.current.sort((a, b) => b.dist - a.dist);
for (index = 0; index < clouds.current.length; index++) {
config = clouds.current[index];
opacities[index] = config.opacity * (config.dist < config.fade - 1 ? config.dist / config.fade : 1);
instance.current.setMatrixAt(index, config.matrix);
instance.current.setColorAt(index, config.color);
}
// Update instance
instance.current.geometry.attributes.cloudOpacity.needsUpdate = true;
instance.current.instanceMatrix.needsUpdate = true;
if (instance.current.instanceColor) instance.current.instanceColor.needsUpdate = true;
});
React.useLayoutEffect(() => {
const count = Math.min(limit, range !== undefined ? range : limit, clouds.current.length);
instance.current.count = count;
setUpdateRange(instance.current.instanceMatrix, {
start: 0,
count: count * 16
});
if (instance.current.instanceColor) {
setUpdateRange(instance.current.instanceColor, {
start: 0,
count: count * 3
});
}
setUpdateRange(instance.current.geometry.attributes.cloudOpacity, {
start: 0,
count: count
});
});
let imageBounds = [(_image$width = cloudTexture.image.width) !== null && _image$width !== void 0 ? _image$width : 1, (_image$height = cloudTexture.image.height) !== null && _image$height !== void 0 ? _image$height : 1];
const max = Math.max(imageBounds[0], imageBounds[1]);
imageBounds = [imageBounds[0] / max, imageBounds[1] / max];
return /*#__PURE__*/React.createElement("group", _extends({
ref: fref
}, props), /*#__PURE__*/React.createElement(context.Provider, {
value: clouds
}, children, /*#__PURE__*/React.createElement("instancedMesh", {
matrixAutoUpdate: false,
ref: instance,
args: [null, null, limit],
frustumCulled: frustumCulled
}, /*#__PURE__*/React.createElement("instancedBufferAttribute", {
usage: DynamicDrawUsage,
attach: "instanceColor",
args: [colors, 3]
}), /*#__PURE__*/React.createElement("planeGeometry", {
args: [...imageBounds]
}, /*#__PURE__*/React.createElement("instancedBufferAttribute", {
usage: DynamicDrawUsage,
attach: "attributes-cloudOpacity",
args: [opacities, 1]
})), /*#__PURE__*/React.createElement("cloudMaterial", {
key: material.name,
map: cloudTexture,
transparent: true,
depthWrite: false
}))));
});
const CloudInstance = /* @__PURE__ */React.forwardRef(({
opacity = 1,
speed = 0,
bounds = [5, 1, 1],
segments = 20,
color = '#ffffff',
fade = 10,
volume = 6,
smallestVolume = 0.25,
distribute = null,
growth = 4,
concentrate = 'inside',
seed = Math.random(),
...props
}, fref) => {
function random() {
const x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
}
const parent = React.useContext(context);
const ref = React.useRef(null);
const uuid = React.useId();
const clouds = React.useMemo(() => {
return [...new Array(segments)].map((_, index) => ({
segments,
bounds: new Vector3(1, 1, 1),
position: new Vector3(),
uuid,
index,
ref,
dist: 0,
matrix: new Matrix4(),
color: new Color(),
rotation: index * (Math.PI / segments)
}));
}, [segments, uuid]);
React.useLayoutEffect(() => {
clouds.forEach((cloud, index) => {
applyProps(cloud, {
volume,
color,
speed,
growth,
opacity,
fade,
bounds,
density: Math.max(0.5, random()),
rotationFactor: Math.max(0.2, 0.5 * random()) * speed
});
// Only distribute randomly if there are multiple segments
const distributed = distribute == null ? void 0 : distribute(cloud, index);
if (distributed || segments > 1) {
var _distributed$point;
cloud.position.copy(cloud.bounds).multiply((_distributed$point = distributed == null ? void 0 : distributed.point) !== null && _distributed$point !== void 0 ? _distributed$point : {
x: random() * 2 - 1,
y: random() * 2 - 1,
z: random() * 2 - 1
});
}
const xDiff = Math.abs(cloud.position.x);
const yDiff = Math.abs(cloud.position.y);
const zDiff = Math.abs(cloud.position.z);
const max = Math.max(xDiff, yDiff, zDiff);
cloud.length = 1;
if (xDiff === max) cloud.length -= xDiff / cloud.bounds.x;
if (yDiff === max) cloud.length -= yDiff / cloud.bounds.y;
if (zDiff === max) cloud.length -= zDiff / cloud.bounds.z;
cloud.volume = ((distributed == null ? void 0 : distributed.volume) !== undefined ? distributed.volume : Math.max(Math.max(0, smallestVolume), concentrate === 'random' ? random() : concentrate === 'inside' ? cloud.length : 1 - cloud.length)) * volume;
});
}, [concentrate, bounds, fade, color, opacity, growth, volume, seed, segments, speed]);
React.useLayoutEffect(() => {
const temp = clouds;
parent.current = [...parent.current, ...temp];
return () => {
parent.current = parent.current.filter(item => item.uuid !== uuid);
};
}, [clouds]);
React.useImperativeHandle(fref, () => ref.current, []);
return /*#__PURE__*/React.createElement("group", _extends({
ref: ref
}, props));
});
const Cloud = /* @__PURE__ */React.forwardRef((props, fref) => {
const parent = React.useContext(context);
if (parent) return /*#__PURE__*/React.createElement(CloudInstance, _extends({
ref: fref
}, props));
return /*#__PURE__*/React.createElement(Clouds, null, /*#__PURE__*/React.createElement(CloudInstance, _extends({
ref: fref
}, props)));
});
export { Cloud, CloudInstance, Clouds };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function n(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var u=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,u.get?u:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var c=u(e),a=n(t);exports.ComputedAttribute=({compute:e,name:t,...u})=>{const[n]=a.useState((()=>new r.BufferAttribute(new Float32Array(0),1))),o=a.useRef(null);return a.useLayoutEffect((()=>{if(o.current){var t;const r=null!==(t=o.current.parent)&&void 0!==t?t:o.current.__r3f.parent.object,u=e(r);o.current.copy(u)}}),[e]),a.createElement("primitive",c.default({ref:o,object:n,attach:`attributes-${t}`},u))};
+8
View File
@@ -0,0 +1,8 @@
import { ThreeElements } from '@react-three/fiber';
import * as React from 'react';
import { BufferAttribute, BufferGeometry } from 'three';
export type ComputedAttributeProps = Omit<ThreeElements['bufferAttribute'], 'args'> & {
compute: (geometry: BufferGeometry) => BufferAttribute;
name: string;
};
export declare const ComputedAttribute: ({ compute, name, ...props }: ComputedAttributeProps) => React.JSX.Element;
+33
View File
@@ -0,0 +1,33 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { BufferAttribute } from 'three';
/**
* Used exclusively as a child of a BufferGeometry.
* Computes the BufferAttribute by calling the `compute` function
* and attaches the attribute to the geometry.
*/
const ComputedAttribute = ({
compute,
name,
...props
}) => {
const [bufferAttribute] = React.useState(() => new BufferAttribute(new Float32Array(0), 1));
const primitive = React.useRef(null);
React.useLayoutEffect(() => {
if (primitive.current) {
var _ref;
// @ts-expect-error brittle
const parent = (_ref = primitive.current.parent) !== null && _ref !== void 0 ? _ref : primitive.current.__r3f.parent.object;
const attr = compute(parent);
primitive.current.copy(attr);
}
}, [compute]);
return /*#__PURE__*/React.createElement("primitive", _extends({
ref: primitive,
object: bufferAttribute,
attach: `attributes-${name}`
}, props));
};
export { ComputedAttribute };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("three"),a=require("@react-three/fiber"),n=require("three-stdlib");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var a=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,a.get?a:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var i=o(e),l=u(r),s=u(t);const c=l.forwardRef((({scale:e=10,frames:r=1/0,opacity:t=1,width:o=1,height:u=1,blur:c=1,near:d=0,far:f=10,resolution:h=512,smooth:m=!0,color:p="#000000",depthWrite:g=!1,renderOrder:v,...b},M)=>{const y=l.useRef(null),w=a.useThree((e=>e.scene)),T=a.useThree((e=>e.gl)),x=l.useRef(null);o*=Array.isArray(e)?e[0]:e||1,u*=Array.isArray(e)?e[1]:e||1;const[O,R,S,j,C,P,q]=l.useMemo((()=>{const e=new s.WebGLRenderTarget(h,h),r=new s.WebGLRenderTarget(h,h);r.texture.generateMipmaps=e.texture.generateMipmaps=!1;const t=new s.PlaneGeometry(o,u).rotateX(Math.PI/2),a=new s.Mesh(t),i=new s.MeshDepthMaterial;i.depthTest=i.depthWrite=!1,i.onBeforeCompile=e=>{e.uniforms={...e.uniforms,ucolor:{value:new s.Color(p)}},e.fragmentShader=e.fragmentShader.replace("void main() {","uniform vec3 ucolor;\n void main() {\n "),e.fragmentShader=e.fragmentShader.replace("vec4( vec3( 1.0 - fragCoordZ ), opacity );","vec4( ucolor * fragCoordZ * 2.0, ( 1.0 - fragCoordZ ) * 1.0 );")};const l=new s.ShaderMaterial(n.HorizontalBlurShader),c=new s.ShaderMaterial(n.VerticalBlurShader);return c.depthTest=l.depthTest=!1,[e,t,i,a,l,c,r]}),[h,o,u,e,p]),E=e=>{j.visible=!0,j.material=C,C.uniforms.tDiffuse.value=O.texture,C.uniforms.h.value=1*e/256,T.setRenderTarget(q),T.render(j,x.current),j.material=P,P.uniforms.tDiffuse.value=q.texture,P.uniforms.v.value=1*e/256,T.setRenderTarget(O),T.render(j,x.current),j.visible=!1};let W,k,A=0;return a.useFrame((()=>{x.current&&(r===1/0||A<r)&&(A++,W=w.background,k=w.overrideMaterial,y.current.visible=!1,w.background=null,w.overrideMaterial=S,T.setRenderTarget(O),T.render(w,x.current),E(c),m&&E(.4*c),T.setRenderTarget(null),y.current.visible=!0,w.overrideMaterial=k,w.background=W)})),l.useImperativeHandle(M,(()=>y.current),[]),l.createElement("group",i.default({"rotation-x":Math.PI/2},b,{ref:y}),l.createElement("mesh",{renderOrder:v,geometry:R,scale:[1,-1,1],rotation:[-Math.PI/2,0,0]},l.createElement("meshBasicMaterial",{transparent:!0,map:O.texture,opacity:t,depthWrite:g})),l.createElement("orthographicCamera",{ref:x,args:[-o/2,o/2,u/2,-u/2,d,f]}))}));exports.ContactShadows=c;
+18
View File
@@ -0,0 +1,18 @@
import * as THREE from 'three';
import { ThreeElements } from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type ContactShadowsProps = Omit<ThreeElements['group'], 'ref' | 'scale'> & {
opacity?: number;
width?: number;
height?: number;
blur?: number;
near?: number;
far?: number;
smooth?: boolean;
resolution?: number;
frames?: number;
scale?: number | [x: number, y: number];
color?: THREE.ColorRepresentation;
depthWrite?: boolean;
};
export declare const ContactShadows: ForwardRefComponent<ContactShadowsProps, THREE.Group>;
+114
View File
@@ -0,0 +1,114 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import * as THREE from 'three';
import { useThree, useFrame } from '@react-three/fiber';
import { HorizontalBlurShader, VerticalBlurShader } from 'three-stdlib';
const ContactShadows = /* @__PURE__ */React.forwardRef(({
scale = 10,
frames = Infinity,
opacity = 1,
width = 1,
height = 1,
blur = 1,
near = 0,
far = 10,
resolution = 512,
smooth = true,
color = '#000000',
depthWrite = false,
renderOrder,
...props
}, fref) => {
const ref = React.useRef(null);
const scene = useThree(state => state.scene);
const gl = useThree(state => state.gl);
const shadowCamera = React.useRef(null);
width = width * (Array.isArray(scale) ? scale[0] : scale || 1);
height = height * (Array.isArray(scale) ? scale[1] : scale || 1);
const [renderTarget, planeGeometry, depthMaterial, blurPlane, horizontalBlurMaterial, verticalBlurMaterial, renderTargetBlur] = React.useMemo(() => {
const renderTarget = new THREE.WebGLRenderTarget(resolution, resolution);
const renderTargetBlur = new THREE.WebGLRenderTarget(resolution, resolution);
renderTargetBlur.texture.generateMipmaps = renderTarget.texture.generateMipmaps = false;
const planeGeometry = new THREE.PlaneGeometry(width, height).rotateX(Math.PI / 2);
const blurPlane = new THREE.Mesh(planeGeometry);
const depthMaterial = new THREE.MeshDepthMaterial();
depthMaterial.depthTest = depthMaterial.depthWrite = false;
depthMaterial.onBeforeCompile = shader => {
shader.uniforms = {
...shader.uniforms,
ucolor: {
value: new THREE.Color(color)
}
};
shader.fragmentShader = shader.fragmentShader.replace(`void main() {`,
//
`uniform vec3 ucolor;
void main() {
`);
shader.fragmentShader = shader.fragmentShader.replace('vec4( vec3( 1.0 - fragCoordZ ), opacity );',
// Colorize the shadow, multiply by the falloff so that the center can remain darker
'vec4( ucolor * fragCoordZ * 2.0, ( 1.0 - fragCoordZ ) * 1.0 );');
};
const horizontalBlurMaterial = new THREE.ShaderMaterial(HorizontalBlurShader);
const verticalBlurMaterial = new THREE.ShaderMaterial(VerticalBlurShader);
verticalBlurMaterial.depthTest = horizontalBlurMaterial.depthTest = false;
return [renderTarget, planeGeometry, depthMaterial, blurPlane, horizontalBlurMaterial, verticalBlurMaterial, renderTargetBlur];
}, [resolution, width, height, scale, color]);
const blurShadows = blur => {
blurPlane.visible = true;
blurPlane.material = horizontalBlurMaterial;
horizontalBlurMaterial.uniforms.tDiffuse.value = renderTarget.texture;
horizontalBlurMaterial.uniforms.h.value = blur * 1 / 256;
gl.setRenderTarget(renderTargetBlur);
gl.render(blurPlane, shadowCamera.current);
blurPlane.material = verticalBlurMaterial;
verticalBlurMaterial.uniforms.tDiffuse.value = renderTargetBlur.texture;
verticalBlurMaterial.uniforms.v.value = blur * 1 / 256;
gl.setRenderTarget(renderTarget);
gl.render(blurPlane, shadowCamera.current);
blurPlane.visible = false;
};
let count = 0;
let initialBackground;
let initialOverrideMaterial;
useFrame(() => {
if (shadowCamera.current && (frames === Infinity || count < frames)) {
count++;
initialBackground = scene.background;
initialOverrideMaterial = scene.overrideMaterial;
ref.current.visible = false;
scene.background = null;
scene.overrideMaterial = depthMaterial;
gl.setRenderTarget(renderTarget);
gl.render(scene, shadowCamera.current);
blurShadows(blur);
if (smooth) blurShadows(blur * 0.4);
gl.setRenderTarget(null);
ref.current.visible = true;
scene.overrideMaterial = initialOverrideMaterial;
scene.background = initialBackground;
}
});
React.useImperativeHandle(fref, () => ref.current, []);
return /*#__PURE__*/React.createElement("group", _extends({
"rotation-x": Math.PI / 2
}, props, {
ref: ref
}), /*#__PURE__*/React.createElement("mesh", {
renderOrder: renderOrder,
geometry: planeGeometry,
scale: [1, -1, 1],
rotation: [-Math.PI / 2, 0, 0]
}, /*#__PURE__*/React.createElement("meshBasicMaterial", {
transparent: true,
map: renderTarget.texture,
opacity: opacity,
depthWrite: depthWrite
})), /*#__PURE__*/React.createElement("orthographicCamera", {
ref: shadowCamera,
args: [-width / 2, width / 2, height / 2, -height / 2, near, far]
}));
});
export { ContactShadows };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("three"),r=require("react"),t=require("@react-three/fiber");function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var n=u(e),a=u(r);function o({resolution:u=256,near:o=.1,far:c=1e3,envMap:s,fog:f}={}){const i=t.useThree((({gl:e})=>e)),l=t.useThree((({scene:e})=>e)),b=r.useMemo((()=>{const r=new e.WebGLCubeRenderTarget(u);return r.texture.type=e.HalfFloatType,r}),[u]);r.useEffect((()=>()=>{b.dispose()}),[b]);const p=r.useMemo((()=>new n.CubeCamera(o,c,b)),[o,c,b]);let d,g;const m=a.useCallback((()=>{d=l.fog,g=l.background,l.background=s||g,l.fog=f||d,p.update(i,l),l.fog=d,l.background=g}),[i,l,p]);return{fbo:b,camera:p,update:m}}exports.CubeCamera=function({children:e,frames:r=1/0,resolution:u,near:n,far:c,envMap:s,fog:f,...i}){const l=a.useRef(null),{fbo:b,camera:p,update:d}=o({resolution:u,near:n,far:c,envMap:s,fog:f});let g=0;return t.useFrame((()=>{l.current&&(r===1/0||g<r)&&(l.current.visible=!1,d(),l.current.visible=!0,g++)})),a.createElement("group",i,a.createElement("primitive",{object:p}),a.createElement("group",{ref:l},null==e?void 0:e(b.texture)))},exports.useCubeCamera=o;
+21
View File
@@ -0,0 +1,21 @@
import * as THREE from 'three';
import { Fog, FogExp2, Texture } from 'three';
import * as React from 'react';
import { ThreeElements } from '@react-three/fiber';
export type CubeCameraOptions = {
resolution?: number;
near?: number;
far?: number;
envMap?: THREE.Texture;
fog?: Fog | FogExp2;
};
export declare function useCubeCamera({ resolution, near, far, envMap, fog }?: CubeCameraOptions): {
fbo: THREE.WebGLCubeRenderTarget;
camera: THREE.CubeCamera;
update: () => void;
};
export type CubeCameraProps = Omit<ThreeElements['group'], 'children'> & {
children?: (tex: Texture) => React.ReactNode;
frames?: number;
} & CubeCameraOptions;
export declare function CubeCamera({ children, frames, resolution, near, far, envMap, fog, ...props }: CubeCameraProps): React.JSX.Element;
+86
View File
@@ -0,0 +1,86 @@
import * as THREE from 'three';
import { WebGLCubeRenderTarget, HalfFloatType } from 'three';
import * as React from 'react';
import { useMemo, useEffect } from 'react';
import { useThree, useFrame } from '@react-three/fiber';
function useCubeCamera({
resolution = 256,
near = 0.1,
far = 1000,
envMap,
fog
} = {}) {
const gl = useThree(({
gl
}) => gl);
const scene = useThree(({
scene
}) => scene);
const fbo = useMemo(() => {
const fbo = new WebGLCubeRenderTarget(resolution);
fbo.texture.type = HalfFloatType;
return fbo;
}, [resolution]);
useEffect(() => {
return () => {
fbo.dispose();
};
}, [fbo]);
const camera = useMemo(() => new THREE.CubeCamera(near, far, fbo), [near, far, fbo]);
let originalFog;
let originalBackground;
const update = React.useCallback(() => {
originalFog = scene.fog;
originalBackground = scene.background;
scene.background = envMap || originalBackground;
scene.fog = fog || originalFog;
camera.update(gl, scene);
scene.fog = originalFog;
scene.background = originalBackground;
}, [gl, scene, camera]);
return {
fbo,
camera,
update
};
}
function CubeCamera({
children,
frames = Infinity,
resolution,
near,
far,
envMap,
fog,
...props
}) {
const ref = React.useRef(null);
const {
fbo,
camera,
update
} = useCubeCamera({
resolution,
near,
far,
envMap,
fog
});
let count = 0;
useFrame(() => {
if (ref.current && (frames === Infinity || count < frames)) {
ref.current.visible = false;
update();
ref.current.visible = true;
count++;
}
});
return /*#__PURE__*/React.createElement("group", props, /*#__PURE__*/React.createElement("primitive", {
object: camera
}), /*#__PURE__*/React.createElement("group", {
ref: ref
}, children == null ? void 0 : children(fbo.texture)));
}
export { CubeCamera, useCubeCamera };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("three"),t=require("@react-three/fiber");function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var n=u(e);function a(e,{path:u}){const[n]=t.useLoader(r.CubeTextureLoader,[e],(e=>e.setPath(u)));return n}a.preload=(e,{path:u})=>t.useLoader.preload(r.CubeTextureLoader,[e],(e=>e.setPath(u))),exports.CubeTexture=function({children:e,files:r,...t}){const u=a(r,{...t});return n.createElement(n.Fragment,null,null==e?void 0:e(u))},exports.useCubeTexture=a;
+14
View File
@@ -0,0 +1,14 @@
import * as React from 'react';
import { CubeTexture as _CubeTexture, Texture } from 'three';
export type CubeTextureOptions = {
path: string;
};
export declare function useCubeTexture(files: string[], { path }: CubeTextureOptions): _CubeTexture;
export declare namespace useCubeTexture {
var preload: (files: string[], { path }: CubeTextureOptions) => void;
}
export type CubeTextureProps = CubeTextureOptions & {
children?: (tex: Texture) => React.ReactNode;
files: Parameters<typeof useCubeTexture>[0];
};
export declare function CubeTexture({ children, files, ...options }: CubeTextureProps): React.JSX.Element;
+25
View File
@@ -0,0 +1,25 @@
import * as React from 'react';
import { CubeTextureLoader } from 'three';
import { useLoader } from '@react-three/fiber';
function useCubeTexture(files, {
path
}) {
const [cubeTexture] = useLoader(CubeTextureLoader, [files], loader => loader.setPath(path));
return cubeTexture;
}
useCubeTexture.preload = (files, {
path
}) => useLoader.preload(CubeTextureLoader, [files], loader => loader.setPath(path));
function CubeTexture({
children,
files,
...options
}) {
const texture = useCubeTexture(files, {
...options
});
return /*#__PURE__*/React.createElement(React.Fragment, null, children == null ? void 0 : children(texture));
}
export { CubeTexture, useCubeTexture };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("three"),n=require("./Line.cjs.js");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function i(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}require("@react-three/fiber"),require("three-stdlib");var o=c(e),u=i(r);const s=u.forwardRef((function({start:e,end:r,midA:c,midB:i,segments:s=20,...f},a){const d=u.useMemo((()=>{const n=e instanceof t.Vector3?e:new t.Vector3(...e),o=r instanceof t.Vector3?r:new t.Vector3(...r),u=c instanceof t.Vector3?c:new t.Vector3(...c),f=i instanceof t.Vector3?i:new t.Vector3(...i);return new t.CubicBezierCurve3(n,u,f,o).getPoints(s)}),[e,r,c,i,s]);return u.createElement(n.Line,o.default({ref:a,points:d},f))}));exports.CubicBezierLine=s;
+12
View File
@@ -0,0 +1,12 @@
import { Vector3 } from 'three';
import { Line2 } from 'three-stdlib';
import { LineProps } from './Line';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type CubicBezierLineProps = Omit<LineProps, 'points' | 'ref'> & {
start: Vector3 | [number, number, number];
end: Vector3 | [number, number, number];
midA: Vector3 | [number, number, number];
midB: Vector3 | [number, number, number];
segments?: number;
};
export declare const CubicBezierLine: ForwardRefComponent<CubicBezierLineProps, Line2>;
+28
View File
@@ -0,0 +1,28 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { Vector3, CubicBezierCurve3 } from 'three';
import { Line } from './Line.js';
const CubicBezierLine = /* @__PURE__ */React.forwardRef(function CubicBezierLine({
start,
end,
midA,
midB,
segments = 20,
...rest
}, ref) {
const points = React.useMemo(() => {
const startV = start instanceof Vector3 ? start : new Vector3(...start);
const endV = end instanceof Vector3 ? end : new Vector3(...end);
const midAV = midA instanceof Vector3 ? midA : new Vector3(...midA);
const midBV = midB instanceof Vector3 ? midB : new Vector3(...midB);
const interpolatedV = new CubicBezierCurve3(startV, midAV, midBV, endV).getPoints(segments);
return interpolatedV;
}, [start, end, midA, midB, segments]);
return /*#__PURE__*/React.createElement(Line, _extends({
ref: ref,
points: points
}, rest));
});
export { CubicBezierLine };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("three"),t=require("@react-three/fiber"),u=require("three-stdlib");function n(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var u=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,u.get?u:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var c=n(e),a=n(r);const i=c.forwardRef((({children:e,curve:r},n)=>{const[i]=c.useState((()=>new a.Scene)),[l,o]=c.useState(),f=c.useRef(null);return c.useLayoutEffect((()=>{f.current=new u.Flow(i.children[0]),o(f.current.object3D)}),[e]),c.useEffect((()=>{var e;r&&(null==(e=f.current)||e.updateCurve(0,r))}),[r]),c.useImperativeHandle(n,(()=>f.current)),c.createElement(c.Fragment,null,t.createPortal(e,i),l&&c.createElement("primitive",{object:l}))}));exports.CurveModifier=i;
+11
View File
@@ -0,0 +1,11 @@
import * as React from 'react';
import * as THREE from 'three';
import { ThreeElements } from '@react-three/fiber';
import { Flow } from 'three-stdlib';
import { ForwardRefComponent } from '../helpers/ts-utils';
export interface CurveModifierProps {
children: React.ReactElement<ThreeElements['mesh']>;
curve?: THREE.Curve<THREE.Vector3>;
}
export type CurveModifierRef = Flow;
export declare const CurveModifier: ForwardRefComponent<CurveModifierProps, CurveModifierRef>;
+27
View File
@@ -0,0 +1,27 @@
import * as React from 'react';
import * as THREE from 'three';
import { createPortal } from '@react-three/fiber';
import { Flow } from 'three-stdlib';
const CurveModifier = /* @__PURE__ */React.forwardRef(({
children,
curve
}, ref) => {
const [scene] = React.useState(() => new THREE.Scene());
const [obj, set] = React.useState();
const modifier = React.useRef(null);
React.useLayoutEffect(() => {
modifier.current = new Flow(scene.children[0]);
set(modifier.current.object3D);
}, [children]);
React.useEffect(() => {
var _modifier$current;
if (curve) (_modifier$current = modifier.current) == null || _modifier$current.updateCurve(0, curve);
}, [curve]);
React.useImperativeHandle(ref, () => modifier.current);
return /*#__PURE__*/React.createElement(React.Fragment, null, createPortal(children, scene), obj && /*#__PURE__*/React.createElement("primitive", {
object: obj
}));
});
export { CurveModifier };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three"),o=require("@react-three/fiber"),n=require("three-stdlib");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var o=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,o.get?o:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var c=a(e),s=i(t),u=i(r);function l(e=[0,0,0]){return function(e){return Array.isArray(e)}(e)?e:e instanceof u.Vector3||e instanceof u.Euler?[e.x,e.y,e.z]:[e,e,e]}const p=s.forwardRef((function({debug:e,depthTest:t=!1,polygonOffsetFactor:r=-10,map:a,mesh:i,children:p,position:f,rotation:m,scale:y,...d},b){const h=s.useRef(null);s.useImperativeHandle(b,(()=>h.current));const g=s.useRef(null),w=s.useRef({position:new u.Vector3,rotation:new u.Euler,scale:new u.Vector3(1,1,1)});return s.useLayoutEffect((()=>{const e=(null==i?void 0:i.current)||h.current.parent,t=h.current;if(!(e instanceof u.Mesh))throw new Error('Decal must have a Mesh as parent or specify its "mesh" prop');if(e){o.applyProps(w.current,{position:f,scale:y});const r=e.matrixWorld.clone();if(e.matrixWorld.identity(),m&&"number"!=typeof m)o.applyProps(w.current,{rotation:m});else{const t=new u.Object3D;t.position.copy(w.current.position);const r=e.geometry.attributes.position.array;void 0===e.geometry.attributes.normal&&e.geometry.computeVertexNormals();const n=e.geometry.attributes.normal.array;let a=1/0,i=new u.Vector3;const c=t.position.x,s=t.position.y,l=t.position.z,p=r.length;let f=-1;for(let e=0;e<p;e+=3){const t=r[e]-c,o=r[e+1]-s,n=r[e+2]-l,i=t*t+o*o+n*n;i<a&&(a=i,f=e)}i.fromArray(n,f),t.lookAt(t.position.clone().add(i)),t.rotateZ(Math.PI),t.rotateY(Math.PI),"number"==typeof m&&t.rotateZ(m),o.applyProps(w.current,{rotation:t.rotation})}return g.current&&o.applyProps(g.current,w.current),t.geometry=new n.DecalGeometry(e,w.current.position,w.current.rotation,w.current.scale),e.matrixWorld=r,()=>{t.geometry.dispose()}}}),[i,...l(f),...l(y),...l(m)]),s.useLayoutEffect((()=>{g.current&&g.current.traverse((e=>e.raycast=()=>null))}),[e]),s.createElement("mesh",c.default({ref:h,"material-transparent":!0,"material-polygonOffset":!0,"material-polygonOffsetFactor":r,"material-depthTest":t,"material-map":a},d),p,e&&s.createElement("mesh",{ref:g},s.createElement("boxGeometry",null),s.createElement("meshNormalMaterial",{wireframe:!0}),s.createElement("axesHelper",null)))}));exports.Decal=p;
+16
View File
@@ -0,0 +1,16 @@
import * as React from 'react';
import * as THREE from 'three';
import * as FIBER from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type DecalProps = Omit<FIBER.ThreeElements['mesh'], 'ref' | 'children'> & {
debug?: boolean;
mesh?: React.RefObject<THREE.Mesh>;
position?: FIBER.Vector3;
rotation?: FIBER.Euler | number;
scale?: FIBER.Vector3;
map?: THREE.Texture;
children?: React.ReactNode;
polygonOffsetFactor?: number;
depthTest?: boolean;
};
export declare const Decal: ForwardRefComponent<DecalProps, THREE.Mesh>;
+128
View File
@@ -0,0 +1,128 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import * as THREE from 'three';
import { applyProps } from '@react-three/fiber';
import { DecalGeometry } from 'three-stdlib';
function isArray(vec) {
return Array.isArray(vec);
}
function vecToArray(vec = [0, 0, 0]) {
if (isArray(vec)) {
return vec;
} else if (vec instanceof THREE.Vector3 || vec instanceof THREE.Euler) {
return [vec.x, vec.y, vec.z];
} else {
return [vec, vec, vec];
}
}
const Decal = /* @__PURE__ */React.forwardRef(function Decal({
debug,
depthTest = false,
polygonOffsetFactor = -10,
map,
mesh,
children,
position,
rotation,
scale,
...props
}, forwardRef) {
const ref = React.useRef(null);
React.useImperativeHandle(forwardRef, () => ref.current);
const helper = React.useRef(null);
const state = React.useRef({
position: new THREE.Vector3(),
rotation: new THREE.Euler(),
scale: new THREE.Vector3(1, 1, 1)
});
React.useLayoutEffect(() => {
const parent = (mesh == null ? void 0 : mesh.current) || ref.current.parent;
const target = ref.current;
if (!(parent instanceof THREE.Mesh)) {
throw new Error('Decal must have a Mesh as parent or specify its "mesh" prop');
}
if (parent) {
applyProps(state.current, {
position,
scale
});
// Zero out the parents matrix world for this operation
const matrixWorld = parent.matrixWorld.clone();
parent.matrixWorld.identity();
if (!rotation || typeof rotation === 'number') {
const o = new THREE.Object3D();
o.position.copy(state.current.position);
// Thanks https://x.com/N8Programs !
const vertices = parent.geometry.attributes.position.array;
if (parent.geometry.attributes.normal === undefined) parent.geometry.computeVertexNormals();
const normal = parent.geometry.attributes.normal.array;
let distance = Infinity;
let closestNormal = new THREE.Vector3();
const ox = o.position.x;
const oy = o.position.y;
const oz = o.position.z;
const vLength = vertices.length;
let chosenIdx = -1;
for (let i = 0; i < vLength; i += 3) {
const x = vertices[i];
const y = vertices[i + 1];
const z = vertices[i + 2];
const xDiff = x - ox;
const yDiff = y - oy;
const zDiff = z - oz;
const distSquared = xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
if (distSquared < distance) {
distance = distSquared;
chosenIdx = i;
}
}
closestNormal.fromArray(normal, chosenIdx);
// Get vector tangent to normal
o.lookAt(o.position.clone().add(closestNormal));
o.rotateZ(Math.PI);
o.rotateY(Math.PI);
if (typeof rotation === 'number') o.rotateZ(rotation);
applyProps(state.current, {
rotation: o.rotation
});
} else {
applyProps(state.current, {
rotation
});
}
if (helper.current) {
applyProps(helper.current, state.current);
}
target.geometry = new DecalGeometry(parent, state.current.position, state.current.rotation, state.current.scale);
// Reset parents matix-world
parent.matrixWorld = matrixWorld;
return () => {
target.geometry.dispose();
};
}
}, [mesh, ...vecToArray(position), ...vecToArray(scale), ...vecToArray(rotation)]);
React.useLayoutEffect(() => {
if (helper.current) {
// Prevent the helpers from blocking rays
helper.current.traverse(child => child.raycast = () => null);
}
}, [debug]);
return /*#__PURE__*/React.createElement("mesh", _extends({
ref: ref,
"material-transparent": true,
"material-polygonOffset": true,
"material-polygonOffsetFactor": polygonOffsetFactor,
"material-depthTest": depthTest,
"material-map": map
}, props), children, debug && /*#__PURE__*/React.createElement("mesh", {
ref: helper
}, /*#__PURE__*/React.createElement("boxGeometry", null), /*#__PURE__*/React.createElement("meshNormalMaterial", {
wireframe: true
}), /*#__PURE__*/React.createElement("axesHelper", null)));
});
export { Decal };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("@react-three/fiber");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var c=n(e),a=u(r);const s=a.forwardRef((({children:e,hysteresis:r=0,distances:n,...u},s)=>{const l=a.useRef(null);return a.useImperativeHandle(s,(()=>l.current),[]),a.useLayoutEffect((()=>{const{current:e}=l;e.levels.length=0,e.children.forEach(((t,u)=>e.levels.push({object:t,hysteresis:r,distance:n[u]})))})),t.useFrame((e=>{var r;return null==(r=l.current)?void 0:r.update(e.camera)})),a.createElement("lOD",c.default({ref:l},u),e)}));exports.Detailed=s;
+10
View File
@@ -0,0 +1,10 @@
import * as React from 'react';
import { LOD, Object3D } from 'three';
import { ThreeElements } from '@react-three/fiber';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type DetailedProps = Omit<ThreeElements['lOD'], 'ref'> & {
children: React.ReactElement<Object3D>[];
hysteresis?: number;
distances: number[];
};
export declare const Detailed: ForwardRefComponent<DetailedProps, LOD>;
+33
View File
@@ -0,0 +1,33 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { useFrame } from '@react-three/fiber';
const Detailed = /* @__PURE__ */React.forwardRef(({
children,
hysteresis = 0,
distances,
...props
}, ref) => {
const lodRef = React.useRef(null);
React.useImperativeHandle(ref, () => lodRef.current, []);
React.useLayoutEffect(() => {
const {
current: lod
} = lodRef;
lod.levels.length = 0;
lod.children.forEach((object, index) => lod.levels.push({
object,
hysteresis,
distance: distances[index]
}));
});
useFrame(state => {
var _lodRef$current;
return (_lodRef$current = lodRef.current) == null ? void 0 : _lodRef$current.update(state.camera);
});
return /*#__PURE__*/React.createElement("lOD", _extends({
ref: lodRef
}, props), children);
});
export { Detailed };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("detect-gpu"),r=require("suspend-react");function n(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var u=n(e);const c=e=>r.suspend((()=>t.getGPUTier(e)),["useDetectGPU"]);exports.DetectGPU=function({children:e,...t}){const r=c(t);return u.createElement(u.Fragment,null,null==e?void 0:e(r))},exports.useDetectGPU=c;
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
import { GetGPUTier } from 'detect-gpu';
export declare const useDetectGPU: (props?: GetGPUTier) => import("detect-gpu").TierResult;
export type DetectGPUProps = {
children?: (result: ReturnType<typeof useDetectGPU>) => React.ReactNode;
} & Parameters<typeof useDetectGPU>[0];
export declare function DetectGPU({ children, ...options }: DetectGPUProps): React.JSX.Element;
+14
View File
@@ -0,0 +1,14 @@
import * as React from 'react';
import { getGPUTier } from 'detect-gpu';
import { suspend } from 'suspend-react';
const useDetectGPU = props => suspend(() => getGPUTier(props), ['useDetectGPU']);
function DetectGPU({
children,
...options
}) {
const result = useDetectGPU(options);
return /*#__PURE__*/React.createElement(React.Fragment, null, children == null ? void 0 : children(result));
}
export { DetectGPU, useDetectGPU };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("@react-three/fiber"),r=require("react"),n=require("three-stdlib");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function o(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var c=u(e),i=o(r);const l=i.forwardRef(((e,r)=>{const{camera:u,onChange:o,makeDefault:l,...s}=e,a=t.useThree((e=>e.camera)),f=t.useThree((e=>e.invalidate)),d=t.useThree((e=>e.get)),v=t.useThree((e=>e.set)),b=u||a,h=i.useMemo((()=>new n.DeviceOrientationControls(b)),[b]);return i.useEffect((()=>{const e=e=>{f(),o&&o(e)};return null==h||null==h.addEventListener||h.addEventListener("change",e),()=>null==h||null==h.removeEventListener?void 0:h.removeEventListener("change",e)}),[o,h,f]),t.useFrame((()=>null==h?void 0:h.update()),-1),i.useEffect((()=>{const e=h;return null==e||e.connect(),()=>null==e?void 0:e.dispose()}),[h]),i.useEffect((()=>{if(l){const e=d().controls;return v({controls:h}),()=>v({controls:e})}}),[l,h]),h?i.createElement("primitive",c.default({ref:r,object:h},s)):null}));exports.DeviceOrientationControls=l;
+10
View File
@@ -0,0 +1,10 @@
import { ThreeElement } from '@react-three/fiber';
import * as THREE from 'three';
import { DeviceOrientationControls as DeviceOrientationControlsImp } from 'three-stdlib';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type DeviceOrientationControlsProps = Omit<ThreeElement<typeof DeviceOrientationControlsImp>, 'ref' | 'args'> & {
camera?: THREE.Camera;
onChange?: (e?: THREE.Event) => void;
makeDefault?: boolean;
};
export declare const DeviceOrientationControls: ForwardRefComponent<DeviceOrientationControlsProps, DeviceOrientationControlsImp>;
+51
View File
@@ -0,0 +1,51 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import { useThree, useFrame } from '@react-three/fiber';
import * as React from 'react';
import { DeviceOrientationControls as DeviceOrientationControls$1 } from 'three-stdlib';
const DeviceOrientationControls = /* @__PURE__ */React.forwardRef((props, ref) => {
const {
camera,
onChange,
makeDefault,
...rest
} = props;
const defaultCamera = useThree(state => state.camera);
const invalidate = useThree(state => state.invalidate);
const get = useThree(state => state.get);
const set = useThree(state => state.set);
const explCamera = camera || defaultCamera;
const controls = React.useMemo(() => new DeviceOrientationControls$1(explCamera), [explCamera]);
React.useEffect(() => {
const callback = e => {
invalidate();
if (onChange) onChange(e);
};
controls == null || controls.addEventListener == null || controls.addEventListener('change', callback);
return () => controls == null || controls.removeEventListener == null ? void 0 : controls.removeEventListener('change', callback);
}, [onChange, controls, invalidate]);
useFrame(() => controls == null ? void 0 : controls.update(), -1);
React.useEffect(() => {
const current = controls;
current == null || current.connect();
return () => current == null ? void 0 : current.dispose();
}, [controls]);
React.useEffect(() => {
if (makeDefault) {
const old = get().controls;
// @ts-ignore https://github.com/three-types/three-ts-types/pull/1398
set({
controls
});
return () => set({
controls: old
});
}
}, [makeDefault, controls]);
return controls ? /*#__PURE__*/React.createElement("primitive", _extends({
ref: ref,
object: controls
}, rest)) : null;
});
export { DeviceOrientationControls };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),t=require("react"),r=require("three"),n=require("./Line.cjs.js");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function s(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}require("@react-three/fiber"),require("three-stdlib");var c=u(e),i=s(t),o=s(r);const a=i.forwardRef((({threshold:e=15,geometry:t,...r},u)=>{const s=i.useRef(null);i.useImperativeHandle(u,(()=>s.current),[]);const a=i.useMemo((()=>[0,0,0,1,0,0]),[]),l=i.useRef(null),f=i.useRef(null);return i.useLayoutEffect((()=>{const r=s.current.parent,n=null!=t?t:null==r?void 0:r.geometry;if(!n)return;if(l.current===n&&f.current===e)return;l.current=n,f.current=e;const u=new o.EdgesGeometry(n,e).attributes.position.array;s.current.geometry.setPositions(u),s.current.geometry.attributes.instanceStart.needsUpdate=!0,s.current.geometry.attributes.instanceEnd.needsUpdate=!0,s.current.computeLineDistances()})),i.createElement(n.Line,c.default({segments:!0,points:a,ref:s,raycast:()=>null},r))}));exports.Edges=a;
+13
View File
@@ -0,0 +1,13 @@
import * as THREE from 'three';
import { ThreeElement, type ThreeElements } from '@react-three/fiber';
import { LineSegmentsGeometry, LineMaterial, LineMaterialParameters, Line2 } from 'three-stdlib';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type EdgesRef = THREE.Mesh<LineSegmentsGeometry, LineMaterial>;
export type EdgesProps = Partial<ThreeElements['mesh']> & {
threshold?: number;
lineWidth?: number;
} & Omit<LineMaterialParameters, 'vertexColors' | 'color'> & Omit<ThreeElement<typeof Line2>, 'args' | 'geometry'> & Omit<ThreeElement<typeof LineMaterial>, 'color' | 'vertexColors' | 'args'> & {
geometry?: THREE.BufferGeometry;
color?: THREE.ColorRepresentation;
};
export declare const Edges: ForwardRefComponent<EdgesProps, EdgesRef>;
+38
View File
@@ -0,0 +1,38 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import * as THREE from 'three';
import { Line } from './Line.js';
const Edges = /* @__PURE__ */React.forwardRef(({
threshold = 15,
geometry: explicitGeometry,
...props
}, fref) => {
const ref = React.useRef(null);
React.useImperativeHandle(fref, () => ref.current, []);
const tmpPoints = React.useMemo(() => [0, 0, 0, 1, 0, 0], []);
const memoizedGeometry = React.useRef(null);
const memoizedThreshold = React.useRef(null);
React.useLayoutEffect(() => {
const parent = ref.current.parent;
const geometry = explicitGeometry !== null && explicitGeometry !== void 0 ? explicitGeometry : parent == null ? void 0 : parent.geometry;
if (!geometry) return;
const cached = memoizedGeometry.current === geometry && memoizedThreshold.current === threshold;
if (cached) return;
memoizedGeometry.current = geometry;
memoizedThreshold.current = threshold;
const points = new THREE.EdgesGeometry(geometry, threshold).attributes.position.array;
ref.current.geometry.setPositions(points);
ref.current.geometry.attributes.instanceStart.needsUpdate = true;
ref.current.geometry.attributes.instanceEnd.needsUpdate = true;
ref.current.computeLineDistances();
});
return /*#__PURE__*/React.createElement(Line, _extends({
segments: true,
points: tmpPoints,
ref: ref,
raycast: () => null
}, props));
});
export { Edges };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),r=require("react"),t=require("three"),a=require("@react-three/fiber"),n=require("three-stdlib");function s(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function u(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var a=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,a.get?a:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}var c=s(e),l=u(r);const o=l.forwardRef((({children:e,multisamping:r=8,renderIndex:s=1,disableRender:u,disableGamma:o,disableRenderPass:i,depthBuffer:d=!0,stencilBuffer:f=!1,anisotropy:p=1,colorSpace:h,type:m,...b},g)=>{l.useMemo((()=>a.extend({EffectComposer:n.EffectComposer,RenderPass:n.RenderPass,ShaderPass:n.ShaderPass})),[]);const y=l.useRef(null);l.useImperativeHandle(g,(()=>y.current),[]);const{scene:v,camera:E,gl:P,size:x,viewport:R}=a.useThree(),[w]=l.useState((()=>{const e=new t.WebGLRenderTarget(x.width,x.height,{type:m||t.HalfFloatType,format:t.RGBAFormat,depthBuffer:d,stencilBuffer:f,anisotropy:p});return m===t.UnsignedByteType&&null!=h&&(e.texture.colorSpace=h),e.samples=r,e}));l.useEffect((()=>{var e,r;null==(e=y.current)||e.setSize(x.width,x.height),null==(r=y.current)||r.setPixelRatio(R.dpr)}),[P,x,R.dpr]),a.useFrame((()=>{var e;u||null==(e=y.current)||e.render()}),s);const j=[];return i||j.push(l.createElement("renderPass",{key:"renderpass",attach:`passes-${j.length}`,args:[v,E]})),o||j.push(l.createElement("shaderPass",{attach:`passes-${j.length}`,key:"gammapass",args:[n.GammaCorrectionShader]})),l.Children.forEach(e,(e=>{e&&j.push(l.cloneElement(e,{key:j.length,attach:`passes-${j.length}`}))})),l.createElement("effectComposer",c.default({ref:y,args:[P,w]},b),j)}));exports.Effects=o,exports.isWebGL2Available=()=>{try{var e=document.createElement("canvas");return!(!window.WebGL2RenderingContext||!e.getContext("webgl2"))}catch(e){return!1}};
+25
View File
@@ -0,0 +1,25 @@
import { TextureDataType, ColorSpace } from 'three';
import { ThreeElement, ThreeElements } from '@react-three/fiber';
import { EffectComposer, RenderPass, ShaderPass } from 'three-stdlib';
import { ForwardRefComponent } from '../helpers/ts-utils';
export type EffectsProps = Omit<ThreeElements['effectComposer'], 'ref' | 'args'> & {
multisamping?: number;
colorSpace?: ColorSpace;
type?: TextureDataType;
renderIndex?: number;
disableGamma?: boolean;
disableRenderPass?: boolean;
disableRender?: boolean;
depthBuffer?: boolean;
stencilBuffer?: boolean;
anisotropy?: number;
};
declare module '@react-three/fiber' {
interface ThreeElements {
effectComposer: ThreeElement<typeof EffectComposer>;
renderPass: ThreeElement<typeof RenderPass>;
shaderPass: ThreeElement<typeof ShaderPass>;
}
}
export declare const isWebGL2Available: () => boolean;
export declare const Effects: ForwardRefComponent<EffectsProps, EffectComposer>;
+91
View File
@@ -0,0 +1,91 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { WebGLRenderTarget, HalfFloatType, RGBAFormat, UnsignedByteType } from 'three';
import { extend, useThree, useFrame } from '@react-three/fiber';
import { EffectComposer, RenderPass, ShaderPass, GammaCorrectionShader } from 'three-stdlib';
const isWebGL2Available = () => {
try {
var canvas = document.createElement('canvas');
return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2'));
} catch (e) {
return false;
}
};
const Effects = /* @__PURE__ */React.forwardRef(({
children,
multisamping = 8,
renderIndex = 1,
disableRender,
disableGamma,
disableRenderPass,
depthBuffer = true,
stencilBuffer = false,
anisotropy = 1,
colorSpace,
type,
...props
}, ref) => {
React.useMemo(() => extend({
EffectComposer,
RenderPass,
ShaderPass
}), []);
const composer = React.useRef(null);
React.useImperativeHandle(ref, () => composer.current, []);
const {
scene,
camera,
gl,
size,
viewport
} = useThree();
const [target] = React.useState(() => {
const t = new WebGLRenderTarget(size.width, size.height, {
type: type || HalfFloatType,
format: RGBAFormat,
depthBuffer,
stencilBuffer,
anisotropy
});
// sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129
if (type === UnsignedByteType && colorSpace != null) {
t.texture.colorSpace = colorSpace;
}
t.samples = multisamping;
return t;
});
React.useEffect(() => {
var _composer$current, _composer$current2;
(_composer$current = composer.current) == null || _composer$current.setSize(size.width, size.height);
(_composer$current2 = composer.current) == null || _composer$current2.setPixelRatio(viewport.dpr);
}, [gl, size, viewport.dpr]);
useFrame(() => {
var _composer$current3;
if (!disableRender) (_composer$current3 = composer.current) == null || _composer$current3.render();
}, renderIndex);
const passes = [];
if (!disableRenderPass) passes.push(/*#__PURE__*/React.createElement("renderPass", {
key: "renderpass",
attach: `passes-${passes.length}`,
args: [scene, camera]
}));
if (!disableGamma) passes.push(/*#__PURE__*/React.createElement("shaderPass", {
attach: `passes-${passes.length}`,
key: "gammapass",
args: [GammaCorrectionShader]
}));
React.Children.forEach(children, el => {
el && passes.push(/*#__PURE__*/React.cloneElement(el, {
key: passes.length,
attach: `passes-${passes.length}`
}));
});
return /*#__PURE__*/React.createElement("effectComposer", _extends({
ref: composer,
args: [gl, target]
}, props), passes);
});
export { Effects, isWebGL2Available };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@babel/runtime/helpers/extends"),n=require("react"),t=require("@react-three/fiber"),r=require("three"),o=require("three-stdlib"),u=require("./useEnvironment.cjs.js");function a(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}function i(e){if(e&&e.__esModule)return e;var n=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(n,t,r.get?r:{enumerable:!0,get:function(){return e[t]}})}})),n.default=e,Object.freeze(n)}require("@monogrid/gainmap-js"),require("../helpers/environment-assets.cjs.js");var s=a(e),c=i(n);function l(e,n,r,o,u={}){var a,i,s,c;u={backgroundBlurriness:0,backgroundIntensity:1,backgroundRotation:[0,0,0],environmentIntensity:1,environmentRotation:[0,0,0],...u};const l=(e=>{return(n=e).current&&n.current.isScene?e.current:e;var n})(n||r),d=l.background,m=l.environment,g={backgroundBlurriness:l.backgroundBlurriness,backgroundIntensity:l.backgroundIntensity,backgroundRotation:null!==(a=null==(i=l.backgroundRotation)||null==i.clone?void 0:i.clone())&&void 0!==a?a:[0,0,0],environmentIntensity:l.environmentIntensity,environmentRotation:null!==(s=null==(c=l.environmentRotation)||null==c.clone?void 0:c.clone())&&void 0!==s?s:[0,0,0]};return"only"!==e&&(l.environment=o),e&&(l.background=o),t.applyProps(l,u),()=>{"only"!==e&&(l.environment=m),e&&(l.background=d),t.applyProps(l,g)}}function d({scene:e,background:n=!1,map:r,...o}){const u=t.useThree((e=>e.scene));return c.useLayoutEffect((()=>{if(r)return l(n,e,u,r,o)})),null}function m({background:e=!1,scene:n,blur:r,backgroundBlurriness:o,backgroundIntensity:a,backgroundRotation:i,environmentIntensity:s,environmentRotation:d,...m}){const g=u.useEnvironment(m),b=t.useThree((e=>e.scene));return c.useLayoutEffect((()=>l(e,n,b,g,{backgroundBlurriness:null!=r?r:o,backgroundIntensity:a,backgroundRotation:i,environmentIntensity:s,environmentRotation:d}))),c.useEffect((()=>()=>{g.dispose()}),[g]),null}function g({children:e,near:n=.1,far:o=1e3,resolution:u=256,frames:a=1,map:i,background:s=!1,blur:g,backgroundBlurriness:b,backgroundIntensity:f,backgroundRotation:v,environmentIntensity:p,environmentRotation:k,scene:E,files:y,path:h,preset:I,extensions:R}){const j=t.useThree((e=>e.gl)),x=t.useThree((e=>e.scene)),P=c.useRef(null),[C]=c.useState((()=>new r.Scene)),q=c.useMemo((()=>{const e=new r.WebGLCubeRenderTarget(u);return e.texture.type=r.HalfFloatType,e}),[u]);c.useEffect((()=>()=>{q.dispose()}),[q]),c.useLayoutEffect((()=>{if(1===a){const e=j.autoClear;j.autoClear=!0,P.current.update(j,C),j.autoClear=e}return l(s,E,x,q.texture,{backgroundBlurriness:null!=g?g:b,backgroundIntensity:f,backgroundRotation:v,environmentIntensity:p,environmentRotation:k})}),[e,C,q.texture,E,x,s,a,j]);let B=1;return t.useFrame((()=>{if(a===1/0||B<a){const e=j.autoClear;j.autoClear=!0,P.current.update(j,C),j.autoClear=e,B++}})),c.createElement(c.Fragment,null,t.createPortal(c.createElement(c.Fragment,null,e,c.createElement("cubeCamera",{ref:P,args:[n,o,q]}),y||I?c.createElement(m,{background:!0,files:y,preset:I,path:h,extensions:R}):i?c.createElement(d,{background:!0,map:i,extensions:R}):null),C))}function b(e){var n,r,a,i;const l=u.useEnvironment(e),m=e.map||l;c.useMemo((()=>t.extend({GroundProjectedEnvImpl:o.GroundProjectedEnv})),[]),c.useEffect((()=>()=>{l.dispose()}),[l]);const g=c.useMemo((()=>[m]),[m]),b=null==(n=e.ground)?void 0:n.height,f=null==(r=e.ground)?void 0:r.radius,v=null!==(a=null==(i=e.ground)?void 0:i.scale)&&void 0!==a?a:1e3;return c.createElement(c.Fragment,null,c.createElement(d,s.default({},e,{map:m})),c.createElement("groundProjectedEnvImpl",{args:g,scale:v,height:b,radius:f}))}exports.Environment=function(e){return e.ground?c.createElement(b,e):e.map?c.createElement(d,e):e.children?c.createElement(g,e):c.createElement(m,e)},exports.EnvironmentCube=m,exports.EnvironmentMap=d,exports.EnvironmentPortal=g;
+37
View File
@@ -0,0 +1,37 @@
import * as React from 'react';
import { Euler, ThreeElement } from '@react-three/fiber';
import { Texture, Scene } from 'three';
import { GroundProjectedEnv as GroundProjectedEnvImpl } from 'three-stdlib';
import { PresetsType } from '../helpers/environment-assets';
import { EnvironmentLoaderProps } from './useEnvironment';
export type EnvironmentProps = {
children?: React.ReactNode;
frames?: number;
near?: number;
far?: number;
resolution?: number;
background?: boolean | 'only';
blur?: number;
backgroundBlurriness?: number;
backgroundIntensity?: number;
backgroundRotation?: Euler;
environmentIntensity?: number;
environmentRotation?: Euler;
map?: Texture;
preset?: PresetsType;
scene?: Scene | React.RefObject<Scene>;
ground?: boolean | {
radius?: number;
height?: number;
scale?: number;
};
} & EnvironmentLoaderProps;
export declare function EnvironmentMap({ scene, background, map, ...config }: EnvironmentProps): null;
export declare function EnvironmentCube({ background, scene, blur, backgroundBlurriness, backgroundIntensity, backgroundRotation, environmentIntensity, environmentRotation, ...rest }: EnvironmentProps): null;
export declare function EnvironmentPortal({ children, near, far, resolution, frames, map, background, blur, backgroundBlurriness, backgroundIntensity, backgroundRotation, environmentIntensity, environmentRotation, scene, files, path, preset, extensions, }: EnvironmentProps): React.JSX.Element;
declare module '@react-three/fiber' {
interface ThreeElements {
groundProjectedEnvImpl: ThreeElement<typeof GroundProjectedEnvImpl>;
}
}
export declare function Environment(props: EnvironmentProps): React.JSX.Element;
+189
View File
@@ -0,0 +1,189 @@
import _extends from '@babel/runtime/helpers/esm/extends';
import * as React from 'react';
import { useThree, useFrame, createPortal, applyProps, extend } from '@react-three/fiber';
import { Scene, WebGLCubeRenderTarget, HalfFloatType } from 'three';
import { GroundProjectedEnv } from 'three-stdlib';
import { useEnvironment } from './useEnvironment.js';
const isRef = obj => obj.current && obj.current.isScene;
const resolveScene = scene => isRef(scene) ? scene.current : scene;
function setEnvProps(background, scene, defaultScene, texture, sceneProps = {}) {
var _target$backgroundRot, _target$backgroundRot2, _target$environmentRo, _target$environmentRo2;
// defaults
sceneProps = {
backgroundBlurriness: 0,
backgroundIntensity: 1,
backgroundRotation: [0, 0, 0],
environmentIntensity: 1,
environmentRotation: [0, 0, 0],
...sceneProps
};
const target = resolveScene(scene || defaultScene);
const oldbg = target.background;
const oldenv = target.environment;
const oldSceneProps = {
// @ts-ignore
backgroundBlurriness: target.backgroundBlurriness,
// @ts-ignore
backgroundIntensity: target.backgroundIntensity,
// @ts-ignore
backgroundRotation: (_target$backgroundRot = (_target$backgroundRot2 = target.backgroundRotation) == null || _target$backgroundRot2.clone == null ? void 0 : _target$backgroundRot2.clone()) !== null && _target$backgroundRot !== void 0 ? _target$backgroundRot : [0, 0, 0],
// @ts-ignore
environmentIntensity: target.environmentIntensity,
// @ts-ignore
environmentRotation: (_target$environmentRo = (_target$environmentRo2 = target.environmentRotation) == null || _target$environmentRo2.clone == null ? void 0 : _target$environmentRo2.clone()) !== null && _target$environmentRo !== void 0 ? _target$environmentRo : [0, 0, 0]
};
if (background !== 'only') target.environment = texture;
if (background) target.background = texture;
applyProps(target, sceneProps);
return () => {
if (background !== 'only') target.environment = oldenv;
if (background) target.background = oldbg;
applyProps(target, oldSceneProps);
};
}
function EnvironmentMap({
scene,
background = false,
map,
...config
}) {
const defaultScene = useThree(state => state.scene);
React.useLayoutEffect(() => {
if (map) return setEnvProps(background, scene, defaultScene, map, config);
});
return null;
}
function EnvironmentCube({
background = false,
scene,
blur,
backgroundBlurriness,
backgroundIntensity,
backgroundRotation,
environmentIntensity,
environmentRotation,
...rest
}) {
const texture = useEnvironment(rest);
const defaultScene = useThree(state => state.scene);
React.useLayoutEffect(() => {
return setEnvProps(background, scene, defaultScene, texture, {
backgroundBlurriness: blur !== null && blur !== void 0 ? blur : backgroundBlurriness,
backgroundIntensity,
backgroundRotation,
environmentIntensity,
environmentRotation
});
});
React.useEffect(() => {
return () => {
texture.dispose();
};
}, [texture]);
return null;
}
function EnvironmentPortal({
children,
near = 0.1,
far = 1000,
resolution = 256,
frames = 1,
map,
background = false,
blur,
backgroundBlurriness,
backgroundIntensity,
backgroundRotation,
environmentIntensity,
environmentRotation,
scene,
files,
path,
preset = undefined,
extensions
}) {
const gl = useThree(state => state.gl);
const defaultScene = useThree(state => state.scene);
const camera = React.useRef(null);
const [virtualScene] = React.useState(() => new Scene());
const fbo = React.useMemo(() => {
const fbo = new WebGLCubeRenderTarget(resolution);
fbo.texture.type = HalfFloatType;
return fbo;
}, [resolution]);
React.useEffect(() => {
return () => {
fbo.dispose();
};
}, [fbo]);
React.useLayoutEffect(() => {
if (frames === 1) {
const autoClear = gl.autoClear;
gl.autoClear = true;
camera.current.update(gl, virtualScene);
gl.autoClear = autoClear;
}
return setEnvProps(background, scene, defaultScene, fbo.texture, {
backgroundBlurriness: blur !== null && blur !== void 0 ? blur : backgroundBlurriness,
backgroundIntensity,
backgroundRotation,
environmentIntensity,
environmentRotation
});
}, [children, virtualScene, fbo.texture, scene, defaultScene, background, frames, gl]);
let count = 1;
useFrame(() => {
if (frames === Infinity || count < frames) {
const autoClear = gl.autoClear;
gl.autoClear = true;
camera.current.update(gl, virtualScene);
gl.autoClear = autoClear;
count++;
}
});
return /*#__PURE__*/React.createElement(React.Fragment, null, createPortal(/*#__PURE__*/React.createElement(React.Fragment, null, children, /*#__PURE__*/React.createElement("cubeCamera", {
ref: camera,
args: [near, far, fbo]
}), files || preset ? /*#__PURE__*/React.createElement(EnvironmentCube, {
background: true,
files: files,
preset: preset,
path: path,
extensions: extensions
}) : map ? /*#__PURE__*/React.createElement(EnvironmentMap, {
background: true,
map: map,
extensions: extensions
}) : null), virtualScene));
}
function EnvironmentGround(props) {
var _props$ground, _props$ground2, _scale, _props$ground3;
const textureDefault = useEnvironment(props);
const texture = props.map || textureDefault;
React.useMemo(() => extend({
GroundProjectedEnvImpl: GroundProjectedEnv
}), []);
React.useEffect(() => {
return () => {
textureDefault.dispose();
};
}, [textureDefault]);
const args = React.useMemo(() => [texture], [texture]);
const height = (_props$ground = props.ground) == null ? void 0 : _props$ground.height;
const radius = (_props$ground2 = props.ground) == null ? void 0 : _props$ground2.radius;
const scale = (_scale = (_props$ground3 = props.ground) == null ? void 0 : _props$ground3.scale) !== null && _scale !== void 0 ? _scale : 1000;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EnvironmentMap, _extends({}, props, {
map: texture
})), /*#__PURE__*/React.createElement("groundProjectedEnvImpl", {
args: args,
scale: scale,
height: height,
radius: radius
}));
}
function Environment(props) {
return props.ground ? /*#__PURE__*/React.createElement(EnvironmentGround, props) : props.map ? /*#__PURE__*/React.createElement(EnvironmentMap, props) : props.children ? /*#__PURE__*/React.createElement(EnvironmentPortal, props) : /*#__PURE__*/React.createElement(EnvironmentCube, props);
}
export { Environment, EnvironmentCube, EnvironmentMap, EnvironmentPortal };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),r=require("./Text3D.cjs.js"),t=require("./Center.cjs.js");function a(e){if(e&&e.__esModule)return e;var r=Object.create(null);return e&&Object.keys(e).forEach((function(t){if("default"!==t){var a=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,a.get?a:{enumerable:!0,get:function(){return e[t]}})}})),r.default=e,Object.freeze(r)}require("@babel/runtime/helpers/extends"),require("@react-three/fiber"),require("three-stdlib"),require("./useFont.cjs.js"),require("suspend-react"),require("three");var c=a(e);const n=c.forwardRef((({font:e,color:a="#cbcbcb",bevelSize:n=.04,debug:l=!1,children:u,...s},i)=>{const[o,b]=c.useState(0),f=c.useCallback(((e=1)=>b(o+e)),[o]),d=c.useCallback(((e=1)=>b(o-e)),[o]),m=c.useMemo((()=>({incr:f,decr:d})),[f,d]);return c.useImperativeHandle(i,(()=>m),[m]),c.createElement("group",s,c.createElement(c.Suspense,{fallback:null},c.createElement(t.Center,{top:!0,cacheKey:JSON.stringify({counter:o,font:e})},c.createElement(r.Text3D,{bevelEnabled:!0,bevelSize:n,font:e},l?c.createElement("meshNormalMaterial",{wireframe:!0}):c.createElement("meshStandardMaterial",{color:a}),o))),u)}));exports.Example=n;
+13
View File
@@ -0,0 +1,13 @@
import * as React from 'react';
import type { Color } from '@react-three/fiber';
export type ExampleProps = {
font: string;
color?: Color;
debug?: boolean;
bevelSize?: number;
} & React.ComponentProps<'group'>;
export type ExampleApi = {
incr: (x?: number) => void;
decr: (x?: number) => void;
};
export declare const Example: React.ForwardRefExoticComponent<Omit<ExampleProps, "ref"> & React.RefAttributes<ExampleApi>>;
+46
View File
@@ -0,0 +1,46 @@
import * as React from 'react';
import { Text3D } from './Text3D.js';
import { Center } from './Center.js';
/* eslint react-hooks/exhaustive-deps: 1 */
/**
* A simple counter example component. Click to increment, meta-click to decrement.
*/
const Example = /* @__PURE__ */React.forwardRef(({
font,
color = '#cbcbcb',
bevelSize = 0.04,
debug = false,
children,
...props
}, fref) => {
const [counter, setCounter] = React.useState(0);
const incr = React.useCallback((x = 1) => setCounter(counter + x), [counter]);
const decr = React.useCallback((x = 1) => setCounter(counter - x), [counter]);
// ref-API
const api = React.useMemo(() => ({
incr,
decr
}), [incr, decr]);
React.useImperativeHandle(fref, () => api, [api]);
return /*#__PURE__*/React.createElement("group", props, /*#__PURE__*/React.createElement(React.Suspense, {
fallback: null
}, /*#__PURE__*/React.createElement(Center, {
top: true,
cacheKey: JSON.stringify({
counter,
font
})
}, /*#__PURE__*/React.createElement(Text3D, {
bevelEnabled: true,
bevelSize: bevelSize,
font: font
}, debug ? /*#__PURE__*/React.createElement("meshNormalMaterial", {
wireframe: true
}) : /*#__PURE__*/React.createElement("meshStandardMaterial", {
color: color
}), counter))), children);
});
export { Example };
+1
View File
@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react"),t=require("three"),r=require("@react-three/fiber");function n(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var u=n(e),i=n(t);function o(e,t,n){const o=r.useThree((e=>e.size)),s=r.useThree((e=>e.viewport)),a="number"==typeof e?e:o.width*s.dpr,l="number"==typeof t?t:o.height*s.dpr,f=("number"==typeof e?n:e)||{},{samples:p=0,depth:c,...d}=f,h=null!=c?c:f.depthBuffer,b=u.useMemo((()=>{const e=new i.WebGLRenderTarget(a,l,{minFilter:i.LinearFilter,magFilter:i.LinearFilter,type:i.HalfFloatType,...d});return h&&(e.depthTexture=new i.DepthTexture(a,l,i.FloatType)),e.samples=p,e}),[]);return u.useLayoutEffect((()=>{b.setSize(a,l),p&&(b.samples=p)}),[p,b,a,l]),u.useEffect((()=>()=>b.dispose()),[]),b}const s=e.forwardRef((({children:t,width:r,height:n,...i},s)=>{const a=o(r,n,i);return e.useImperativeHandle(s,(()=>a),[a]),u.createElement(u.Fragment,null,null==t?void 0:t(a))}));exports.Fbo=s,exports.useFBO=o;
+22
View File
@@ -0,0 +1,22 @@
import * as React from 'react';
import * as THREE from 'three';
import { type RenderTargetOptions } from 'three';
type FBOSettings = {
depth?: boolean;
} & RenderTargetOptions;
export declare function useFBO(width?: number | FBOSettings, height?: number, settings?: FBOSettings): THREE.WebGLRenderTarget<THREE.Texture>;
type UseFBOParams = Parameters<typeof useFBO>;
type Fbo = ReturnType<typeof useFBO>;
export type FboProps = {
children?: (target: Fbo) => React.ReactNode;
width?: UseFBOParams[0];
height?: UseFBOParams[1];
} & FBOSettings;
export declare const Fbo: React.ForwardRefExoticComponent<{
children?: (target: Fbo) => React.ReactNode;
width?: UseFBOParams[0];
height?: UseFBOParams[1];
} & {
depth?: boolean;
} & THREE.RenderTargetOptions & React.RefAttributes<THREE.WebGLRenderTarget<THREE.Texture>>>;
export {};

Some files were not shown because too many files have changed in this diff Show More