expo-three
expo-three copied to clipboard
[Unhandled promise rejection: TypeError: null is not an object (evaluating 'gl.canvas.width')]
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.
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
}
I have the exact same problem
I finally fix it by downgrading threejs
"three": "0.126.1"
"expo-three": "5.7.0"
hopefully that can help you :)
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?
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 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.
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.


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.
This should be fixed with the next release of Three.JS 🎉
@migupry yes, it works, but then there was another problem
TypeError: undefined is not a constructor (evaluating 'new THREE.RectAreaLightHelper(whiteRectLight1)')
@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 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 );`
@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 ok, thank you very much, yes, it works. There are other problems as well. But it is a three.js update problem.