Skip to content

Commit

Permalink
feat: hud
Browse files Browse the repository at this point in the history
  • Loading branch information
drcmda committed Nov 27, 2022
1 parent 5d7bfe4 commit b941939
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
39 changes: 39 additions & 0 deletions README.md
Expand Up @@ -142,6 +142,7 @@ The `native` route of the library **does not** export `Html` or `Loader`. The de
</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="#mask">Mask</a></li>
Expand Down Expand Up @@ -2341,6 +2342,44 @@ function Effects() {

# Portals

#### Hud

<p>
<a href="https://codesandbox.io/s/py4db"><img width="20%" src="https://codesandbox.io/api/v1/sandboxes/py4db/screenshot.png" alt="Demo"/></a>
</p>

Renders a heads-up-display (HUD). Each HUD is a scene on top of the previous. That scene is inside a React `createPortal` and is completely isolated, you can have your own cameras in there, environments, etc. The first HUD (`renderpriotity === 1`) will clear the scene and render the default scene, it needs to be the first to execute! Make sure to be explicit about the `renderpriority` of your HUDs.

```tsx
type HudProps = {
/** Any React node */
children: React.ReactNode
/** Render priority, default: 1 */
renderPriority?: number
}
```

```jsx
{
/* Renders on top of the default scene with a perspective camera */
}
;<Hud>
<PerspectiveCamera makeDefault position={[0, 0, 10]} />
<mesh>
<ringGeometry />
</mesh>
</Hud>
{
/* Renders on top of the previous HUD with an orthographic camera */
}
;<Hud renderPriority={2}>
<OrthographicCamera makeDefault position={[0, 0, 10]} />
<mesh>
<boxGeometry />
</mesh>
</Hud>
```

#### View

<p>
Expand Down
49 changes: 49 additions & 0 deletions src/core/Hud.tsx
@@ -0,0 +1,49 @@
import * as THREE from 'three'
import * as React from 'react'
import { useFrame, useThree, createPortal } from '@react-three/fiber'

type RenderHudProps = {
defaultScene: THREE.Scene
defaultCamera: THREE.Camera
renderPriority?: number
}

type HudProps = {
/** Any React node */
children: React.ReactNode
/** Render priority, default: 1 */
renderPriority?: number
}

function RenderHud({ defaultScene, defaultCamera, renderPriority = 1 }: RenderHudProps) {
const { gl, scene, camera } = useThree()
useFrame(() => {
if (renderPriority === 1) {
// Clear scene and render the default scene
gl.autoClear = true
gl.render(defaultScene, defaultCamera)
}
// Disable cleaning and render the portal with its own camera
gl.autoClear = false
gl.clearDepth()
gl.render(scene, camera)
}, renderPriority)
return <> </>
}

export function Hud({ children, renderPriority = 1 }: HudProps) {
const { scene: defaultScene, camera: defaultCamera } = useThree()
const [hudScene] = React.useState(() => new THREE.Scene())
return (
<>
{createPortal(
<>
{children}
<RenderHud defaultScene={defaultScene} defaultCamera={defaultCamera} renderPriority={renderPriority} />
</>,
hudScene,
{ events: { priority: renderPriority + 1 } }
)}
</>
)
}
1 change: 1 addition & 0 deletions src/core/index.ts
Expand Up @@ -118,3 +118,4 @@ export * from './PerformanceMonitor'
// Portals
export * from './RenderTexture'
export * from './Mask'
export * from './Hud'

1 comment on commit b941939

@vercel
Copy link

@vercel vercel bot commented on b941939 Nov 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.