From 1cb5ea784eaeba92ca136bfdfda2267d0d73ecae Mon Sep 17 00:00:00 2001 From: Antoine BERNIER Date: Fri, 21 Jul 2023 11:00:39 +0200 Subject: [PATCH] chore: using wrapEffect --- src/effects/LensFlare.tsx | 220 +++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 111 deletions(-) diff --git a/src/effects/LensFlare.tsx b/src/effects/LensFlare.tsx index 7ae9757..3e6dd9e 100644 --- a/src/effects/LensFlare.tsx +++ b/src/effects/LensFlare.tsx @@ -2,12 +2,13 @@ // From https://github.com/ektogamat/R3F-Ultimate-Lens-Flare import * as THREE from 'three' -import { useMemo, useEffect, forwardRef, useState, useContext } from 'react' +import { useEffect, useState, useContext, useRef } from 'react' import { useFrame, useThree } from '@react-three/fiber' import { BlendFunction, Effect } from 'postprocessing' import { easing } from 'maath' import { EffectComposerContext } from '../EffectComposer' +import { wrapEffect } from '../util' const LensFlareShader = { fragmentShader: ` @@ -495,8 +496,6 @@ export class LensFlareEffect extends Effect { } } -type LensFlareApi = LensFlareEffect - type LensFlareProps = { /** Position of the effect */ position?: THREE.Vector3 @@ -506,118 +505,117 @@ type LensFlareProps = { smoothTime?: number } & Partial -export const LensFlare = forwardRef( - ( - { - position = new THREE.Vector3(-25, 6, -60), - followMouse = false, - smoothTime = 0.07, - // - blendFunction = BlendFunction.NORMAL, - enabled = true, - glareSize = 0.2, - lensPosition = new THREE.Vector2(0.01, 0.01), - screenRes = new THREE.Vector2(0, 0), - starPoints = 6, - flareSize = 0.01, - flareSpeed = 0.01, - flareShape = 0.01, - animated = true, - anamorphic = false, - colorGain = new THREE.Color(20, 20, 20), - lensDirtTexture = null, - haloScale = 0.5, - secondaryGhosts = true, - aditionalStreaks = true, - ghostScale = 0.0, - opacity = 1.0, - starBurst = false, - }, - ref - ) => { - const viewport = useThree(({ viewport }) => viewport) - const raycaster = useThree(({ raycaster }) => raycaster) - const pointer = useThree(({ pointer }) => pointer) - const { scene, camera } = useContext(EffectComposerContext) - - const [projectedPosition] = useState(() => new THREE.Vector3()) - const [mouse2d] = useState(() => new THREE.Vector2()) - - const opts = { - blendFunction, - enabled, - glareSize, - lensPosition, - screenRes, - starPoints, - flareSize, - flareSpeed, - flareShape, - animated, - anamorphic, - colorGain, - lensDirtTexture, - haloScale, - secondaryGhosts, - aditionalStreaks, - ghostScale, - opacity, - starBurst, - } - // eslint-disable-next-line react-hooks/exhaustive-deps - const effect = useMemo(() => new LensFlareEffect(opts), [JSON.stringify(opts)]) - - useFrame((_, delta) => { - const uLensPosition = effect.uniforms.get('lensPosition') - const uOpacity = effect.uniforms.get('opacity') - if (!uLensPosition || !uOpacity) return - - let target = 1 - - if (followMouse) { - uLensPosition.value.x = pointer.x - uLensPosition.value.y = pointer.y - target = 0 - } else { - projectedPosition.copy(position).project(camera) - if (projectedPosition.z > 1) return - - uLensPosition.value.x = projectedPosition.x - uLensPosition.value.y = projectedPosition.y - - mouse2d.set(projectedPosition.x, projectedPosition.y) - raycaster.setFromCamera(mouse2d, camera) - const intersects = raycaster.intersectObjects(scene.children, true) - const { object } = intersects[0] - if (object) { - if (object.userData?.lensflare === 'no-occlusion') { - target = 0 - } else if (object instanceof THREE.Mesh) { - if (object.material.uniforms?._transmission?.value > 0.2) { - //Check for MeshTransmissionMaterial - target = 0.2 - } else if (object.material._transmission && object.material._transmission > 0.2) { - //Check for MeshPhysicalMaterial with transmission setting - target = 0.2 - } else if (object.material.transparent) { - // Check for OtherMaterials with transparent parameter - target = object.material.opacity - } +const LensFlareWrapped = wrapEffect(LensFlareEffect) + +export const LensFlare = ({ + position = new THREE.Vector3(-25, 6, -60), + followMouse = false, + smoothTime = 0.07, + // + blendFunction = BlendFunction.NORMAL, + enabled = true, + glareSize = 0.2, + lensPosition = new THREE.Vector2(0.01, 0.01), + screenRes = new THREE.Vector2(0, 0), + starPoints = 6, + flareSize = 0.01, + flareSpeed = 0.01, + flareShape = 0.01, + animated = true, + anamorphic = false, + colorGain = new THREE.Color(20, 20, 20), + lensDirtTexture = null, + haloScale = 0.5, + secondaryGhosts = true, + aditionalStreaks = true, + ghostScale = 0.0, + opacity = 1.0, + starBurst = false, +}: LensFlareProps) => { + const viewport = useThree(({ viewport }) => viewport) + const raycaster = useThree(({ raycaster }) => raycaster) + const pointer = useThree(({ pointer }) => pointer) + const { scene, camera } = useContext(EffectComposerContext) + + const [projectedPosition] = useState(() => new THREE.Vector3()) + const [mouse2d] = useState(() => new THREE.Vector2()) + + const ref = useRef(null) + + useFrame((_, delta) => { + if (!ref?.current) return + const uLensPosition = ref.current.uniforms.get('lensPosition') + const uOpacity = ref.current.uniforms.get('opacity') + if (!uLensPosition || !uOpacity) return + + let target = 1 + + if (followMouse) { + uLensPosition.value.x = pointer.x + uLensPosition.value.y = pointer.y + target = 0 + } else { + projectedPosition.copy(position).project(camera) + if (projectedPosition.z > 1) return + + uLensPosition.value.x = projectedPosition.x + uLensPosition.value.y = projectedPosition.y + + mouse2d.set(projectedPosition.x, projectedPosition.y) + raycaster.setFromCamera(mouse2d, camera) + const intersects = raycaster.intersectObjects(scene.children, true) + const { object } = intersects[0] + if (object) { + if (object.userData?.lensflare === 'no-occlusion') { + target = 0 + } else if (object instanceof THREE.Mesh) { + if (object.material.uniforms?._transmission?.value > 0.2) { + //Check for MeshTransmissionMaterial + target = 0.2 + } else if (object.material._transmission && object.material._transmission > 0.2) { + //Check for MeshPhysicalMaterial with transmission setting + target = 0.2 + } else if (object.material.transparent) { + // Check for OtherMaterials with transparent parameter + target = object.material.opacity } } } + } - easing.damp(uOpacity, 'value', target, smoothTime, delta) - }) + easing.damp(uOpacity, 'value', target, smoothTime, delta) + }) - useEffect(() => { - const screenRes = effect.uniforms.get('screenRes') - if (screenRes) { - screenRes.value.x = viewport.width - screenRes.value.y = viewport.height - } - }, [effect, viewport]) + useEffect(() => { + if (!ref?.current) return - return + const screenRes = ref.current.uniforms.get('screenRes') + if (screenRes) { + screenRes.value.x = viewport.width + screenRes.value.y = viewport.height + } + }, [viewport]) + + const opts = { + blendFunction, + enabled, + glareSize, + lensPosition, + screenRes, + starPoints, + flareSize, + flareSpeed, + flareShape, + animated, + anamorphic, + colorGain, + lensDirtTexture, + haloScale, + secondaryGhosts, + aditionalStreaks, + ghostScale, + opacity, + starBurst, } -) + return +}