Search code examples
three.jsreact-three-fiberreact-three-drei

React three fiber: Putting Html text in heads up display


I'm working on a project where I have a minimap in the top left of my react-three-fiber scene. The minimap is a portal into another scene and is fixed to my camera's frame. This means I can move around in a scene and the minimap stays in the top left.

This works great, but I also want to have text above the minimap to describe the current state of the minimap. I want this text to also stay fixed to my camera's frame and not move when I move in the scene. Below is an example of what my goal is. m is my minimap, and t is the text I want above my minimap.

 _____________
|t            |
|m            |
|   my scene  |
|             |
|_____________|

However, when I try to add an drei Html component to the same virtual scene as the minimap, my scene just freezes and crashes.

import React from 'react'                                                  
import * as THREE from 'three'                                             
import { useFrame, useThree, createPortal } from '@react-three/fiber'      
import { Plane, useFBO, OrthographicCamera, Text } from '@react-three/drei'
                                                                           
function Panel(props) {                                                    
  const viewTarget = useFBO()                                              
                       
  // A camera that is mounted above and looking down on my scene                                                    
  const viewCamera = props.camera;                                         
                                                                           
  const virtualScene = new THREE.Scene()                                   
  const virtualCamera = React.useRef()                                     
                                                                                                                                                                       
                                                                           
  useFrame(({ gl, camera, scene }) => {                                    
    gl.autoClear = false                                                   
                                                                                                                                                      
    // Render the scene from the camera above into my WebGLRenderTarget
    gl.setRenderTarget(viewTarget)                                         
    gl.render(scene, viewCamera.current)                                   
                                                                           
    // Render my original main scene                                                   
    gl.setRenderTarget(null)                                               
    gl.render(scene, camera)                                               
                                                                           
    // render GUI panels on top of main scene                              
    gl.render(virtualScene, virtualCamera.current)                         
    gl.autoClear = true                                                    
  }, 1)                                                                    
                                                                           
  return createPortal(                                                     
    <>                                                                     
      <OrthographicCamera ref={virtualCamera} near={0.0001} far={1} />     
      <group position-z={-0.1} position-x={0}>                             
        <Html>                                                             
          I want text here                                                     
        </Html>                                                            
        <Plane args={[200, 100, 1]} position-y={0}/>                       
      </group>                                                             
    </>,                                                                   
    virtualScene                                                           
  )                                                                        
}                                                                          

When I import this component into my scene, the scene freezes. If I remove the Html component from this component, the scene no longer freezes.

I am new to react three fiber, so I have a feeling I'm misunderstanding what a portal is.


Solution

  • You need to import the Html component. Change the drei import to:

    import { Plane, useFBO, OrthographicCamera, Text, Html } from '@react-three/drei'