import React, { createContext, forwardRef, useContext, useEffect, useImperativeHandle, useState } from "react" import { PCFSoftShadowMap, sRGBEncoding, WebGLRenderer } from "three" import { ReactorComponentProps } from "../reactor" import { useWindowResizeHandler } from "./useWindowResizeHandler" const RendererContext = createContext(null!) type RendererProps = ReactorComponentProps export const Renderer = forwardRef( ({ children }, ref) => { const [canvas, setCanvas] = useState() const [renderer, setRenderer] = useState() useEffect(() => { if (!canvas) return setRenderer(() => { const renderer = new WebGLRenderer({ canvas: canvas, powerPreference: "high-performance", antialias: false, alpha: false, stencil: false, logarithmicDepthBuffer: true }) renderer.autoClear = false renderer.setPixelRatio(1) renderer.outputEncoding = sRGBEncoding renderer.shadowMap.enabled = true renderer.shadowMap.type = PCFSoftShadowMap renderer.setSize(canvas.clientWidth, canvas.clientHeight) return renderer }) return () => void setRenderer(undefined) }, [canvas]) useImperativeHandle(ref, () => renderer!, [renderer]) useWindowResizeHandler(() => { if (!renderer) return const width = window.innerWidth const height = window.innerHeight renderer.setSize(width, height) }, [renderer]) return ( {renderer && ( {typeof children === "function" ? children() : children} )} ) } ) export const useRenderer = () => useContext(RendererContext)