expo-three icon indicating copy to clipboard operation
expo-three copied to clipboard

[Unhandled promise rejection: TypeError: null is not an object (evaluating 'gl.canvas.width')]

Open haibert opened this issue 3 years ago • 13 comments

Hello, I have just discovered this library and attempting to use it.

I have cloned the example project multiple times and every time I run the project I get error that gl.canvas is null.

simulator_screenshot_DA99E780-73A9-4001-9306-87335D95E2BC

Code

` import { ExpoWebGLRenderingContext, GLView } from 'expo-gl' import { Renderer, TextureLoader } from 'expo-three' import * as React from 'react' import { AmbientLight, BoxBufferGeometry, Fog, GridHelper, Mesh, MeshStandardMaterial, PerspectiveCamera, PointLight, Scene, SpotLight, } from 'three'

export default function App() { let timeout

React.useEffect(() => {
    // Clear the animation loop when the component unmounts
    return () => clearTimeout(timeout)
}, [])

return (
    <GLView
        style={{ flex: 1 }}
        onContextCreate={async (gl: ExpoWebGLRenderingContext) => {
            const {
                drawingBufferWidth: width,
                drawingBufferHeight: height,
            } = gl
            const sceneColor = 0x6ad6f0

            // Create a WebGLRenderer without a DOM element
            const renderer = new Renderer({ gl })
            renderer.setSize(width, height)
            renderer.setClearColor(sceneColor)

            const camera = new PerspectiveCamera(
                70,
                width / height,
                0.01,
                1000
            )
            camera.position.set(2, 5, 5)

            const scene = new Scene()
            scene.fog = new Fog(sceneColor, 1, 10000)
            scene.add(new GridHelper(10, 10))

            const ambientLight = new AmbientLight(0x101010)
            scene.add(ambientLight)

            const pointLight = new PointLight(0xffffff, 2, 1000, 1)
            pointLight.position.set(0, 200, 200)
            scene.add(pointLight)

            const spotLight = new SpotLight(0xffffff, 0.5)
            spotLight.position.set(0, 500, 100)
            spotLight.lookAt(scene.position)
            scene.add(spotLight)

            const cube = new IconMesh()
            scene.add(cube)

            camera.lookAt(cube.position)

            function update() {
                cube.rotation.y += 0.05
                cube.rotation.x += 0.025
            }

            // Setup an animation loop
            const render = () => {
                timeout = requestAnimationFrame(render)
                update()
                renderer.render(scene, camera)
                gl.endFrameEXP()
            }
            render()
        }}
    />
)

}

class IconMesh extends Mesh { constructor() { super( new BoxBufferGeometry(1.0, 1.0, 1.0), new MeshStandardMaterial({ map: new TextureLoader().load(require('./assets/icon.png')), // color: 0xff0000 }) ) } }

`

Here are my dependencies

{
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject"
  },
  "dependencies": {
    "expo": "~41.0.1",
    "expo-gl": "~10.2.0",
    "expo-graphics": "^2.0.0",
    "expo-status-bar": "~1.0.4",
    "expo-three": "^5.7.0",
    "react": "16.13.1",
    "react-dom": "16.13.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
    "react-native-web": "~0.13.12",
    "three": "^0.128.0"
  },
  "devDependencies": {
    "@babel/core": "^7.9.0",
    "@types/react": "~16.9.35",
    "@types/react-native": "~0.63.2",
    "typescript": "~4.0.0"
  },
  "private": true
}

haibert avatar May 03 '21 22:05 haibert

I have the exact same problem

chiliwax avatar May 04 '21 15:05 chiliwax

I finally fix it by downgrading threejs

"three": "0.126.1"
"expo-three": "5.7.0"

hopefully that can help you :)

chiliwax avatar May 05 '21 08:05 chiliwax

I finally fix it by downgrading threejs

"three": "0.126.1"
"expo-three": "5.7.0"

hopefully that can help you :)

@chiliwax, i've tried downgrading three to the mentioned version, to no luck...

Do you care to post the npm list of your project?

migupry avatar May 10 '21 16:05 migupry

I didn't had to downgrade threejs. I've found a simple workaround: -Added the following statement inside onContextCreate function, before creating the Renderer: gl.canvas = { width: gl.drawingBufferWidth, height: gl.drawingBufferHeight };

migupry avatar May 10 '21 17:05 migupry

@migupry Encountered this too. Your solution works, thanks!

~~But now I'm wondering when this bug in Expo's GLView started. SDK 39 doesn't have this bug (I have an old project still on SDK 39, this hack isn't needed).~~

I'm currently using SDK 41, same as you.

Edit : OK I've looked at the GLView source code, it seems the canvas has always been null at the point that onContextCreate is called, so it's likely that this error is due to a change in how Three.JS initialized things, likely in initGLContext() according to the logs.

swittk avatar May 12 '21 21:05 swittk

Might be this change in THREE.JS from 2 months ago, since it's the only place in that initGLContext() function that seems to reference the GL context.

It's in the WebGLState object. https://github.com/mrdoob/three.js/commit/f5c6b1c944a2dba2c7abb9fb780719a8fbe46ab0

Would need to check a bit, but I think this might be the cause of the problem.

swittk avatar May 12 '21 21:05 swittk

Screen Shot 2564-05-13 at 04 55 01 Screen Shot 2564-05-13 at 04 55 11

OK, now those lines are definitely the cause of this problem.

Edit : Changed those mentioned lines to the original and now the bug is gone, I'm going to try and file a pull request.

swittk avatar May 12 '21 21:05 swittk

This should be fixed with the next release of Three.JS 🎉

swittk avatar May 14 '21 22:05 swittk

@migupry yes, it works, but then there was another problem

TypeError: undefined is not a constructor (evaluating 'new THREE.RectAreaLightHelper(whiteRectLight1)')

igorroman777 avatar May 16 '21 18:05 igorroman777

@migupry yes, it works, but then there was another problem

TypeError: undefined is not a constructor (evaluating 'new THREE.RectAreaLightHelper(whiteRectLight1)')

Hmm that's strange. I didn't face this. Care to post your code maybe? Maybe it makes sense to create a new issue, because this doesn't seem to be related to the inital error.

migupry avatar May 16 '21 18:05 migupry

@migupry it worked before: ` const whiteRectLight1 = new THREE.RectAreaLight( WHITE_COLOR, intensity, lights_width, lights_height ); whiteRectLight1.position.set( 200, 185, -300 ); whiteRectLight1.lookAt( 200, 0, -300 ); scene.add( whiteRectLight1 );

  const rectLightHelper1 = new THREE.RectAreaLightHelper( whiteRectLight1 );
  whiteRectLight1.add( rectLightHelper1 );`

igorroman777 avatar May 16 '21 19:05 igorroman777

@migupry it worked before: ` const whiteRectLight1 = new THREE.RectAreaLight( WHITE_COLOR, intensity, lights_width, lights_height ); whiteRectLight1.position.set( 200, 185, -300 ); whiteRectLight1.lookAt( 200, 0, -300 ); scene.add( whiteRectLight1 );

  const rectLightHelper1 = new THREE.RectAreaLightHelper( whiteRectLight1 );
  whiteRectLight1.add( rectLightHelper1 );`

Ok, i've tested your code, and it does not work. But I'm 100% sure this is not releated to this issue.

Check this link.

RectAreaLightHelper has been dropped from ThreeJS core, and you need to import it as such: import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper.js";

Also, you need to adjust your code accordingly, so use: new RectAreaLightHelper instead of new THREE.RectAreaLightHelper

migupry avatar May 16 '21 20:05 migupry

@migupry ok, thank you very much, yes, it works. There are other problems as well. But it is a three.js update problem.

igorroman777 avatar May 16 '21 20:05 igorroman777