Hi Omar,
I’ve switched my code over to use three js fiber to make it easier to coordinate state in my scene. But I have not been able to get your custom outline renderer to work using fiber. I have tried to use drei, specifically:
as well as trying by using . But I am not sure how to add the CustomOutlinePass. I am sure I am doing this all wrong, but I just don’t understand the lifecycle. Have you ever tried to use Fiber with custom post processing?
Thanks! Here is my code:
SceneViewer.tsx:
import * as THREE from 'three';
import ReactDOM from 'react-dom';
import { Effects, OrbitControls, PerspectiveCamera } from '@react-three/drei';
import React, { useRef } from 'react';
import { Canvas } from '@react-three/fiber';
import SpaceShip from './scenes/SpaceShip';
import { CustomOutlinePass } from './CustomOutlinePass';
export default function SceneViewer() {
const WIDTH = 1600;
const HEIGHT = 1200;
const camera = useRef(null!);
const scene = useRef(null!);
const composer = useRef(null!);
// Outline pass.
const customOutline = new CustomOutlinePass(
new THREE.Vector2(WIDTH, HEIGHT),
scene.current,
camera.current
);
composer.current.addPass(customOutline);
return (
<div style={{ position: 'relative', width: WIDTH, height: HEIGHT }}>
<Canvas>
<Effects ref={composer} />
<PerspectiveCamera
ref={camera}
makeDefault
position={[0, 200, 0]}
up={[0, 0, 1]}
/>
<OrbitControls
enablePan={true}
enableZoom={true}
enableRotate={true}
target={[0, 0, 0]}
/>
<ambientLight />
<pointLight position={[10, 10, 10]} />
<scene ref={scene}>
<SpaceShip />
</scene>
</Canvas>
</div>
);
}
SelectableModel.tsx:
import * as THREE from 'three';
import ReactDOM from 'react-dom';
import { useGLTF } from '@react-three/drei';
import React, { useState } from 'react';
export default function SelectableModel(props) {
const gltf = useGLTF(props.modelType, true);
const [hovered, setHover] = useState(false);
const [active, setActive] = useState(false);
return (
<primitive
object={gltf.scene}
position={props.position}
scale={active ? 1.5 : 1}
onClick={event => {
setActive(!active);
event.stopPropagation();
}}
onPointerOver={event => setHover(true)}
onPointerOut={event => setHover(false)}
/>
);
}
SpaceShip.tsx:
import * as THREE from 'three';
import ReactDOM from 'react-dom';
import React, { Suspense } from 'react';
import MainSection from './models/MainSection.glb';
import Box from '../common/Box';
import SelectableModel from './SelectableModel';
function SpaceShip() {
return (
<Suspense fallback={<Box />}>
<SelectableModel modelType={MainSection} position={[0, 0, 0]} />
</Suspense>
);
}
Box.tsx:
import * as THREE from 'three';
import React, { useRef, useState } from 'react';
import { useFrame } from '@react-three/fiber';
export default function Box(props) {
const mesh = useRef<THREE.Mesh>(null!);
const [hovered, setHover] = useState(false);
const [active, setActive] = useState(false);
useFrame((state, delta) => (mesh.current.rotation.x += 0.01));
return (
<mesh
{...props}
ref={mesh}
scale={active ? 1.5 : 1}
onClick={event => setActive(!active)}
onPointerOver={event => setHover(true)}
onPointerOut={event => setHover(false)}>
<boxGeometry args={[1, 1, 1]} />
</mesh>
);
}