Skip to content

Releases: pmndrs/react-ogl

v0.5.0

15 Jun 12:11
Compare
Choose a tag to compare

What's Changed

New Architecture

This release sports a new reconciliation architecture and a bunch of fixes for substantial improvements in performance and stability, particularly when using react features like suspense and concurrency.

Handling OGL side-effects

Instances' respective OGL elements are no longer created alongside the instance, but on commit mount once the tree is finalized. Instead, instances are created as descriptors that will create and link up with an OGL element once managed in the tree.

This prevents GPU memory leaks that would arise when using suspense or concurrent features whenever instances are discarded and later recreated as renders are rolled back to fallback content. OGL's use of effectful constructors is not a good design, but this way, we work around them.

Reactive attach

Attach is now gracefully handled reactively instead of at instance creation. Multiple elements can alternate between attach targets and will clean up after themselves in isolation.

<mesh>
  <box />
  <customProgram>
    <texture attach={foo ? 'texture1' : 'texture2'} />
    <texture attach={foo ? 'texture2' : 'texture1'} />
  </customProgram>
</mesh>

OGL Types

Additionally, OGL type information is now inherited from https://github.com/CodyJasonBennett/ogl-types aliased to @types/ogl (see oframe/ogl#24 as for getting this in DefinitelyTyped). These are 1-1 with the current version of OGL and will be maintained in lockstep by the community.

Event types changes

With this change, event types are now streamlined to extend Raycast hit interfaces, with a reference to the original DOM event:

export interface OGLEvent<TEvent extends Event> extends Partial<OGL.RaycastHit> {
  nativeEvent: TEvent
  // OGL.RaycastHit
  // localPoint?: OGL.Vec3
  // distance?: number
  // point?: OGL.Vec3
  // faceNormal?: OGL.Vec3
  // localFaceNormal?: OGL.Vec3
  // uv?: OGL.Vec2
  // localNormal?: OGL.Vec3
  // normal?: OGL.Vec3
}

export interface EventHandlers {
  onClick?: (event: OGLEvent<MouseEvent>) => void
  onPointerUp?: (event: OGLEvent<PointerEvent>) => void
  onPointerDown?: (event: OGLEvent<PointerEvent>) => void
  onPointerMove?: (event: OGLEvent<PointerEvent>) => void
  onPointerOver?: (event: OGLEvent<PointerEvent>) => void
  onPointerOut?: (event: OGLEvent<PointerEvent>) => void
}

Node types changes

Furthermore, extended JSX nodes have a streamlined interface rather than function-specific node interfaces, and a props helper type for element-specific prop values:

import type { WithOGLProps, Node } from 'react-ogl'

class CustomElement {}

interface CustomElementProps extends WithOGLProps<CustomElement> {}

declare global {
  namespace JSX {
    interface IntrinsicElements {
      customElement: Node<CustomElement, typeof CustomElement>
    }
  }
}

Full Changelog: v0.4.3...v0.5.0

v0.4.3

09 Jun 14:53
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.4.2...v0.4.3

v0.4.2

05 Jun 13:55
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.4.1...v0.4.2

v0.4.1

05 Jun 13:08
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.4.0...v0.4.1

v0.4.0

04 Jun 08:23
Compare
Choose a tag to compare

What's Changed

Size prop

Adds a size render prop to mirror R3F's API for sizing, this is handled by the <Canvas /> component. This can be subscribed to via useOGL:

const size = useOGL(state => state.size)
console.log(size.width, size.height)

WebXR support

Adds support for WebXR rendering via an XRManager:

XRManager {
  session: XRSession | null
  setSession(session: XRSession | null): void
  connect(session: XRSession): void
  disconnect(): void
}

//

const renderer = useOGL(state => state.renderer)
const xr = useOGL(state => state.xr)

useEffect(() => {
  let mounted = true

  (async () => {
    const session = await navigator.xr.requestSession('immersive-vr', {
      optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking'],
    })
    session.updateRenderState({ baseLayer: new XRWebGLLayer(session, renderer.gl) })

    if (!mounted) return session.end()
    else xr.connect(session)
  })()

  return () => {
    mounted = false
    xr.disconnect()
  }
}, [renderer, xr])

This will augment useFrame subscriptions to access an XRFrame while in a session:

useFrame((state: RootState, time: number, frame?: XRFrame) => {
  // ...
})

Full Changelog: v0.3.7...v0.4.0

v0.3.7

02 Jun 02:04
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.3.6...v0.3.7

v0.3.6

01 Jun 14:37
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.3.5...v0.3.6

v0.3.5

01 Jun 10:43
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.3.4...v0.3.5

v0.3.4

31 May 18:11
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.3.3...v0.3.4

v0.3.3

31 May 16:50
Compare
Choose a tag to compare

What's Changed

Full Changelog: v0.3.2...v0.3.3