diff --git a/docs/getting-started/components-and-properties.md b/docs/getting-started/components-and-properties.md index 5d040dca..41ac4139 100644 --- a/docs/getting-started/components-and-properties.md +++ b/docs/getting-started/components-and-properties.md @@ -210,7 +210,7 @@ The default image doesn't use react's suspense but rather loads the image silent ## Portal -The `Portal` component uses the `Image` component under the hood to render its children into a render target, which is displayed on the surface of the `Portal` component. In contrast to the `Image` component, the `Portal` component doesn't have a default `aspectRatio` or an `src` property. The size of the portal is completly controlled through the flexbox properties. +The `Portal` component uses the `Image` component under the hood to render its children into a render target, which is displayed on the surface of the `Portal` component. In contrast to the `Image` component, the `Portal` component doesn't have a default `aspectRatio` or an `src` property. The size of the portal is completly controlled through the flexbox properties, the resolution of the portal is equal to the size multiplied by the `dpr` property, which defaults to the system `dpr`. ```jsx diff --git a/examples/uikit/src/App.tsx b/examples/uikit/src/App.tsx index fbdb2a41..a6098e73 100644 --- a/examples/uikit/src/App.tsx +++ b/examples/uikit/src/App.tsx @@ -55,7 +55,7 @@ export default function App() { {/* By default, the Portal should create it's own camera and thus not be affected by the scene camera and orbit controls..*/} - + diff --git a/packages/react/src/portal.tsx b/packages/react/src/portal.tsx index 07c4288d..4296f075 100644 --- a/packages/react/src/portal.tsx +++ b/packages/react/src/portal.tsx @@ -60,7 +60,11 @@ export type PortalProperties = { frames?: number renderPriority?: number eventPriority?: number - resolution?: number + /** + * ratio between the size (in pixels) and the size of the render target (in pixels) + * higher dpr means higher resolution of the render target + */ + dpr?: number children?: ReactNode } & BasePortalProperties & EventHandlers & { @@ -70,10 +74,11 @@ export type PortalProperties = { export const Portal: ( props: PortalProperties & RefAttributes>, ) => ReactNode = forwardRef( - ({ children, resolution = 1, frames = Infinity, renderPriority = 0, eventPriority = 0, ...props }, ref) => { + ({ children, dpr, frames = Infinity, renderPriority = 0, eventPriority = 0, ...props }, ref) => { const fbo = useMemo(() => new Signal(undefined), []) const imageRef = useRef>(null) const previousRoot = useStore() + dpr ??= previousRoot.getState().viewport.dpr useImperativeHandle(ref, () => imageRef.current!, []) const texture = useMemo(() => computed(() => fbo.value?.texture), [fbo]) @@ -161,7 +166,6 @@ export const Portal: ( return } const [width, height] = size.value - const dpr = previousRoot.getState().viewport.dpr renderTarget.setSize(width * dpr, height * dpr) usePortalStore.setState({ size: { width, height, top: 0, left: 0 }, @@ -172,7 +176,7 @@ export const Portal: ( unsubscribeSetSize() renderTarget.dispose() } - }, [fbo, previousRoot, usePortalStore]) + }, [fbo, previousRoot, usePortalStore, dpr]) return ( <>