Coming soon. Aims to provide support to run Three.js natively, in React Native.
Interested in this project? Star it in GitHub to show your support.
Looking for more direct access to the GPU through a JavaScript api? Check out react-native-webgpu.
You can find instructions to run the examples here.
⚠️ Please note that these instructions don't work since this package has not yet been published
- Install packages
yarn add react-native-webgpu-three react-native-webgpu three fast-text-encoding
yarn add -D @babel/plugin-transform-export-namespace-from
# For TypeScript also:
yarn add -D @types/three
- Install pods
cd ios
pod install
cd ..
- Import
react-native-webgpu-three
before importingthree
. It might be best to import it inindex.js
to be sure.
// src/index.js
import 'react-native-webgpu-three';
- Add the plugins to
babel.config.js
// babel.config.js
modules.exports = {
plugins: [...require('react-native-webgpu-three/babel').plugins],
};
- Add
resolveRequest
andunstable_enablePackageExports
tometro.config.js
// metro.config.js
module.exports = {
resolver: {
resolveRequest: require('react-native-webgpu-three/metro').resolver
.resolveRequest,
unstable_enablePackageExports: true,
},
};
There are a few small changes you will need to make to get your scene working. Below is a simple example taken from the three
GitHub page. It has TODO:
s marking the places we need to change.
import * as THREE from 'three';
const width = window.innerWidth,
height = window.innerHeight; // TODO: Replace web api
// init
const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10);
camera.position.z = 1;
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const renderer = new THREE.WebGLRenderer({antialias: true}); // TODO: Use WebGPURenderer
renderer.setSize(width, height);
renderer.setAnimationLoop(animate);
document.body.appendChild(renderer.domElement); // TODO: Remove web api
// animation
function animate(time) {
mesh.rotation.x = time / 2000;
mesh.rotation.y = time / 1000;
renderer.render(scene, camera);
// TODO: We need to tell the surface to present itself onscreen
}
// TODO: Clean up on unmount and cancel animation loop
Here is a working (TypeScript) example. It has FIXED:
comments to show where the changes were made.
import React from 'react';
import { ThreeWebGpuView, type ThreeWebGpuViewProps } from 'react-native-webgpu-three';
import * as THREE from 'three';
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
export const HelloThree = () => {
const onCreateSurface: ThreeWebGpuViewProps['onCreateSurface'] = async ({ context, rendererParameters }) => {
// FIXED: Use the context to get the width and height instead of window
const {width, height} = context
const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 10);
camera.position.z = 1;
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// FIXED: Use WebGPURenderer
const renderer = new WebGPURenderer({
antialias: true,
// FIXED: Pass correct configuration
...rendererParameters,
});
await renderer.init();
// FIXED: Deleted web api: document.body.appendChild( renderer.domElement )
// animation
function animate(time: number) {
mesh.rotation.x = time / 2000;
mesh.rotation.y = time / 1000;
renderer.render(scene, camera);
// FIXED: Add context.presentSurface() to display the surface
context.presentSurface();
}
renderer.setAnimationLoop(animate);
// FIXED: Return function called on unmount to cancel the animation loop
return () => {
// FIXED: Clear up resources and cancel animation loop
renderer.dispose();
}
};
return <ThreeWebGpuView onCreateSurface={onCreateSurface} style={{flex: 1}} />;
};