Skip to content

Conversation

@rudin
Copy link
Contributor

@rudin rudin commented Aug 22, 2025

I was unable to get this to render on the iOS Simulator. I kept encountering EXC_BAD_ACCESS crashes.
After investigating, I discovered that iOS Simulators provide incomplete/unreliable support for OpenGL ES, which causes issues with WebGL rendering. So, I suggest adding a note to recommend testing on a physical iOS device.

Added a note about iOS simulator limitations for 3D rendering.
@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 75c939f:

Sandbox Source
example Configuration

@DennisSmolek
Copy link
Contributor

Were you using React-Native or what exactly? When you tried Vanilla threejs what happened?

This might be a generic threejs problem and not a r3f one

@qalqi
Copy link

qalqi commented Nov 22, 2025

Yes! This is required.. react three fiber doesn't work ios simulator 26.1

@DennisSmolek
Copy link
Contributor

Yes! This is required.. react three fiber doesn't work ios simulator 26.1

Right but three.js might be the issue, not r3f

@CodyJasonBennett
Copy link
Member

I missed this. The PR author is precisely correct, and the issue comes from the use of OpenGL ES directly from expo-gl, which is deprecated and very unreliable on Apple's OpenGL driver (Intel especially). If React Native had ANGLE bindings, which is what browsers use to implement WebGL, then we could enjoy more stability and compliance. I am happy to accept the warning as written.

I must warn against general React Native usage since the problem is more severe and not solvable alone through the graphics stack. React Native core and networking stack further worsen stability in a real application (we have a host of issues when using loaders and data APIs, and we are not alone since this is upstream and a core API pattern facebook/react-native#39276). These are very WIP areas across the stack, and I would urge anyone to use a webview instead. Remember that you can use many solutions in harmony with React Native, and so this doesn't have to compromise the rest of your stack.

@qalqi
Copy link

qalqi commented Nov 25, 2025

Issue Summary

expo-three does not show any visual output inside the iPhone Simulator.
It works correctly on:

  • Web (with a single "expo" entry in app.json)
  • Android simulator

Doesnt work in

  • Snack environment
  • iPhone Simulator - iOS 26.1

I will test on a physical iPhone device shortly and update here.

Here is a comment in expo-three about iPhone simulator
> 🚨 You'll need to use a physical device as the iOS Simulators and Android emulators do not work well with Three.js + EXGL.


Reproduction Code

import { GLView } from "expo-gl";
import { Renderer, TextureLoader } from "expo-three";
import { useEffect } from "react";
import {
  AmbientLight,
  BoxGeometry,
  Fog,
  GridHelper,
  HemisphereLight,
  HemisphereLightHelper,
  Mesh,
  MeshStandardMaterial,
  PerspectiveCamera,
  PointLight,
  Scene,
  SpotLight,
} from "three";

export default function JustThree() {
  let timeout: number;

  useEffect(() => {
    return () => clearTimeout(timeout);
  }, []);

  const onContextCreate = async (gl: WebGLRenderingContext) => {
    const { drawingBufferWidth: width, drawingBufferHeight: height } = gl as any;

    const renderer = new Renderer({ gl });
    renderer.setSize(width, height);
    renderer.setClearColor(0x101010);

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

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

    const hemiLight = new HemisphereLight(0xffffff, 0xffffff, 2);
    hemiLight.color.setHSL(0.6, 1, 0.6);
    hemiLight.groundColor.setHSL(0.095, 1, 0.75);
    hemiLight.position.set(0, 50, 0);
    scene.add(hemiLight);

    scene.add(new HemisphereLightHelper(hemiLight, 10));

    scene.add(new AmbientLight(0x101010));

    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;
    }

    const render = () => {
      timeout = requestAnimationFrame(render);
      update();
      renderer.render(scene, camera);
      (gl as any).endFrameEXP();
    };

    render();
  };

  return <GLView style={{ flex: 1 }} onContextCreate={onContextCreate} />;
}

class IconMesh extends Mesh {
  constructor() {
    super(new BoxGeometry(1, 1, 1), new MeshStandardMaterial({}));
  }
}

Screenshots

Web – Working

Screenshot 2025-11-25 at 11 55 24 AM

iPhone Simulator – Not Working

Screenshot 2025-11-25 at 11 54 52 AM

Related Issue

The same problem was discussed here:
#2532


Additional Notes

expo-gl alone works fine on iPhone Simulator and Snack:

Snack example: https://snack.expo.dev/@qalqi/aad124

Screenshot 2025-11-25 at 12 00 48 PM

@CodyJasonBennett
Copy link
Member

I will further add that Apple OpenGL has been broken on the simulator for some time now. OpenGL ES works on-device but is unreliable and not officially supported by Apple (they deprecated OpenGL in 2014). If one were to use Apple Metal directly for graphics (or via ANGLE for WebGL), it would work on the simulator and on-device. Unless anyone has objects, I would like to include this note since it affects quality control in a confusing way.

@CodyJasonBennett CodyJasonBennett changed the title Update installation guide with iOS simulator note docs: update installation guide with iOS simulator note Nov 25, 2025
@DennisSmolek
Copy link
Contributor

Unless anyone has objects, I would like to include this note since it affects quality control in a confusing way.

I think it's fine to add a note, but I'd like to point out that it's not a r3f or even threejs thing. It's a react-native/webgl thing.

I wonder with the new Dawn/WebGPU situation in RN if it would be better to push people to using that instead of webgl because its so problematic

@qalqi
Copy link

qalqi commented Nov 25, 2025

@DennisSmolek Thanks for the suggestion!

One click configuration of @react-three/fiber with
npx create-expo-app@latest -e with-webgpu
yarn install
npx expo prebuild
yarn ios and all good!
Working in iOS simulator iOS 26.1 and web both! and feels faster

Screenshot 2025-11-25 at 5 09 21 PM

@DennisSmolek
Copy link
Contributor

@DennisSmolek Thanks for the suggestion!

Nice! This is the way to go!

@qalqi
Copy link

qalqi commented Nov 25, 2025

@DennisSmolek Thanks for the suggestion!

Nice! This is the way to go!

If you don't mind, can you share if react-native-wgpu is good enough alternative to expo-gl for production apps with three and react-three-fiber?
We have a language learning game with 1K users..

@CodyJasonBennett
Copy link
Member

My suggestion would be to use a webview because data APIs and React Native stack are slow to unstable, which undermines the games use case even with a solid graphics stack. If you do wish to use a graphics API natively, then WebGPU via wgpu/Dawn (like react-native-wgpu) would be my suggestion (react-native-webgpu abstracts both implementations).

@CodyJasonBennett CodyJasonBennett merged commit 1dea40e into pmndrs:master Nov 29, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants