@@ -8,11 +8,15 @@ import {
8
8
useStore ,
9
9
useThree ,
10
10
} from '@react-three/fiber'
11
- import { forwardRef , ReactNode , RefObject , useCallback , useEffect , useImperativeHandle , useMemo , useRef } from 'react'
11
+ import { ReactNode , RefObject , useCallback , useEffect , useMemo , useRef } from 'react'
12
12
import {
13
+ DepthTexture ,
14
+ HalfFloatType ,
15
+ LinearFilter ,
13
16
Mesh ,
14
17
MeshBasicMaterial ,
15
18
Object3D ,
19
+ OrthographicCamera ,
16
20
PerspectiveCamera ,
17
21
Raycaster ,
18
22
Scene ,
@@ -23,7 +27,6 @@ import {
23
27
import { useXRLayer } from './layer.js'
24
28
import { createXRLayer , XRLayerEntry , XRLayerOptions , XRLayerProperties , XRLayerShape } from '@pmndrs/xr'
25
29
import { XRStore } from '../xr.js'
26
- import { isOrthographicCamera } from '@react-three/fiber/dist/declarations/src/core/utils.js'
27
30
import { create , StoreApi , UseBoundStore } from 'zustand'
28
31
import { forwardObjectEvents } from '@pmndrs/pointer-events'
29
32
@@ -43,10 +46,13 @@ export type XRRenderTargetLayerProperties = {
43
46
renderPriority ?: number
44
47
pixelWidth : number
45
48
pixelHeight : number
49
+ src ?: undefined
46
50
} & Omit < XRLayerOptions , 'textureType' | 'isStatic' | 'layout' > &
47
51
XRLayerProperties &
48
52
MeshProps
49
53
54
+ //TODO: custom geometry and border radius for cut outs
55
+
50
56
export function NonXRRenderTargetLayer ( {
51
57
renderOrder,
52
58
pixelWidth,
@@ -55,31 +61,32 @@ export function NonXRRenderTargetLayer({
55
61
renderPriority = 0 ,
56
62
...props
57
63
} : XRRenderTargetLayerProperties ) {
58
- const renderTargetRef = useRef < WebGLRenderTarget > ( null )
59
64
const ref = useRef < Mesh > ( null )
65
+ const layerStore = useLayerStore ( pixelWidth , pixelHeight )
66
+ const renderTargetRef = useRenderTargetRef ( pixelWidth , pixelHeight )
60
67
const materialRef = useRef < MeshBasicMaterial > ( null )
61
68
useEffect ( ( ) => {
62
69
if ( materialRef . current == null || renderTargetRef . current == null ) {
63
70
return
64
71
}
65
72
materialRef . current . map = renderTargetRef . current . texture
66
- } , [ ] )
73
+ materialRef . current . needsUpdate = true
74
+ } , [ renderTargetRef ] )
67
75
68
- const layerStore = useLayerStore ( pixelWidth , pixelHeight )
69
76
useForwardEvents ( layerStore , ref )
70
77
return (
71
78
< >
72
79
{ reconciler . createPortal (
73
80
< context . Provider value = { layerStore } >
74
- < ChildrenToRenderTarget ref = { renderTargetRef } renderPriority = { renderPriority } >
81
+ < ChildrenToRenderTarget renderTargetRef = { renderTargetRef } renderPriority = { renderPriority } >
75
82
{ children }
76
83
</ ChildrenToRenderTarget >
77
84
</ context . Provider > ,
78
85
layerStore ,
79
86
null ,
80
87
) }
81
- < mesh { ...props } >
82
- < meshBasicMaterial toneMapped = { false } />
88
+ < mesh ref = { ref } { ...props } >
89
+ < meshBasicMaterial ref = { materialRef } toneMapped = { false } />
83
90
</ mesh >
84
91
</ >
85
92
)
@@ -131,19 +138,24 @@ export function XRRenderTargetLayer({
131
138
} )
132
139
const layerStore = useLayerStore ( pixelWidth , pixelHeight )
133
140
useForwardEvents ( layerStore , ref )
141
+ const renderTargetRef = useRenderTargetRef ( pixelWidth , pixelHeight )
134
142
return (
135
143
< >
136
144
{ reconciler . createPortal (
137
145
< context . Provider value = { layerStore } >
138
- < ChildrenToRenderTarget renderPriority = { renderPriority } layerEntryRef = { layerEntryRef } >
146
+ < ChildrenToRenderTarget
147
+ renderTargetRef = { renderTargetRef }
148
+ renderPriority = { renderPriority }
149
+ layerEntryRef = { layerEntryRef }
150
+ >
139
151
{ children }
140
152
</ ChildrenToRenderTarget >
141
153
</ context . Provider > ,
142
154
layerStore ,
143
155
null ,
144
156
) }
145
157
< mesh { ...props } renderOrder = { - Infinity } ref = { ref } >
146
- < meshBasicMaterial colorWrite = { false } />
158
+ < meshBasicMaterial />
147
159
</ mesh >
148
160
</ >
149
161
)
@@ -262,27 +274,37 @@ export function useLayerStore(width: number, height: number) {
262
274
return layerStore
263
275
}
264
276
265
- const ChildrenToRenderTarget = forwardRef <
266
- WebGLRenderTarget ,
267
- {
268
- renderPriority : number
269
- children : ReactNode
270
- layerEntryRef ?: RefObject < XRLayerEntry | undefined >
271
- }
272
- > ( ( { renderPriority, children, layerEntryRef } , ref ) => {
273
- const store = useStore ( )
274
-
277
+ export function useRenderTargetRef ( width : number , height : number ) {
275
278
const renderTargetRef = useRef < WebGLRenderTarget | undefined > ( undefined )
276
279
useEffect ( ( ) => {
277
- const renderTarget = ( renderTargetRef . current = new WebGLRenderTarget ( 1 , 1 , { } ) )
280
+ const renderTarget = ( renderTargetRef . current = new WebGLRenderTarget ( width , height , {
281
+ minFilter : LinearFilter ,
282
+ magFilter : LinearFilter ,
283
+ type : HalfFloatType ,
284
+ depthTexture : new DepthTexture ( width , height ) ,
285
+ } ) )
278
286
return ( ) => renderTarget . dispose ( )
279
- } , [ ] )
287
+ } , [ width , height ] )
288
+ return renderTargetRef
289
+ }
290
+
291
+ function ChildrenToRenderTarget ( {
292
+ renderPriority,
293
+ children,
294
+ layerEntryRef,
295
+ renderTargetRef,
296
+ } : {
297
+ renderPriority : number
298
+ children : ReactNode
299
+ layerEntryRef ?: RefObject < XRLayerEntry | undefined >
300
+ renderTargetRef : RefObject < WebGLRenderTarget | undefined >
301
+ } ) {
302
+ const store = useStore ( )
280
303
281
304
useEffect ( ( ) => {
282
305
const update = ( state : RootState , prevState ?: RootState ) => {
283
306
const { size, camera } = state
284
- renderTargetRef . current ?. setSize ( size . width , size . height )
285
- if ( isOrthographicCamera ( camera ) ) {
307
+ if ( camera instanceof OrthographicCamera ) {
286
308
camera . left = size . width / - 2
287
309
camera . right = size . width / 2
288
310
camera . top = size . height / 2
@@ -301,14 +323,15 @@ const ChildrenToRenderTarget = forwardRef<
301
323
return store . subscribe ( update )
302
324
} , [ store ] )
303
325
304
- useImperativeHandle ( ref , ( ) => renderTargetRef . current ! , [ ] )
305
-
306
326
let oldAutoClear
307
327
let oldXrEnabled
308
328
let oldIsPresenting
309
329
let oldRenderTarget
310
330
useFrame ( ( { gl, scene, camera } , _delta , frame : XRFrame | undefined ) => {
311
- if ( renderTargetRef . current == null || ( layerEntryRef != null && layerEntryRef . current == null ) || frame == null ) {
331
+ if (
332
+ renderTargetRef . current == null ||
333
+ ( layerEntryRef != null && ( layerEntryRef . current == null || frame == null ) )
334
+ ) {
312
335
return
313
336
}
314
337
oldAutoClear = gl . autoClear
@@ -319,7 +342,7 @@ const ChildrenToRenderTarget = forwardRef<
319
342
gl . xr . enabled = false
320
343
gl . xr . isPresenting = false
321
344
const renderTarget = renderTargetRef . current
322
- if ( layerEntryRef ?. current != null ) {
345
+ if ( layerEntryRef ?. current != null && frame != null ) {
323
346
const subImage = gl . xr . getBinding ( ) . getSubImage ( layerEntryRef . current . layer , frame )
324
347
gl . setRenderTargetTextures ( renderTarget , subImage . colorTexture )
325
348
}
@@ -331,4 +354,4 @@ const ChildrenToRenderTarget = forwardRef<
331
354
gl . xr . isPresenting = oldIsPresenting
332
355
} , renderPriority )
333
356
return < > { children } </ >
334
- } )
357
+ }
0 commit comments