UNPKG

@osobh/reactar

Version:

AR Library for React Native and Expo

184 lines (180 loc) 7.61 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const expo_camera_1 = require("expo-camera"); const expo_gl_1 = require("expo-gl"); const Permissions = __importStar(require("expo-permissions")); const react_1 = __importDefault(require("react")); const react_native_1 = require("react-native"); const vertShaderSource = `#version 300 es precision highp float; in vec2 position; out vec2 uv; void main() { uv = position; gl_Position = vec4(1.0 - 2.0 * position, 0, 1); }`; const fragShaderSource = `#version 300 es precision highp float; uniform sampler2D cameraTexture; in vec2 uv; out vec4 fragColor; void main() { fragColor = vec4(1.0 - texture(cameraTexture, uv).rgb, 1.0); }`; class GLCameraScreen extends react_1.default.Component { constructor() { super(...arguments); this.state = { zoom: 0, type: expo_camera_1.CameraType.back, }; this.onContextCreate = async (gl) => { // Create texture asynchronously this.texture = await this.createCameraTexture(); const cameraTexture = this.texture; // Compile vertex and fragment shaders const vertShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertShader, vertShaderSource); gl.compileShader(vertShader); const fragShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragShader, fragShaderSource); gl.compileShader(fragShader); // Link, use program, save and enable attributes const program = gl.createProgram(); gl.attachShader(program, vertShader); gl.attachShader(program, fragShader); gl.linkProgram(program); gl.validateProgram(program); gl.useProgram(program); const positionAttrib = gl.getAttribLocation(program, 'position'); gl.enableVertexAttribArray(positionAttrib); // Create, bind, fill buffer const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); const verts = new Float32Array([-2, 0, 0, -2, 2, 2]); gl.bufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW); // Bind 'position' attribute gl.vertexAttribPointer(positionAttrib, 2, gl.FLOAT, false, 0, 0); // Set 'cameraTexture' uniform gl.uniform1i(gl.getUniformLocation(program, 'cameraTexture'), 0); // Activate unit 0 gl.activeTexture(gl.TEXTURE0); // Render loop const loop = () => { this._rafID = requestAnimationFrame(loop); // Clear gl.clearColor(0, 0, 1, 1); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Bind texture if created gl.bindTexture(gl.TEXTURE_2D, cameraTexture); // Draw! gl.drawArrays(gl.TRIANGLES, 0, verts.length / 2); // Submit frame gl.endFrameEXP(); }; loop(); }; this.toggleFacing = () => { this.setState((state) => ({ type: state.type === expo_camera_1.CameraType.back ? expo_camera_1.CameraType.front : expo_camera_1.CameraType.back, })); }; this.zoomOut = () => { this.setState((state) => ({ zoom: state.zoom - 0.1 < 0 ? 0 : state.zoom - 0.1, })); }; this.zoomIn = () => { this.setState((state) => ({ zoom: state.zoom + 0.1 > 1 ? 1 : state.zoom + 0.1, })); }; } componentWillUnmount() { if (this._rafID !== undefined) { cancelAnimationFrame(this._rafID); } } async createCameraTexture() { const { status } = await Permissions.askAsync(Permissions.CAMERA); if (status !== 'granted') { throw new Error('Denied camera permissions!'); } return this.glView.createCameraTextureAsync(this.camera); } render() { return (react_1.default.createElement(react_native_1.View, { style: styles.container }, react_1.default.createElement(expo_camera_1.Camera, { style: react_native_1.StyleSheet.absoluteFill, type: this.state.type, zoom: this.state.zoom, ref: (ref) => (this.camera = ref) }), react_1.default.createElement(expo_gl_1.GLView, { style: react_native_1.StyleSheet.absoluteFill, onContextCreate: this.onContextCreate, ref: (ref) => (this.glView = ref) }), react_1.default.createElement(react_native_1.View, { style: styles.buttons }, react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.button, onPress: this.toggleFacing }, react_1.default.createElement(react_native_1.Text, null, "Flip")), react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.button, onPress: this.zoomIn }, react_1.default.createElement(react_native_1.Text, null, "Zoom in")), react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.button, onPress: this.zoomOut }, react_1.default.createElement(react_native_1.Text, null, "Zoom out"))))); } } GLCameraScreen.title = 'Expo.Camera integration'; const styles = react_native_1.StyleSheet.create({ container: { flex: 1, flexDirection: 'column', }, camera: Object.assign({}, react_native_1.StyleSheet.absoluteFillObject), buttons: { flex: 1, paddingHorizontal: 10, backgroundColor: 'transparent', flexDirection: 'row', alignItems: 'flex-end', justifyContent: 'space-around', }, button: { flex: 1, height: 40, margin: 10, backgroundColor: 'white', borderRadius: 8, alignItems: 'center', justifyContent: 'center', }, }); exports.default = GLCameraScreen; //# sourceMappingURL=GLCameraScreen.js.map