Three.JS WebGLRenderer fails to create when canvas is not initialized.
See original GitHub issueDescribe the bug
I’m using Expo React-Native with Three.JS, and just recently noticed a new bug that happens when I’m initializing the Three.JS renderer. TypeError: null is not an object (evaluating 'gl.canvas.width')
.
Same as mentioned in this thread.
I’ve pinpointed the source of the issue to be due to this change https://github.com/mrdoob/three.js/commit/f5c6b1c944a2dba2c7abb9fb780719a8fbe46ab0, specifically
The changing of the following lines in its initialization from
const currentScissor = new Vector4();
const currentViewport = new Vector4();
to
const currentScissor = new Vector4( 0, 0, gl.canvas.width, gl.canvas.height );
const currentViewport = new Vector4( 0, 0, gl.canvas.width, gl.canvas.height );
I’ve tested by replacing these lines with the original ones (the Vector4 without parameters) and this issue is gone.
I’m filing this issue to ask if it will be ok if I create a pull request to change these lines to be
const currentScissor = gl.canvas ? new Vector4( 0, 0, gl.canvas.width, gl.canvas.height ) : new Vector4();
const currentViewport = gl.canvas ? new Vector4( 0, 0, gl.canvas.width, gl.canvas.height ) : new Vector4();
This change causes everything to work again.
To Reproduce
Steps to reproduce the behavior:
- Go to https://snack.expo.io/@switt/threejs-renderer-initialization-bug-example
- Use a mobile device running Expo Go client to scan the QR code to run it.
- See Alert “Renderer failed”, with error message of “null is not an object (evaluating ‘e.canvas.width’)”
- Change package.json version of “three” to something like “~0.122”
- See a spinning cube.
Code
import { ExpoWebGLRenderingContext, GLView } from 'expo-gl';
...
<GLView
style={{ flex: 1 }}
onContextCreate={async (gl: ExpoWebGLRenderingContext) => {
const {
drawingBufferWidth: width,
drawingBufferHeight: height,
} = gl;
const renderer = new Renderer({ gl }) // This will fail
renderer.setSize(width, height)
renderer.setClearColor(sceneColor)
}}
/>
Live example
Expected behavior
A clear and concise description of what you expected to happen.
- Renderer created successfully
Screenshots
If applicable, add screenshots to help explain your problem (drag and drop the image).
Platform:
- Device: Mobile Expo React-Native, SDK 39-41
- OS: iOS and Android
- Browser: Expo GLView React-Native
- Three.js version: “^0.128.0” (not sure what last working version was, but 0.122 did work)
Issue Analytics
- State:
- Created 2 years ago
- Comments:7
Top GitHub Comments
Right but I don’t think those docs really account for the subtlety in behavior when the system can’t match the drawing buffer to the canvas size. Consider the following test that tries to create a webgl context from a canvas with a width and height that is larger than the browser can handle:
So in chrome if you try to initialize a gl context to something too large it just fails. But in Firefox the draw buffer is resized and you can see that the default scissor box size matches the
gl.drawingBuffer*
value rather than the canvas dimensions.Perhaps the most robust thing to do here is just initialize the scissor and viewport vectors using the returned
gl.getParameter
values, instead, which should also fix the compatibility issue with expo.That sounds good! Let me file a PR.