WebXR kullanarak etkileyici AR oturumu oluşturma

Bu sayfa, WebXR'yi kullanarak basit bir etkileyici AR uygulaması oluşturma konusunda size yol gösterecektir.

Başlamak için WebXR uyumlu bir geliştirme ortamına ihtiyacınız vardır.

HTML sayfası oluşturma

WebXR'nin oturum başlatabilmesi için kullanıcı etkileşimi gerekir. activateXR() çağıran bir düğme oluşturun. Kullanıcı sayfayı yükledikten sonra bu düğmeyi kullanarak AR deneyimini başlatabilir.

index.html adında yeni bir dosya oluşturun ve aşağıdaki HTML kodunu ekleyin:

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <title>Hello WebXR!</title>

  <!-- three.js -->
  <script src="https://unpkg.com/three@0.126.0/build/three.js"></script>
</head>
<body>

<!-- Starting an immersive WebXR session requires user interaction.
    We start this one with a simple button. -->
<button onclick="activateXR()">Start Hello WebXR</button>
<script>
async function activateXR() {
  // Add a canvas element and initialize a WebGL context that is compatible with WebXR.
  const canvas = document.createElement("canvas");
  document.body.appendChild(canvas);
  const gl = canvas.getContext("webgl", {xrCompatible: true});

  // To be continued in upcoming steps.
}
</script>
</body>
</html>

Two.js'yi başlatma

Başlat düğmesine basıldığında fazla bir şey olmaz. 3D ortam oluşturmak için, bir sahneyi görüntülemek üzere oluşturma kitaplığı kullanabilirsiniz.

Bu örnekte, WebGL oluşturucu sağlayan three.js adlı JavaScript 3D oluşturma kitaplığını kullanacaksınız. Three.js; oluşturma, kameralar ve sahne grafiklerini yöneterek web'de 3D içeriğin görüntülenmesini kolaylaştırır.

Sahne oluşturma

3D ortam genellikle sahne olarak modellenir. AR öğeleri içeren bir THREE.Scene oluşturun. Aşağıdaki kod, artırılmış gerçeklik (AR) modunda ışığı yanmayan renkli bir kutuya bakmanıza olanak tanır.

activateXR() işlevinin en altına şu kodu ekleyin:

const scene = new THREE.Scene();

// The cube will have a different color on each side.
const materials = [
  new THREE.MeshBasicMaterial({color: 0xff0000}),
  new THREE.MeshBasicMaterial({color: 0x0000ff}),
  new THREE.MeshBasicMaterial({color: 0x00ff00}),
  new THREE.MeshBasicMaterial({color: 0xff00ff}),
  new THREE.MeshBasicMaterial({color: 0x00ffff}),
  new THREE.MeshBasicMaterial({color: 0xffff00})
];

// Create the cube and add it to the demo scene.
const cube = new THREE.Mesh(new THREE.BoxBufferGeometry(0.2, 0.2, 0.2), materials);
cube.position.set(1, 1, 1);
scene.add(cube);

Three.js kullanarak oluşturmayı ayarlama

Bu sahneyi artırılmış gerçeklikte (AR) görüntüleyebilmek için bir oluşturucuya ve kameraya ihtiyacınız vardır. Oluşturucu, sahnenizi ekrana çizmek için WebGL'yi kullanır. Kamera, sahnenin görüntülendiği görüntü alanını tanımlar.

activateXR() işlevinin en altına şu kodu ekleyin:

// Set up the WebGLRenderer, which handles rendering to the session's base layer.
const renderer = new THREE.WebGLRenderer({
  alpha: true,
  preserveDrawingBuffer: true,
  canvas: canvas,
  context: gl
});
renderer.autoClear = false;

// The API directly updates the camera matrices.
// Disable matrix auto updates so three.js doesn't attempt
// to handle the matrices independently.
const camera = new THREE.PerspectiveCamera();
camera.matrixAutoUpdate = false;

XRSession oluşturma

WebXR'ye giriş noktası XRSystem.requestSession() üzerinden. Oluşturulan içeriğin gerçek dünyada görüntülenmesini sağlamak için immersive-ar modunu kullanın.

XRReferenceSpace, sanal dünyadaki nesneler için kullanılan koordinat sistemini tanımlar. 'local' modu, kaynağı görüntüleyiciye yakın olan bir referans alanı ve kararlı takibiyle en çok artırılmış gerçeklik (AR) deneyimi için uygundur.

XRSession ve XRReferenceSpace oluşturmak için activateXR() işlevinin alt kısmına şu kodu ekleyin:

// Initialize a WebXR session using "immersive-ar".
const session = await navigator.xr.requestSession("immersive-ar");
session.updateRenderState({
  baseLayer: new XRWebGLLayer(session, gl)
});

// A 'local' reference space has a native origin that is located
// near the viewer's position at the time the session was created.
const referenceSpace = await session.requestReferenceSpace('local');

Sahneyi oluştur

Artık sahneyi oluşturabilirsiniz. XRSession.requestAnimationFrame(), tarayıcı çerçeve çizmeye hazır olduğunda yürütülecek bir geri çağırma planlar.

Animasyon çerçevesi geri çağırma işlemi sırasında, izleyicinin pozunu yerel koordinat alanına göre elde etmek için XRFrame.getViewerPose() yöntemini çağırın. Bu, sahne içi kamerayı güncellemek için kullanılır ve oluşturucu, güncellenmiş kamerayı kullanarak sahneyi çizmeden önce kullanıcının sanal dünyayı görüntüleme şeklini değiştirir.

activateXR() işlevinin en altına şu kodu ekleyin:

// Create a render loop that allows us to draw on the AR view.
const onXRFrame = (time, frame) => {
  // Queue up the next draw request.
  session.requestAnimationFrame(onXRFrame);

  // Bind the graphics framebuffer to the baseLayer's framebuffer
  gl.bindFramebuffer(gl.FRAMEBUFFER, session.renderState.baseLayer.framebuffer)

  // Retrieve the pose of the device.
  // XRFrame.getViewerPose can return null while the session attempts to establish tracking.
  const pose = frame.getViewerPose(referenceSpace);
  if (pose) {
    // In mobile AR, we only have one view.
    const view = pose.views[0];

    const viewport = session.renderState.baseLayer.getViewport(view);
    renderer.setSize(viewport.width, viewport.height)

    // Use the view's transform matrix and projection matrix to configure the THREE.camera.
    camera.matrix.fromArray(view.transform.matrix)
    camera.projectionMatrix.fromArray(view.projectionMatrix);
    camera.updateMatrixWorld(true);

    // Render the scene with THREE.WebGLRenderer.
    renderer.render(scene, camera)
  }
}
session.requestAnimationFrame(onXRFrame);

Hello WebXR'yi çalıştır

Cihazınızda WebXR dosyasına gidin. Renkli bir küpü her yönden görüntüleyebilmeniz gerekir.

İsabet testi ekle

AR dünyasıyla etkileşimde bulunmanın yaygın bir yolu, ışın ve gerçek geometrinin kesişimini bulan isabet testidir. Hello WebXR'de sanal dünyaya ayçiçeği yerleştirmek için bir isabet testi kullanacaksınız.

Demo küpü kaldırın

Aydınlatılmayan küpü kaldırıp ışık içeren bir sahneyle değiştirin:

const scene = new THREE.Scene();

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.3);
directionalLight.position.set(10, 15, 10);
scene.add(directionalLight);

hit-test özelliğini kullanma

İsabet testi işlevini başlatmak için hit-test özelliğiyle oturum isteğinde bulunun. Önceki requestSession() parçasını bulun ve hit-test parçasını ekleyin:

const session = await navigator.xr.requestSession("immersive-ar", {requiredFeatures: ['hit-test']});

Model yükleyici ekle

Şu an için sahnede yalnızca renkli bir küp bulunmaktadır. Deneyimi daha ilgi çekici hale getirmek için GLTF modellerinin yüklenmesine olanak tanıyan bir model yükleyici ekleyin.

Dokümanınızın <head> etiketine three.js' GLTFLoader ifadesini ekleyin.

<!-- three.js -->
<script src="https://unpkg.com/three@0.126.0/build/three.js"></script>

<script src="https://unpkg.com/three@0.126.0/examples/js/loaders/GLTFLoader.js"></script>

GLTF modellerini yükleme

Web'den bir hedefleme retikülü ve ayçiçeği yüklemek için önceki adımda bulunan model yükleyiciyi kullanın.

Bu kodu onXRFrame kodunun üzerine ekleyin:

const loader = new THREE.GLTFLoader();
let reticle;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/reticle/reticle.gltf", function(gltf) {
  reticle = gltf.scene;
  reticle.visible = false;
  scene.add(reticle);
})

let flower;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/sunflower/sunflower.gltf", function(gltf) {
  flower = gltf.scene;
});

// Create a render loop that allows us to draw on the AR view.
const onXRFrame = (time, frame) => {

İsabet testi kaynağı oluşturma

Gerçek nesnelerle kesişimleri hesaplamak için XRSession.requestHitTestSource() kullanarak bir XRHitTestSource oluşturun. İsabet testi için kullanılan ışın, kaynak olarak viewer referans alanına sahiptir, yani isabet testi görüntü alanının merkezinden yapılır.

İsabet testi kaynağı oluşturmak için local referans alanını oluşturduktan sonra şu kodu ekleyin:

// A 'local' reference space has a native origin that is located
// near the viewer's position at the time the session was created.
const referenceSpace = await session.requestReferenceSpace('local');

// Create another XRReferenceSpace that has the viewer as the origin.
const viewerSpace = await session.requestReferenceSpace('viewer');
// Perform hit testing using the viewer as origin.
const hitTestSource = await session.requestHitTestSource({ space: viewerSpace });

Hedefleme retikülü çizme

Ayçiçeğinin yerleştirileceği yeri netleştirmek için sahneye bir hedefleme retikülasyonu ekleyin. Bu manşet, gerçek dünyadaki yüzeylere yapışarak ayçiçeğinin demir atacağı yeri belirtir.

XRFrame.getHitTestResults, bir XRHitTestResult dizisi döndürür ve gerçek geometriye sahip kesişimleri gösterir. Hedefleme noktasını her kareye konumlandırmak için bu kesişimleri kullanın.

camera.projectionMatrix.fromArray(view.projectionMatrix);
camera.updateMatrixWorld(true);

const hitTestResults = frame.getHitTestResults(hitTestSource);
if (hitTestResults.length > 0 && reticle) {
  const hitPose = hitTestResults[0].getPose(referenceSpace);
  reticle.visible = true;
  reticle.position.set(hitPose.transform.position.x, hitPose.transform.position.y, hitPose.transform.position.z)
  reticle.updateMatrixWorld(true);
}

Dokunulduğunda etkileşimler ekleniyor

XRSession, kullanıcı birincil işlemi tamamladığında select etkinlik alır. Artırılmış gerçeklik oturumunda bu, ekrana dokunulmasına karşılık gelir.

Başlatma sırasında şu kodu ekleyerek kullanıcı ekrana dokunduğunda yeni bir ayçiçeğin görünmesini sağlayın:

let flower;
loader.load("https://immersive-web.github.io/webxr-samples/media/gltf/sunflower/sunflower.gltf", function(gltf) {
  flower = gltf.scene;
});

session.addEventListener("select", (event) => {
  if (flower) {
    const clone = flower.clone();
    clone.position.copy(reticle.position);
    scene.add(clone);
  }
});

İsabet testini test etme

Sayfaya gitmek için mobil cihazınızı kullanın. WebXR çevreyi anladıktan sonra retikül gerçek dünyadaki yüzeylerde görünmelidir. Tüm yönlerden görülebilen ayçiçeği yerleştirmek için ekrana dokunun.

Sonraki adımlar