Reference version

This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

Expo GLView iconExpo GLView

一个提供 GLView 的库,GLView 充当 OpenGL ES 渲染目标并提供 GLContext。适用于渲染 2D 和 3D 图形。

Android
iOS
Web
Included in Expo Go

expo-gl provides a View that acts as an OpenGL ES rendering target, suitable for rendering 2D and 3D graphics. When mounted, it creates an OpenGL ES context. Its drawing buffer is presented as the contents of the View on each frame.

安装

Terminal
npx expo install expo-gl

If you are installing this in an existing React Native app, make sure to install expo in your project.

用法

基础 GL 用法
import { View } from 'react-native'; import { GLView } from 'expo-gl'; export default function App() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <GLView style={{ width: 300, height: 300 }} onContextCreate={onContextCreate} /> </View> ); } function onContextCreate(gl) { gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); gl.clearColor(0, 1, 1, 1); // 创建顶点着色器(形状和位置) const vert = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource( vert, ` void main(void) { gl_Position = vec4(0.0, 0.0, 0.0, 1.0); gl_PointSize = 150.0; } ` ); gl.compileShader(vert); // 创建片段着色器(颜色) const frag = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource( frag, ` void main(void) { gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); } ` ); gl.compileShader(frag); // 组合链接成一个程序 const program = gl.createProgram(); gl.attachShader(program, vert); gl.attachShader(program, frag); gl.linkProgram(program); gl.useProgram(program); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.POINTS, 0, 1); gl.flush(); gl.endFrameEXP(); }

高级 API

由于 WebGL API 相当底层,使用底层的 GLView 来渲染时,借助更高级别的图形 API 会更方便。以下库集成了常见的图形 API:

任何支持 WebGL、并且期望使用 WebGLRenderingContext 的库都可以使用。有时这类库会假设 Web 端的 JavaScript 环境(例如假设存在 document)。通常这只是用于资源加载或事件处理,而主要渲染逻辑仍然只使用纯 WebGL。因此,这些库通常仍可通过一些变通方法使用。上面这些 Expo 特定的集成已经为一些常见库提供了这些变通方法。

与 Reanimated worklet 集成

要在 Reanimated worklet 中使用此 API,你需要将 GL 上下文 ID 传递给 worklet,并像下面的示例一样重新创建 GL 对象。

Reanimated worklet 中的 GL 用法
import { View } from 'react-native'; import { runOnUI } from 'react-native-reanimated'; import { GLView } from 'expo-gl'; function render(gl) { 'worklet'; // 在这里添加你的 WebGL 代码 } function onContextCreate(gl) { runOnUI((contextId: number) => { 'worklet'; const gl = GLView.getWorkletContext(contextId); render(gl); })(gl.contextId); } export default function App() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <GLView style={{ width: 300, height: 300 }} enableExperimentalWorkletSupport onContextCreate={onContextCreate} /> </View> ); }

如果你想了解如何在 Reanimated 和 Gesture Handler 中使用 expo-gl 的更深入示例,可以查看这个示例

限制

Worklet 运行时对在其中运行的代码施加了一些限制,因此如果你已经有现成的 WebGL 代码,很可能需要做一些修改才能在 worklet 线程中运行。

  • 像 Pixi.js 或 Three.js 这样的第三方库无法在 worklet 中使用,你只能使用在开头添加了 'worklet' 的函数。
  • 如果你需要加载一些资源传递给 WebGL 代码,需要在主线程中完成,并通过某种引用传递给 worklet。如果你使用的是 expo-assets,你可以直接将由 Asset.fromModule 返回的资源对象,或通过 hook useAssets 获取的资源对象,传递给 runOnUI 函数。
  • 要实现渲染循环,你需要使用 requestAnimationFrame,像 setTimeout 这样的 API 不受支持。

更多信息请查看Reanimated 文档

Remote Debugging and GLView

When remote debugging is enabled, this API does not work as expected. The React Native debugger runs the JavaScript on your computer instead of on the mobile device. GLView requires synchronous native calls, which are not supported in Chrome.

API

import { GLView } from 'expo-gl';

Component

GLView

Android
iOS
Web

Type: React.Component<GLViewProps>

A View that acts as an OpenGL ES render target. On mounting, an OpenGL ES context is created. Its drawing buffer is presented as the contents of the View every frame.

GLViewProps

enableExperimentalWorkletSupport

Android
iOS
Web
Optional • Type: boolean • Default: false

Enables support for interacting with a gl object from code running on the Reanimated worklet thread.

msaaSamples

iOS
Optional • Type: number • Default: 4

GLView can enable iOS's built-in multisampling. This prop specifies the number of samples to use. Setting this to 0 turns off multisampling.

onContextCreate

Android
iOS
Web
Type: (gl: ExpoWebGLRenderingContext) => void

A function that will be called when the OpenGL ES context is created. The function is passed a single argument gl that extends a WebGLRenderingContext interface.

Inherited props

Static methods

createContextAsync()

Android
iOS
Web

Imperative API that creates headless context which is devoid of underlying view. It's useful for headless rendering or in case you want to keep just one context per application and share it between multiple components. It is slightly faster than usual context as it doesn't swap framebuffers and doesn't present them on the canvas, however it may require you to take a snapshot in order to present its results. Note that the context created using createContextAsync has to be destroyed using destroyContextAsync. Also, keep in mind that you need to set up a viewport and create your own framebuffer and texture that you will be drawing to, before you take a snapshot.

A promise that resolves to WebGL context object. See WebGL API for more details.

destroyContextAsync(exgl)

Android
iOS
Web
ParameterTypeDescription
exgl(optional)number | ExpoWebGLRenderingContext

WebGL context to destroy.


Destroys given context. This method is intended to use to destroy headless context created with createContextAsync.

Returns:
Promise<boolean>

A promise that resolves to boolean value that is true if given context existed and has been destroyed successfully.

takeSnapshotAsync(exgl, options)

Android
iOS
Web
ParameterTypeDescription
exgl(optional)number | ExpoWebGLRenderingContext

WebGL context to take a snapshot from.

options(optional)SnapshotOptions
Default:{}

Takes a snapshot of the framebuffer and saves it as a file to app's cache directory.

A promise that resolves to GLSnapshot object.

Component methods

createCameraTextureAsync(cameraRefOrHandle)

Android
iOS
Web
ParameterType
cameraRefOrHandleComponentOrHandle

destroyObjectAsync(glObject)

Android
iOS
Web
ParameterType
glObjectWebGLObject

Returns:
Promise<boolean>

takeSnapshotAsync(options)

Android
iOS
Web
ParameterType
options(optional)SnapshotOptions

Same as static takeSnapshotAsync(), but uses WebGL context that is associated with the view on which the method is called.

Methods

GLView.getWorkletContext(contextId)

Android
iOS
Web
ParameterType
contextIdnumber

Returns:
ExpoWebGLRenderingContext | undefined

Interfaces

ExpoWebGLRenderingContext

Android
iOS
Web

Extends: WebGL2RenderingContext

PropertyTypeDescription
contextIdnumber
-

ExpoWebGLRenderingContext Methods

__expoSetLogging(option)

Android
iOS
Web
ParameterType
optionGLLoggingOption

Returns:
void

_expo_texImage2D(...props)

Android
iOS
Web
ParameterType
...propsany[]

Returns:
void

_expo_texSubImage2D(...props)

Android
iOS
Web
ParameterType
...propsany[]

Returns:
void

endFrameEXP()

Android
iOS
Web
Returns:
void

flushEXP()

Android
iOS
Web
Returns:
void

Types

ComponentOrHandle

Android
iOS
Web

Literal type: union

Acceptable values are: null | number | Component<any, any> | ComponentClass<any>

GLSnapshot

Android
iOS
Web
PropertyTypeDescription
heightnumber

Height of the snapshot.

localUristring

Synonym for uri. Makes snapshot object compatible with texImage2D.

uristring | Blob | null

URI to the snapshot.

widthnumber

Width of the snapshot.

SnapshotOptions

Android
iOS
Web
PropertyTypeDescription
compress(optional)number

A value in range 0 to 1.0 specifying compression level of the result image. 1.0 means no compression and 0 the highest compression.

Default:1.0
flip(optional)boolean

Whether to flip the snapshot vertically.

Default:false
format(optional)'jpeg' | 'png' | 'webp'

Specifies what type of compression should be used and what is the result file extension. PNG compression is lossless but slower, JPEG is faster but the image has visible artifacts.

Default:'jpeg'
framebuffer(optional)WebGLFramebuffer

Specify the framebuffer that we will be reading from. Defaults to underlying framebuffer that is presented in the view or the current framebuffer if context is headless.

rect(optional){ height: number, width: number, x: number, y: number }

Rect to crop the snapshot. It's passed directly to glReadPixels.

SurfaceCreateEvent

Android
iOS
Web
PropertyTypeDescription
nativeEvent{ exglCtxId: number }
-

WebGLObject

Android
iOS
Web
PropertyTypeDescription
idnumber
-

Enums

GLLoggingOption

Android
iOS
Web

DISABLED

GLLoggingOption.DISABLED = 0

Disables logging entirely.

METHOD_CALLS

GLLoggingOption.METHOD_CALLS = 1

Logs method calls, their parameters and results.

GET_ERRORS

GLLoggingOption.GET_ERRORS = 2

Calls gl.getError() after each other method call and prints an error if any is returned. This option has a significant impact on the performance as this method is blocking.

RESOLVE_CONSTANTS

GLLoggingOption.RESOLVE_CONSTANTS = 4

Resolves parameters of type number to their constant names.

TRUNCATE_STRINGS

GLLoggingOption.TRUNCATE_STRINGS = 8

When this option is enabled, long strings will be truncated. It's useful if your shaders are really big and logging them significantly reduces performance.

ALL

GLLoggingOption.ALL = 15

Enables all other options. It implies GET_ERRORS so be aware of the slowdown.

WebGL API

组件挂载并且 OpenGL ES 上下文创建完成后,通过 onContextCreate 属性接收的 gl 对象就会成为 OpenGL ES 上下文的接口,并提供 WebGL API。它类似于 WebGL 2 规范中的 WebGL2RenderingContext

某些较旧的 Android 设备可能不支持 WebGL2 功能。要检查设备是否支持 WebGL2,建议使用 gl instanceof WebGL2RenderingContext

还提供了一个额外的方法 gl.endFrameEXP(),它会通知上下文当前帧已准备好呈现。这类似于其他 OpenGL 平台中的“交换缓冲区”API 调用。

以下 WebGL2RenderingContext 方法目前未实现:

  • getFramebufferAttachmentParameter()
  • getRenderbufferParameter()
  • compressedTexImage2D()
  • compressedTexSubImage2D()
  • getTexParameter()
  • getUniform()
  • getVertexAttrib()
  • getVertexAttribOffset()
  • getBufferSubData()
  • getInternalformatParameter()
  • renderbufferStorageMultisample()
  • compressedTexImage3D()
  • compressedTexSubImage3D()
  • fenceSync()
  • isSync()
  • deleteSync()
  • clientWaitSync()
  • waitSync()
  • getSyncParameter()
  • getActiveUniformBlockParameter()

texImage2D()pixels 参数必须是 null、包含像素数据的 ArrayBuffer,或形如 { localUri } 的对象,其中 localUri 是设备文件系统中某个图像的 file:// URI。因此,在调用 .downloadAsync() 并完成后,会使用 Asset 对象来获取资源。

出于效率考虑,当前这些方法的实现不会对其参数执行类型或边界检查。因此,传入无效参数可能会导致原生崩溃。计划在未来的 SDK 版本中更新 API,以进行参数检查。

目前,错误检查的优先级较低,因为引擎通常并不依赖 OpenGL API 来执行参数检查;否则,由底层 OpenGL ES 实现执行的检查通常已经足够。