-
-
Notifications
You must be signed in to change notification settings - Fork 35.9k
WebXRManager: Add Raw Camera Access module. #31487
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
f38f913
4a7217c
72d44b3
a9d27ff
6692d4d
fd6048c
aa4787a
ee0b072
795ef25
f3b67d1
3d76b3a
44a7014
89c906b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>three.js ar - camera access</title> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> | ||
<link type="text/css" rel="stylesheet" href="main.css"> | ||
</head> | ||
<body> | ||
|
||
<div id="info"> | ||
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> ar - camera access<br/> | ||
</div> | ||
|
||
<script type="importmap"> | ||
{ | ||
"imports": { | ||
"three": "../build/three.module.js", | ||
"three/addons/": "./jsm/" | ||
} | ||
} | ||
</script> | ||
|
||
<script type="module"> | ||
|
||
import * as THREE from 'three'; | ||
import { ARButton } from 'three/addons/webxr/ARButton.js'; | ||
|
||
const clock = new THREE.Clock(); | ||
|
||
let camera, scene, renderer; | ||
let cube; | ||
|
||
init(); | ||
|
||
async function init() { | ||
|
||
const container = document.createElement( 'div' ); | ||
document.body.appendChild( container ); | ||
|
||
scene = new THREE.Scene(); | ||
|
||
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 20 ); | ||
|
||
const defaultLight = new THREE.HemisphereLight( 0xffffff, 0xbbbbff, 3 ); | ||
defaultLight.position.set( 0.5, 1, 0.25 ); | ||
scene.add( defaultLight ); | ||
|
||
// | ||
|
||
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); | ||
renderer.setPixelRatio( window.devicePixelRatio ); | ||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
renderer.setAnimationLoop( animate ); | ||
renderer.xr.enabled = true; | ||
container.appendChild( renderer.domElement ); | ||
|
||
// | ||
|
||
document.body.appendChild( ARButton.createButton( renderer, { requiredFeatures: [ 'camera-access' ] } ) ); | ||
|
||
// | ||
|
||
const boxGeometry = new THREE.BoxGeometry( 1, 1, 1 ); | ||
const boxMaterial = new THREE.MeshStandardMaterial(); | ||
cube = new THREE.Mesh( boxGeometry, boxMaterial ); | ||
cube.position.z = -3; | ||
|
||
scene.add( cube ); | ||
|
||
// | ||
|
||
window.addEventListener( 'resize', onWindowResize ); | ||
|
||
} | ||
|
||
function onWindowResize() { | ||
|
||
camera.aspect = window.innerWidth / window.innerHeight; | ||
camera.updateProjectionMatrix(); | ||
|
||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
|
||
} | ||
|
||
// | ||
|
||
function setCameraTexture() { | ||
|
||
if ( ! renderer.xr.getSession() ) { | ||
|
||
if ( cube.material.map ) { | ||
|
||
cube.material.map = null; | ||
cube.material.needsUpdate = true; | ||
|
||
} | ||
|
||
return; | ||
|
||
} | ||
|
||
const frame = renderer.xr.getFrame(); | ||
const referenceSpace = renderer.xr.getReferenceSpace(); | ||
|
||
if ( !frame || !referenceSpace ) return; | ||
|
||
const viewerPose = frame.getViewerPose( referenceSpace ); | ||
|
||
if ( ! viewerPose ) return; | ||
|
||
const view = viewerPose.views.find( view => view.camera ); | ||
|
||
const cameraTexture = renderer.xr.getCameraTexture( view.camera ); | ||
|
||
if ( cube.material.map === cameraTexture ) return; | ||
|
||
cube.material.map = cameraTexture; | ||
cube.material.needsUpdate = true; | ||
|
||
} | ||
|
||
function animate() { | ||
|
||
const delta = clock.getDelta(); | ||
|
||
setCameraTexture(); | ||
|
||
cube.rotation.x += delta; | ||
cube.rotation.y += delta; | ||
|
||
renderer.render( scene, camera ); | ||
|
||
} | ||
|
||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { Texture } from './Texture.js'; | ||
|
||
/** | ||
* Represents a texture created externally from the renderer context. | ||
* | ||
* This may be a texture from a protected media stream, device camera feed, | ||
* or other data feeds like a depth sensor. | ||
* | ||
* Note that this class is only supported in {@link WebGLRenderer} right now. | ||
* | ||
* @augments Texture | ||
*/ | ||
class RawTexture extends Texture { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We also use it for webxr depth textures, but there was some debate about naming in the linked issues and RawTexture was settled on. I could see it being useful for anything that uses raw texture handles, possibly protected content? |
||
|
||
/** | ||
* Creates a new raw texture. | ||
* | ||
* @param {?WebGLTexture} [sourceTexture=null] - The external texture. | ||
*/ | ||
constructor( sourceTexture = null ) { | ||
|
||
super(); | ||
|
||
/** | ||
* The external source texture. | ||
* | ||
* @type {?WebGLTexture} | ||
* @default null | ||
*/ | ||
this.sourceTexture = sourceTexture; | ||
|
||
/** | ||
* This flag can be used for type testing. | ||
* | ||
* @type {boolean} | ||
* @readonly | ||
* @default true | ||
*/ | ||
this.isRawTexture = true; | ||
|
||
} | ||
|
||
} | ||
|
||
export { RawTexture }; |
Uh oh!
There was an error while loading. Please reload this page.