import * as GL from 'expo-gl'; import mat4 from 'gl-mat4'; import hsv2rgb from 'hsv2rgb'; import React from 'react'; import { ActivityIndicator, InteractionManager, StyleSheet, View } from 'react-native'; import REGL from 'regl'; const NUM_POINTS = 1e4; const VERT_SIZE = 4 * (4 + 4 + 3); export default class BasicScene extends React.Component { static title = 'GLView example'; static navigationOptions = { title: 'GLView example', }; state = { transitionIsComplete: false, }; componentDidMount() { InteractionManager.runAfterInteractions(() => { this.setState({ transitionIsComplete: true }); }); } render() { if (!this.state.transitionIsComplete) { return ( ); } return ; } _onContextCreate = (gl: GL.ExpoWebGLRenderingContext) => { const regl = REGL({ gl }); const pointBuffer = regl.buffer( Array(NUM_POINTS) .fill(0) .map(() => { const color = hsv2rgb(Math.random() * 360, 0.6, 1); return [ // freq Math.random() * 10, Math.random() * 10, Math.random() * 10, Math.random() * 10, // phase 2.0 * Math.PI * Math.random(), 2.0 * Math.PI * Math.random(), 2.0 * Math.PI * Math.random(), 2.0 * Math.PI * Math.random(), // color color[0] / 255, color[1] / 255, color[2] / 255, ]; }) ); const drawParticles = regl({ vert: ` precision highp float; attribute vec4 freq, phase; attribute vec3 color; uniform float time; uniform mat4 view, projection; varying vec3 fragColor; void main() { vec3 position = 8.0 * cos(freq.xyz * time + phase.xyz); gl_PointSize = 10.0 * (1.0 + cos(freq.w * time + phase.w)); gl_Position = projection * view * vec4(position, 1); fragColor = color; }`, frag: ` precision lowp float; varying vec3 fragColor; void main() { if (length(gl_PointCoord.xy - 0.5) > 0.5) { discard; } gl_FragColor = vec4(fragColor, 1); }`, attributes: { freq: { buffer: pointBuffer, stride: VERT_SIZE, offset: 0, }, phase: { buffer: pointBuffer, stride: VERT_SIZE, offset: 16, }, color: { buffer: pointBuffer, stride: VERT_SIZE, offset: 32, }, }, uniforms: { view: ({ time: t }: { time: number }) => { t = t * 0.1; return mat4.lookAt([], [30 * Math.cos(t), 2.5, 30 * Math.sin(t)], [0, 0, 0], [0, 1, 0]); }, projection: mat4.perspective( [], Math.PI / 4, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.01, 1000 ), time: ({ time }: { time: number }) => time * 0.1, }, count: NUM_POINTS, primitive: 'points', }); const frame = () => { regl.poll(); regl.clear({ color: [0, 0, 0, 1], depth: 1, }); drawParticles(); gl.flush(); gl.endFrameEXP(); requestAnimationFrame(frame); }; frame(); }; }