I am developing an augmented reality application using Three.js, WebXR, and Vue.js version 3. My goal is to add a button that, when pressed, captures a snapshot of the current scene. However, I am facing issues while attempting to take the snapshot. On a mobile device, the captured image is blank, while in the WebXR environment (I am using firefox and chrome with the webxrapi extension to simulate a galax s8 phone) on desktop, I can only see the 3D model with a white background.
Here is the code for my Vue component template:
<template>
<canvas ref="canvas" id="canvas"></canvas>
<div ref="overlay" id="overlay">
<button ref="picture" class="picture-button" v-show="arSessionStarted">
TA BILD
</button>
<button ref="rotate" class="rotation-button" v-show="arSessionStarted">
ROTERA
</button>
</div>
</template>
This is the main function:
init() {
// Create a THREE scene
this.scene = new THREE.Scene()
this.camera = new THREE.PerspectiveCamera(
70,
window.innerWidth / window.innerHeight,
0.1,
20
);
this.camera.position.z = 1;
// CreatE a THREE WebGLRenderer
this.canvas = this.$refs.canvas;
this.gl = this.canvas.getContext('webgl', {xrCompatible: true});
this.renderer = new THREE.WebGLRenderer({
canvas: this.canvas,
context: this.gl,
antialias: true,
alpha: true,
powerPreference: 'high-performance',
xrCompatible: true,
preserveDrawingBuffer: true
});
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.xr.enabled = true;
// Create a THREE light object
const light = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 1);
light.position.set(0.5, 1, 0.25);
this.scene.add(light);
// Load the model and reticle to the scene
this.addReticleToScene();
this.addModelToScene();
// Create THREE controller to place the container
this.controller = this.renderer.xr.getController(0);
this.controller.addEventListener("select", this.onSelect);
this.scene.add(this.controller);
// Create a button to enter a AR session
this.overlay = this.$refs.overlay;
const button = ARButton.createButton(this.renderer, {
requiredFeatures: ["hit-test"],
optionalFeatures: [
"dom-overlay",
"dom-overlay-for-handheld-ar",
],
domOverlay: {
root: this.overlay,
},
});
this.overlay.appendChild(button);
// Add an id to the ar button
button.id = "my-id";
//Initiate the event listeners for the rotate and take picture buttons
this.rotationButton = this.$refs.rotate;
this.takePictureButton = this.$refs.picture;
this.rotationButton.addEventListener('beforexrselect', ev => ev.preventDefault());
this.takePictureButton.addEventListener('beforexrselect', ev => ev.preventDefault());
this.rotationButton.addEventListener('click', () => {
this.rotate();
});
this.takePictureButton.addEventListener('click', () => {
this.takePicture();
});
// Add event listener to adjust the size of the window
window.addEventListener("resize", this.onWindowResize, false);
}
This is thetakePicture function:
takePicture() {
//Take Picture
this.screenshoot = this.renderer.domElement.toDataURL();
console.log(this.screenshoot);
alert("Work in Progress!");
},
This is therenderer:
render(timestamp, frame) {
if (frame) {
if (!this.hitTestSourceInitialized) {
this.initializeHitTestSource();
}
if (this.hitTestSourceInitialized) {
const hitTestResults = frame.getHitTestResults(
this.hitTestSource
);
if (hitTestResults.length > 0) {
const hit = hitTestResults[0];
const pose = hit.getPose(this.localSpace);
this.reticle.visible = true;
this.reticle.matrix.fromArray(pose.transform.matrix);
} else {
this.reticle.visible = false;
}
}
this.renderer.render(this.scene, this.camera);
}
}
animate() {
this.renderer.setAnimationLoop(this.render);
}
I have tried the following:
takePicture() {
//Take Picture
this.screenshoot = this.renderer.domElement.toDataURL();
console.log(this.screenshoot);
alert("Work in Progress!");
},
Thread from stackoverflow: How to capture an image of THREE.Scene uning THREE.PerspectiveCamera?
Thread from stackoverflow: Three.js: How can I make a 2D SnapShot of a Scene as a JPG Image?