@osobh/reactar
Version:
AR Library for React Native and Expo
184 lines (180 loc) • 7.61 kB
JavaScript
;
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