import React, {
createContext,
FC,
ReactNode,
useContext,
useState
} from "react"
import * as THREE from "three"
import { AdaptiveToneMappingPass } from "three/examples/jsm/postprocessing/AdaptiveToneMappingPass.js"
import T from "."
import { Composer, Renderer, Ticker, useWindowResizeHandler } from "./engine"
import {
EffectPass,
RenderPass,
UnrealBloomPass,
Vignette
} from "./postprocessing"
type RenderPipelineComponent = FC<{
scene: THREE.Scene
camera: THREE.Camera
children?: ReactNode
}>
export const BasicRenderPipeline: RenderPipelineComponent = ({
scene,
camera,
children
}) => (
{children}
)
export const FancyRenderPipeline: RenderPipelineComponent = ({
children,
...props
}) => (
{children}
)
function useNullableState(initial?: T | (() => T)) {
return useState(initial!)
}
type ApplicationApi = {
setScene: (scene: THREE.Scene | null) => void
setCamera: (camera: THREE.Camera | null) => void
}
const ApplicationContext = createContext(null!)
export const useApplication = () => useContext(ApplicationContext)
export const Application: FC<{
children: ReactNode | ((api: ApplicationApi) => ReactNode)
renderPipeline?: RenderPipelineComponent
}> = ({ children, renderPipeline: RenderPipeline = BasicRenderPipeline }) => {
const [scene, setScene] = useNullableState()
const [camera, setCamera] = useNullableState()
useWindowResizeHandler(() => {
if (camera) {
const width = window.innerWidth
const height = window.innerHeight
if (camera instanceof THREE.PerspectiveCamera) {
camera.aspect = width / height
camera.updateProjectionMatrix()
}
}
}, [camera])
return (
{scene && camera && }
{/* {scene && camera && } */}
{children instanceof Function
? children({ setScene, setCamera })
: children}
)
}