Etkileyici artırılmış gerçeklik deneyimleri için ARCore Depth API'yi kullanın

1. Başlamadan önce

ARCore, mobil cihazlarda artırılmış gerçeklik (AR) uygulamaları oluşturmaya yönelik bir platformdur. ARCore, farklı API'ler kullanarak kullanıcının cihazının ortamıyla ilgili bilgileri gözlemlemesini ve almasını, ayrıca bu bilgilerle etkileşim kurmasını sağlar.

Bu codelab'de, ARCore Depth API'yi kullanan basit bir AR özellikli uygulama oluşturma sürecini inceleyeceksiniz.

Ön koşullar

Bu kod laboratuvarı, temel AR kavramları hakkında bilgi sahibi olan geliştiriciler için hazırlanmıştır.

Ne oluşturacaksınız?

1a0236e93212210c.gif

Sahnenin geometrisini görselleştirmek ve yerleştirilen sanal öğeler üzerinde kapatma işlemi gerçekleştirmek için her karede derinlik görüntüsünü kullanan bir uygulama oluşturacaksınız. Aşağıdaki adımları uygulayacaksınız:

  • Telefonda Depth API desteğini kontrol etme
  • Her kare için derinlik görüntüsünü alma
  • Derinlik bilgilerini birden fazla şekilde görselleştirme (yukarıdaki animasyona bakın)
  • Kapanma içeren uygulamaların gerçekçiliğini artırmak için derinliği kullanma
  • Derinlik API'sini desteklemeyen telefonları düzgün şekilde işleme

Gerekenler

Donanım Gereksinimleri

Yazılım Gereksinimleri

2. ARCore ve Depth API

Derinlik API'si, derinlik haritaları (derinlik görüntüleri olarak da bilinir) oluşturmak için desteklenen bir cihazın RGB kamerasını kullanır. Derinlik haritası tarafından sağlanan bilgileri kullanarak sanal nesnelerin gerçek dünya nesnelerinin önünde veya arkasında doğru şekilde görünmesini sağlayabilir, böylece sürükleyici ve gerçekçi kullanıcı deneyimleri sunabilirsiniz.

ARCore Depth API, ARCore'un Session'ı tarafından sağlanan her kareyle eşleşen derinlik resimlerine erişim sağlar. Her piksel, kameradan ortama olan mesafeyi ölçerek AR uygulamanızda daha gerçekçi bir deneyim sunar.

Depth API'nin temel özelliklerinden biri örtme'dir: Dijital nesnelerin, gerçek dünyadaki nesnelere göre doğru şekilde görünmesini sağlar. Bu sayede nesneler, kullanıcının bulunduğu ortamdaymış gibi görünür.

Bu codelab, sanal nesnelerin gerçek dünya yüzeylerinin arkasında kapatılmasını sağlamak ve algılanan alan geometrisini görselleştirmek için derinlik görüntülerini kullanan basit bir AR özellikli uygulama oluşturma sürecinde size yol gösterecektir.

3. Hazırlanın

Geliştirme makinesini ayarlama

  1. ARCore cihazınızı USB kablosuyla bilgisayarınıza bağlayın. Cihazınızın USB üzerinden hata ayıklamaya izin verdiğinden emin olun.
  2. Bir terminal açıp aşağıdaki şekilde adb devices komutunu çalıştırın:
adb devices

List of devices attached
<DEVICE_SERIAL_NUMBER>    device

<DEVICE_SERIAL_NUMBER>, cihazınıza özgü bir dize olur. Devam etmeden önce tam olarak bir cihaz gördüğünüzden emin olun.

Code'u indirip yükleyin.

  1. Depoyu klonlayabilirsiniz:
git clone https://github.com/googlecodelabs/arcore-depth

Alternatif olarak, bir ZIP dosyası indirip ayıklayabilirsiniz:

  1. Android Studio'yu başlatın ve Open an existing Android Studio project (Mevcut bir Android Studio projesini aç) seçeneğini tıklayın.
  2. Yukarıda indirilen ZIP dosyasını çıkardığınız dizini bulun ve depth_codelab_io2020 dizinini açın.

Bu, birden fazla modül içeren tek bir Gradle projesidir. Android Studio'nun sol üst kısmındaki Proje bölmesi henüz Proje bölmesinde gösterilmiyorsa açılır menüden Projeler'i tıklayın.

Sonuç şu şekilde görünmelidir:

Bu proje aşağıdaki modülleri içerir:

  • part0_work: Başlangıç uygulaması. Bu Codelab'i yaparken bu modülde düzenlemeler yapmanız gerekir.
  • part1: 1. Bölüm'ü tamamladığınızda düzenlemelerinizin nasıl görüneceğine dair referans kodu.
  • part2: 2. Bölümü tamamlarken referans kodunu kullanın.
  • part3: 3. Bölüm'ü tamamlarken referans kodu.
  • part4_completed: Uygulamanın son sürümü. Bölüm 4'ü ve bu Codelab'i tamamladığınızda referans kodu.

part0_work modülünde çalışacaksınız. Ayrıca, codelab'in her bölümü için eksiksiz çözümler de vardır. Her modül, oluşturulabilir bir uygulamadır.

4. Başlangıç uygulamasını çalıştırma

  1. Run > Run... (Çalıştır > Çalıştır...) seçeneğini tıklayın. > ‘part0_work'. Görüntülenen Select Deployment Target (Dağıtım Hedefini Seç) iletişim kutusunda cihazınız Connected Devices (Bağlı Cihazlar) altında listelenmelidir.
  2. Cihazınızı seçip Tamam'ı tıklayın. Android Studio, ilk uygulamayı oluşturup cihazınızda çalıştırır.
  3. Uygulama, kamera izinleri isteyecektir. Devam etmek için İzin ver'e dokunun.

c5ef65f7a1da0d9.png

Uygulama nasıl kullanılır?

  1. Uygulamanın bir düzlem bulmasına yardımcı olmak için cihazı hareket ettirin. En alttaki mesaj, ne zaman hareket etmeye devam etmeniz gerektiğini gösterir.
  2. Sabitleyiciyi yerleştirmek için düz bir zeminde herhangi bir yere dokunun. Sabitleme noktasının yerleştirildiği yere bir Android şekli çizilir. Bu uygulama, aynı anda yalnızca bir sabitleme noktası yerleştirmenize olanak tanır.
  3. Cihazı hareket ettirin. Cihaz hareket etse bile figür aynı yerde kalmalıdır.

Uygulamanız şu anda çok basit ve gerçek dünyadaki sahne geometrisi hakkında fazla bilgiye sahip değil.

Örneğin, bir Android figürünü sandalyenin arkasına yerleştirirseniz uygulama sandalyenin orada olduğunu ve Android'i gizlemesi gerektiğini bilmediğinden oluşturma işlemi önde duruyormuş gibi görünür.

6182cf62be13cd97.png beb0d327205f80ee.png e4497751c6fad9a7.png

Bu sorunu düzeltmek için bu uygulamada etkileyiciliği ve gerçekçiliği artırmak üzere Depth API'yi kullanacağız.

5. Depth API'nin desteklenip desteklenmediğini kontrol etme (1. Bölüm)

ARCore Depth API yalnızca desteklenen cihazların bir alt kümesinde çalışır. Bu derinlik görüntülerini kullanarak bir uygulamaya işlevsellik entegre etmeden önce uygulamanın desteklenen bir cihazda çalıştığından emin olmanız gerekir.

Mevcut cihazın derinliği destekleyip desteklemediğini depolayan bir işaret görevi gören DepthCodelabActivity adlı sınıfa yeni bir özel üye ekleyin:

private boolean isDepthSupported;

Bu işareti, yeni bir oturumun oluşturulduğu onResume() işlevinin içinden doldurabiliriz.

Mevcut kodu bulun:

// Creates the ARCore session.
session = new Session(/* context= */ this);

Kodu şu şekilde güncelleyin:

// Creates the ARCore session.
session = new Session(/* context= */ this);
Config config = session.getConfig();
isDepthSupported = session.isDepthModeSupported(Config.DepthMode.AUTOMATIC);
if (isDepthSupported) {
  config.setDepthMode(Config.DepthMode.AUTOMATIC);
} else {
  config.setDepthMode(Config.DepthMode.DISABLED);
}
session.configure(config);

Artık AR oturumu uygun şekilde yapılandırıldı ve uygulamanız derinliğe dayalı özellikleri kullanıp kullanamayacağını biliyor.

Ayrıca, bu oturumda derinliğin kullanılıp kullanılmadığını da kullanıcıya bildirmeniz gerekir.

Snackbar'a başka bir mesaj ekleyin. Ekranın alt kısmında görünür:

// Add this line at the top of the file, with the other messages.
private static final String DEPTH_NOT_AVAILABLE_MESSAGE = "[Depth not supported on this device]";

onDrawFrame() içinde, bu mesajı gerektiğinde gösterebilirsiniz:

// Add this if-statement above messageSnackbarHelper.showMessage(this, messageToShow).
if (!isDepthSupported) {
  messageToShow += "\n" + DEPTH_NOT_AVAILABLE_MESSAGE;
}

Uygulamanız derinliği desteklemeyen bir cihazda çalıştırılıyorsa az önce eklediğiniz mesaj en altta görünür:

5c878a7c27833cb2.png

Ardından, uygulamayı Depth API'yi çağıracak ve her kare için derinlik görüntülerini alacak şekilde güncelleyeceksiniz.

6. Derinlik görüntülerini alma (2. Bölüm)

Depth API, cihazın ortamının 3D gözlemlerini yakalar ve bu verileri içeren bir derinlik görüntüsünü uygulamanıza döndürür. Derinlik görüntüsündeki her piksel, cihaz kamerasından gerçek dünya ortamına olan mesafeyi ölçer.

Şimdi, uygulamadaki oluşturma ve görselleştirmeyi iyileştirmek için bu derinlik görüntülerini kullanacaksınız. İlk adım, her kare için derinlik görüntüsünü almak ve bu dokuyu GPU tarafından kullanılacak şekilde bağlamaktır.

Öncelikle projenize yeni bir sınıf ekleyin.
DepthTextureHandler, belirli bir ARCore karesi için derinlik görüntüsünü almaktan sorumludur.
Şu dosyayı ekleyin:

be8d14dfe9656551.png

src/main/java/com/google/ar/core/codelab/depth/DepthTextureHandler.java

package com.google.ar.core.codelab.depth;

import static android.opengl.GLES20.GL_CLAMP_TO_EDGE;
import static android.opengl.GLES20.GL_TEXTURE_2D;
import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_S;
import static android.opengl.GLES20.GL_TEXTURE_WRAP_T;
import static android.opengl.GLES20.GL_UNSIGNED_BYTE;
import static android.opengl.GLES20.glBindTexture;
import static android.opengl.GLES20.glGenTextures;
import static android.opengl.GLES20.glTexImage2D;
import static android.opengl.GLES20.glTexParameteri;
import static android.opengl.GLES30.GL_LINEAR;
import static android.opengl.GLES30.GL_RG;
import static android.opengl.GLES30.GL_RG8;

import android.media.Image;
import com.google.ar.core.Frame;
import com.google.ar.core.exceptions.NotYetAvailableException;

/** Handle RG8 GPU texture containing a DEPTH16 depth image. */
public final class DepthTextureHandler {

  private int depthTextureId = -1;
  private int depthTextureWidth = -1;
  private int depthTextureHeight = -1;

  /**
   * Creates and initializes the depth texture. This method needs to be called on a
   * thread with a EGL context attached.
   */
  public void createOnGlThread() {
    int[] textureId = new int[1];
    glGenTextures(1, textureId, 0);
    depthTextureId = textureId[0];
    glBindTexture(GL_TEXTURE_2D, depthTextureId);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  }

  /**
   * Updates the depth texture with the content from acquireDepthImage16Bits().
   * This method needs to be called on a thread with an EGL context attached.
   */
  public void update(final Frame frame) {
    try {
      Image depthImage = frame.acquireDepthImage16Bits();
      depthTextureWidth = depthImage.getWidth();
      depthTextureHeight = depthImage.getHeight();
      glBindTexture(GL_TEXTURE_2D, depthTextureId);
      glTexImage2D(
          GL_TEXTURE_2D,
          0,
          GL_RG8,
          depthTextureWidth,
          depthTextureHeight,
          0,
          GL_RG,
          GL_UNSIGNED_BYTE,
          depthImage.getPlanes()[0].getBuffer());
      depthImage.close();
    } catch (NotYetAvailableException e) {
      // This normally means that depth data is not available yet.
    }
  }

  public int getDepthTexture() {
    return depthTextureId;
  }

  public int getDepthWidth() {
    return depthTextureWidth;
  }

  public int getDepthHeight() {
    return depthTextureHeight;
  }
}

Şimdi bu sınıfın bir örneğini DepthCodelabActivity'ya ekleyerek her kare için derinlik görüntüsünün kolayca erişilebilen bir kopyasını elde edeceksiniz.

DepthCodelabActivity.java içinde, yeni sınıfımızın bir örneğini özel üye değişkeni olarak ekleyin:

private final DepthTextureHandler depthTexture = new DepthTextureHandler();

Ardından, bu dokuyu başlatmak için onSurfaceCreated() yöntemini güncelleyin. Böylece doku, GPU gölgelendiricilerimiz tarafından kullanılabilir:

// Put this at the top of the "try" block in onSurfaceCreated().
depthTexture.createOnGlThread();

Son olarak, bu dokuyu her karede en son derinlik görüntüsüyle doldurmanız gerekir. Bu işlem, session'dan alınan en son karede yukarıda oluşturduğunuz update() yöntemini çağırarak yapılabilir.
Bu uygulamada derinlik desteği isteğe bağlı olduğundan bu aramayı yalnızca derinlik kullanıyorsanız yapın.

// Add this just after "frame" is created inside onDrawFrame().
if (isDepthSupported) {
  depthTexture.update(frame);
}

Artık her karede güncellenen bir derinlik görüntünüz var. Bu doku, gölgelendiricileriniz tarafından kullanılmaya hazırdır.

Ancak uygulamanın davranışıyla ilgili henüz bir değişiklik yapılmadı. Şimdi uygulamanızı geliştirmek için derinlik görüntüsünü kullanacaksınız.

7. Derinlik görüntüsünü oluşturma (3. Bölüm)

Artık derinlik görüntünüzü kullanmaya başlayabilirsiniz. Bu bölümde, her karenin derinliğini oluşturmak için uygulamaya bir düğme ekleyeceksiniz.

Yeni gölgelendiriciler ekleme

Derinlik görüntüsünü görüntülemenin birçok yolu vardır. Aşağıdaki gölgelendiriciler, basit bir renk eşleme görselleştirmesi sağlar.

Yeni bir .vert shader ekleme

Android Studio'da:

  1. Öncelikle yeni .vert ve .frag gölgelendiricileri src/main/assets/shaders/ dizinine ekleyin.
  2. Gölgelendiriciler dizinini sağ tıklayın.
  3. Yeni -> Dosya'yı seçin.
  4. background_show_depth_map.vert olarak adlandırın.
  5. Metin dosyası olarak ayarlayın.

Yeni dosyaya aşağıdaki kodu ekleyin:

src/main/assets/shaders/background_show_depth_map.vert

attribute vec4 a_Position;
attribute vec2 a_TexCoord;

varying vec2 v_TexCoord;

void main() {
   v_TexCoord = a_TexCoord;
   gl_Position = a_Position;
}

Aynı dizinde parça gölgelendirici oluşturmak için yukarıdaki adımları tekrarlayın ve dosyayı background_show_depth_map.frag olarak adlandırın.

Bu yeni dosyaya aşağıdaki kodu ekleyin:

src/main/assets/shaders/background_show_depth_map.frag

precision mediump float;
uniform sampler2D u_Depth;
varying vec2 v_TexCoord;
const highp float kMaxDepth = 20000.0; // In millimeters.

float GetDepthMillimeters(vec4 depth_pixel_value) {
  return 255.0 * (depth_pixel_value.r + depth_pixel_value.g * 256.0);
}

// Returns an interpolated color in a 6 degree polynomial interpolation.
vec3 GetPolynomialColor(in float x,
  in vec4 kRedVec4, in vec4 kGreenVec4, in vec4 kBlueVec4,
  in vec2 kRedVec2, in vec2 kGreenVec2, in vec2 kBlueVec2) {
  // Moves the color space a little bit to avoid pure red.
  // Removes this line for more contrast.
  x = clamp(x * 0.9 + 0.03, 0.0, 1.0);
  vec4 v4 = vec4(1.0, x, x * x, x * x * x);
  vec2 v2 = v4.zw * v4.z;
  return vec3(
    dot(v4, kRedVec4) + dot(v2, kRedVec2),
    dot(v4, kGreenVec4) + dot(v2, kGreenVec2),
    dot(v4, kBlueVec4) + dot(v2, kBlueVec2)
  );
}

// Returns a smooth Percept colormap based upon the Turbo colormap.
vec3 PerceptColormap(in float x) {
  const vec4 kRedVec4 = vec4(0.55305649, 3.00913185, -5.46192616, -11.11819092);
  const vec4 kGreenVec4 = vec4(0.16207513, 0.17712472, 15.24091500, -36.50657960);
  const vec4 kBlueVec4 = vec4(-0.05195877, 5.18000081, -30.94853351, 81.96403246);
  const vec2 kRedVec2 = vec2(27.81927491, -14.87899417);
  const vec2 kGreenVec2 = vec2(25.95549545, -5.02738237);
  const vec2 kBlueVec2 = vec2(-86.53476570, 30.23299484);
  const float kInvalidDepthThreshold = 0.01;
  return step(kInvalidDepthThreshold, x) *
         GetPolynomialColor(x, kRedVec4, kGreenVec4, kBlueVec4,
                            kRedVec2, kGreenVec2, kBlueVec2);
}

void main() {
  vec4 packed_depth = texture2D(u_Depth, v_TexCoord.xy);
  highp float depth_mm = GetDepthMillimeters(packed_depth);
  highp float normalized_depth = depth_mm / kMaxDepth;
  vec4 depth_color = vec4(PerceptColormap(normalized_depth), 1.0);
  gl_FragColor = depth_color;
}

Ardından, BackgroundRenderer sınıfını src/main/java/com/google/ar/core/codelab/common/rendering/BackgroundRenderer.java konumundaki bu yeni gölgelendiricileri kullanacak şekilde güncelleyin.

Sınıfın en üstüne gölgelendiricilerin dosya yollarını ekleyin:

// Add these under the other shader names at the top of the class.
private static final String DEPTH_VERTEX_SHADER_NAME = "shaders/background_show_depth_map.vert";
private static final String DEPTH_FRAGMENT_SHADER_NAME = "shaders/background_show_depth_map.frag";

İki gölgelendirici çalıştırılacağından BackgroundRenderer sınıfına daha fazla üye değişkeni ekleyin:

// Add to the top of file with the rest of the member variables.
private int depthProgram;
private int depthTextureParam;
private int depthTextureId = -1;
private int depthQuadPositionParam;
private int depthQuadTexCoordParam;

Bu alanları doldurmak için yeni bir yöntem ekleyin:

// Add this method below createOnGlThread().
public void createDepthShaders(Context context, int depthTextureId) throws IOException {
  int vertexShader =
      ShaderUtil.loadGLShader(
          TAG, context, GLES20.GL_VERTEX_SHADER, DEPTH_VERTEX_SHADER_NAME);
  int fragmentShader =
      ShaderUtil.loadGLShader(
          TAG, context, GLES20.GL_FRAGMENT_SHADER, DEPTH_FRAGMENT_SHADER_NAME);

  depthProgram = GLES20.glCreateProgram();
  GLES20.glAttachShader(depthProgram, vertexShader);
  GLES20.glAttachShader(depthProgram, fragmentShader);
  GLES20.glLinkProgram(depthProgram);
  GLES20.glUseProgram(depthProgram);
  ShaderUtil.checkGLError(TAG, "Program creation");

  depthTextureParam = GLES20.glGetUniformLocation(depthProgram, "u_Depth");
  ShaderUtil.checkGLError(TAG, "Program parameters");

  depthQuadPositionParam = GLES20.glGetAttribLocation(depthProgram, "a_Position");
  depthQuadTexCoordParam = GLES20.glGetAttribLocation(depthProgram, "a_TexCoord");

  this.depthTextureId = depthTextureId;
}

Her karede bu gölgelendiricilerle çizim yapmak için kullanılan şu yöntemi ekleyin:

// Put this at the bottom of the file.
public void drawDepth(@NonNull Frame frame) {
  if (frame.hasDisplayGeometryChanged()) {
    frame.transformCoordinates2d(
        Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
        quadCoords,
        Coordinates2d.TEXTURE_NORMALIZED,
        quadTexCoords);
  }

  if (frame.getTimestamp() == 0 || depthTextureId == -1) {
    return;
  }

  // Ensure position is rewound before use.
  quadTexCoords.position(0);

  // No need to test or write depth, the screen quad has arbitrary depth, and is expected
  // to be drawn first.
  GLES20.glDisable(GLES20.GL_DEPTH_TEST);
  GLES20.glDepthMask(false);

  GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, depthTextureId);
  GLES20.glUseProgram(depthProgram);
  GLES20.glUniform1i(depthTextureParam, 0);

  // Set the vertex positions and texture coordinates.
  GLES20.glVertexAttribPointer(
        depthQuadPositionParam, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadCoords);
  GLES20.glVertexAttribPointer(
        depthQuadTexCoordParam, TEXCOORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, quadTexCoords);

  // Draws the quad.
  GLES20.glEnableVertexAttribArray(depthQuadPositionParam);
  GLES20.glEnableVertexAttribArray(depthQuadTexCoordParam);
  GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
  GLES20.glDisableVertexAttribArray(depthQuadPositionParam);
  GLES20.glDisableVertexAttribArray(depthQuadTexCoordParam);

  // Restore the depth state for further drawing.
  GLES20.glDepthMask(true);
  GLES20.glEnable(GLES20.GL_DEPTH_TEST);

  ShaderUtil.checkGLError(TAG, "BackgroundRendererDraw");
}

Açma/kapatma düğmesi ekleme

Artık derinlik haritasını oluşturma özelliğine sahipsiniz. Bu özelliği kullanın. Bu oluşturmayı açıp kapatan bir düğme ekleyin.

DepthCodelabActivity dosyasının en üstüne, kullanılacak düğme için bir içe aktarma işlemi ekleyin:

import android.widget.Button;

Derinlik oluşturmanın etkin olup olmadığını belirten bir boole üyesi eklemek için sınıfı güncelleyin (varsayılan olarak devre dışıdır):

private boolean showDepthMap = false;

Ardından, showDepthMap boolean'ını kontrol eden düğmeyi onCreate() yönteminin sonuna ekleyin:

final Button toggleDepthButton = (Button) findViewById(R.id.toggle_depth_button);
    toggleDepthButton.setOnClickListener(
        view -> {
          if (isDepthSupported) {
            showDepthMap = !showDepthMap;
            toggleDepthButton.setText(showDepthMap ? R.string.hide_depth : R.string.show_depth);
          } else {
            showDepthMap = false;
            toggleDepthButton.setText(R.string.depth_not_available);
          }
        });

res/values/strings.xml dosyasına şu dizeleri ekleyin:

<string translatable="false" name="show_depth">Show Depth</string>
<string translatable="false" name="hide_depth">Hide Depth</string>
<string translatable="false" name="depth_not_available">Depth Not Available</string>

Bu düğmeyi res/layout/activity_main.xml uygulamasındaki uygulama düzeninin en altına ekleyin:

<Button
    android:id="@+id/toggle_depth_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="20dp"
    android:gravity="center"
    android:text="@string/show_depth"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"/>

Düğme artık showDepthMap Boole değerini kontrol ediyor. Derinlik haritasının oluşturulup oluşturulmayacağını kontrol etmek için bu işareti kullanın.

DepthCodelabActivity içindeki onDrawFrame() yöntemine geri dönün ve şunları ekleyin:

// Add this snippet just under backgroundRenderer.draw(frame);
if (showDepthMap) {
  backgroundRenderer.drawDepth(frame);
}

onSurfaceCreated() içine aşağıdaki satırı ekleyerek derinlik dokusunu backgroundRenderer öğesine iletin:

// Add to onSurfaceCreated() after backgroundRenderer.createonGlThread(/*context=*/ this);
backgroundRenderer.createDepthShaders(/*context=*/ this, depthTexture.getDepthTexture());

Artık ekranın sağ üst kısmındaki düğmeye basarak her karenin derinlik görüntüsünü görebilirsiniz.

Depth API desteği olmadan çalıştırma

Depth API desteğiyle çalıştırma

[İsteğe bağlı] Gelişmiş derinlik animasyonu

Uygulama şu anda derinlik haritasını doğrudan gösteriyor. Kırmızı pikseller, yakın alanları gösterir. Mavi pikseller, uzak alanları gösterir.

Derinlik bilgilerini aktarmanın birçok yolu vardır. Bu bölümde, gölgelendiriciyi yalnızca kameradan tekrar tekrar uzaklaşan bantlar içindeki derinliği gösterecek şekilde değiştirerek gölgelendiriciyi derinliği periyodik olarak titreşecek şekilde değiştireceksiniz.

İlk olarak, background_show_depth_map.frag dosyasının en üstüne aşağıdaki değişkenleri ekleyin:

uniform float u_DepthRangeToRenderMm;
const float kDepthWidthToRenderMm = 350.0;
  • Ardından, bu değerleri kullanarak gölgelendiricinin main() işlevinde hangi piksellerin derinlik değerleriyle kaplanacağını filtreleyin:
// Add this line at the end of main().
gl_FragColor.a = clamp(1.0 - abs((depth_mm - u_DepthRangeToRenderMm) / kDepthWidthToRenderMm), 0.0, 1.0);

Ardından, bu gölgelendirici parametrelerini korumak için BackgroundRenderer.java öğesini güncelleyin. Sınıfın en üstüne aşağıdaki alanları ekleyin:

private static final float MAX_DEPTH_RANGE_TO_RENDER_MM = 20000.0f;
private float depthRangeToRenderMm = 0.0f;
private int depthRangeToRenderMmParam;

createDepthShaders() yönteminin içine, bu parametreleri gölgelendirici programıyla eşleştirmek için aşağıdakileri ekleyin:

depthRangeToRenderMmParam = GLES20.glGetUniformLocation(depthProgram, "u_DepthRangeToRenderMm");
  • Son olarak, bu aralığı zaman içinde drawDepth() yöntemiyle kontrol edebilirsiniz. Aşağıdaki kodu ekleyin. Bu kod, her çerçeve çizildiğinde bu aralığı artırır:
// Enables alpha blending.
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

// Updates range each time draw() is called.
depthRangeToRenderMm += 50.0f;
if (depthRangeToRenderMm > MAX_DEPTH_RANGE_TO_RENDER_MM) {
  depthRangeToRenderMm = 0.0f;
}

// Passes latest value to the shader.
GLES20.glUniform1f(depthRangeToRenderMmParam, depthRangeToRenderMm);

Artık derinlik, sahnenizde akan animasyonlu bir titreşim olarak görselleştiriliyor.

b846e4365d7b69b1.gif

Burada sağlanan değerleri değiştirerek titreşimi daha yavaş, daha hızlı, daha geniş, daha dar vb. hale getirebilirsiniz. Ayrıca, gölgelendiriciyi derinlik bilgilerini gösterecek şekilde değiştirmenin yepyeni yollarını da keşfedebilirsiniz.

8. Örtme için Depth API'yi kullanma (4. Bölüm)

Artık uygulamanızda nesne tıkanmasını işleyeceksiniz.

Kapanma, sanal nesne ile kamera arasında gerçek nesneler olduğundan sanal nesnenin tam olarak oluşturulamaması durumunu ifade eder. Kapanmayı yönetmek, AR deneyimlerinin etkileyici olması için çok önemlidir.

Sanal nesnelerin gerçek zamanlı olarak doğru şekilde oluşturulması, artırılmış sahnenin gerçekçiliğini ve inanılırlığını artırır. Daha fazla örnek için lütfen Derinlik API'si ile gerçeklikleri harmanlama konulu videomuzu inceleyin.

Bu bölümde, yalnızca derinlik mevcutsa uygulamanızı sanal nesneler içerecek şekilde güncelleyeceksiniz.

Yeni nesne gölgelendiricileri ekleme

Önceki bölümlerde olduğu gibi, derinlik bilgilerini desteklemek için yeni gölgelendiriciler ekleyeceksiniz. Bu kez mevcut nesne gölgelendiricilerini kopyalayabilir ve tıkanma işlevini ekleyebilirsiniz.

Uygulamanızın derinliği destekleyip desteklemeyeceğine çalışma zamanında karar verebilmesi için nesne gölgelendiricilerinin her iki sürümünü de saklamanız önemlidir.

object.vert ve object.frag gölgelendirici dosyalarının src/main/assets/shaders dizininde kopyalarını oluşturun.

  • object.vert dosyasını hedef dosya src/main/assets/shaders/occlusion_object.vert konumuna kopyalama
  • object.frag dosyasını hedef dosya src/main/assets/shaders/occlusion_object.frag konumuna kopyalama

occlusion_object.vert içinde, main()'nin üstüne aşağıdaki değişkeni ekleyin:

varying vec3 v_ScreenSpacePosition;

Bu değişkeni main() bölümünün en altında ayarlayın:

v_ScreenSpacePosition = gl_Position.xyz / gl_Position.w;

Dosyanın en üst kısmındaki main() öğesinin üzerine şu değişkenleri ekleyerek occlusion_object.frag öğesini güncelleyin:

varying vec3 v_ScreenSpacePosition;

uniform sampler2D u_Depth;
uniform mat3 u_UvTransform;
uniform float u_DepthTolerancePerMm;
uniform float u_OcclusionAlpha;
uniform float u_DepthAspectRatio;
  • Derinlik bilgileriyle çalışmayı kolaylaştırmak için bu yardımcı işlevleri gölgelendiricide main() işaretinin üzerine ekleyin:
float GetDepthMillimeters(in vec2 depth_uv) {
  // Depth is packed into the red and green components of its texture.
  // The texture is a normalized format, storing millimeters.
  vec3 packedDepthAndVisibility = texture2D(u_Depth, depth_uv).xyz;
  return dot(packedDepthAndVisibility.xy, vec2(255.0, 256.0 * 255.0));
}

// Returns linear interpolation position of value between min and max bounds.
// E.g., InverseLerp(1100, 1000, 2000) returns 0.1.
float InverseLerp(in float value, in float min_bound, in float max_bound) {
  return clamp((value - min_bound) / (max_bound - min_bound), 0.0, 1.0);
}

// Returns a value between 0.0 (not visible) and 1.0 (completely visible)
// Which represents how visible or occluded is the pixel in relation to the
// depth map.
float GetVisibility(in vec2 depth_uv, in float asset_depth_mm) {
  float depth_mm = GetDepthMillimeters(depth_uv);

  // Instead of a hard z-buffer test, allow the asset to fade into the
  // background along a 2 * u_DepthTolerancePerMm * asset_depth_mm
  // range centered on the background depth.
  float visibility_occlusion = clamp(0.5 * (depth_mm - asset_depth_mm) /
    (u_DepthTolerancePerMm * asset_depth_mm) + 0.5, 0.0, 1.0);

  // Depth close to zero is most likely invalid, do not use it for occlusions.
  float visibility_depth_near = 1.0 - InverseLerp(
      depth_mm, /*min_depth_mm=*/150.0, /*max_depth_mm=*/200.0);

  // Same for very high depth values.
  float visibility_depth_far = InverseLerp(
      depth_mm, /*min_depth_mm=*/17500.0, /*max_depth_mm=*/20000.0);

  float visibility =
    max(max(visibility_occlusion, u_OcclusionAlpha),
      max(visibility_depth_near, visibility_depth_far));

  return visibility;
}

Artık occlusion_object.frag içindeki main() öğesini derinlik algılayacak şekilde güncelleyebilir ve kapatma uygulayabilirsiniz. Dosyanın en altına aşağıdaki satırları ekleyin:

const float kMToMm = 1000.0;
float asset_depth_mm = v_ViewPosition.z * kMToMm * -1.;
vec2 depth_uvs = (u_UvTransform * vec3(v_ScreenSpacePosition.xy, 1)).xy;
gl_FragColor.a *= GetVisibility(depth_uvs, asset_depth_mm);

Artık nesne gölgelendiricilerinizin yeni bir sürümüne sahip olduğunuz için oluşturucu kodunu değiştirebilirsiniz.

Nesne aydınlatmasını oluşturma

ObjectRenderer bölümünde bulunan src/main/java/com/google/ar/core/codelab/common/rendering/ObjectRenderer.java sınıfının kopyasını oluşturun.

  • ObjectRenderer sınıfını seçin.
  • Sağ tıklayın > Kopyala
  • Rendering klasörünü seçin.
  • Sağ tıklayın > Yapıştır'ı seçin.

7487ece853690c31.png

  • Sınıfı OcclusionObjectRenderer olarak yeniden adlandırın.

760a4c80429170c2.png

Yeni, yeniden adlandırılmış sınıf artık aynı klasörde görünmelidir:

9335c373dc60cd17.png

Yeni oluşturulan OcclusionObjectRenderer.java dosyasını açın ve dosyanın üst kısmındaki gölgelendirici yollarını değiştirin:

private static final String VERTEX_SHADER_NAME = "shaders/occlusion_object.vert";
private static final String FRAGMENT_SHADER_NAME = "shaders/occlusion_object.frag";
  • Bu derinlikle ilgili üye değişkenlerini sınıfın en üstündeki diğer değişkenlerle birlikte ekleyin. Değişkenler, tıkanma kenarlığının keskinliğini ayarlar.
// Shader location: depth texture
private int depthTextureUniform;

// Shader location: transform to depth uvs
private int depthUvTransformUniform;

// Shader location: depth tolerance property
private int depthToleranceUniform;

// Shader location: maximum transparency for the occluded part.
private int occlusionAlphaUniform;

private int depthAspectRatioUniform;

private float[] uvTransform = null;
private int depthTextureId;

Sınıfın en üstünde varsayılan değerlere sahip şu üye değişkenlerini oluşturun:

// These values will be changed each frame based on the distance to the object.
private float depthAspectRatio = 0.0f;
private final float depthTolerancePerMm = 0.015f;
private final float occlusionsAlpha = 0.0f;

createOnGlThread() yönteminde gölgelendirici için tek tip parametreleri başlatın:

// Occlusions Uniforms.  Add these lines before the first call to ShaderUtil.checkGLError
// inside the createOnGlThread() method.
depthTextureUniform = GLES20.glGetUniformLocation(program, "u_Depth");
depthUvTransformUniform = GLES20.glGetUniformLocation(program, "u_UvTransform");
depthToleranceUniform = GLES20.glGetUniformLocation(program, "u_DepthTolerancePerMm");
occlusionAlphaUniform = GLES20.glGetUniformLocation(program, "u_OcclusionAlpha");
depthAspectRatioUniform = GLES20.glGetUniformLocation(program, "u_DepthAspectRatio");
  • draw() yöntemini güncelleyerek bu değerlerin her çizildiklerinde güncellendiğinden emin olun:
// Add after other GLES20.glUniform calls inside draw().
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, depthTextureId);
GLES20.glUniform1i(depthTextureUniform, 1);
GLES20.glUniformMatrix3fv(depthUvTransformUniform, 1, false, uvTransform, 0);
GLES20.glUniform1f(depthToleranceUniform, depthTolerancePerMm);
GLES20.glUniform1f(occlusionAlphaUniform, occlusionsAlpha);
GLES20.glUniform1f(depthAspectRatioUniform, depthAspectRatio);

Oluşturma işleminde karıştırma modunu etkinleştirmek için draw() içine aşağıdaki satırları ekleyin. Böylece, sanal nesneler kapatıldığında şeffaflık uygulanabilir:

// Add these lines just below the code-block labeled "Enable vertex arrays"
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
// Add these lines just above the code-block labeled "Disable vertex arrays"
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDepthMask(true);
  • OcclusionObjectRenderer numaralı telefondan arayanların derinlik bilgilerini sağlayabilmesi için aşağıdaki yöntemleri ekleyin:
// Add these methods at the bottom of the OcclusionObjectRenderer class.
public void setUvTransformMatrix(float[] transform) {
  uvTransform = transform;
}

public void setDepthTexture(int textureId, int width, int height) {
  depthTextureId = textureId;
  depthAspectRatio = (float) width / (float) height;
}

Nesne aydınlatmasını kontrol etme

Artık yeni bir OcclusionObjectRenderer öğeniz olduğuna göre bunu DepthCodelabActivity öğenize ekleyebilir ve tıkanma oluşturma özelliğini ne zaman ve nasıl kullanacağınızı seçebilirsiniz.

OcclusionObjectRenderer ve ObjectRenderer öğelerinin her ikisi de DepthCodelabActivity öğesinin üyesi olacak şekilde, etkinliğe OcclusionObjectRenderer örneği ekleyerek bu mantığı etkinleştirin:

// Add this include at the top of the file.
import com.google.ar.core.codelab.common.rendering.OcclusionObjectRenderer;
// Add this member just below the existing "virtualObject", so both are present.
private final OcclusionObjectRenderer occludedVirtualObject = new OcclusionObjectRenderer();
  • Ardından, mevcut cihazın Depth API'yi destekleyip desteklemediğine bağlı olarak bu occludedVirtualObject öğesinin ne zaman kullanılacağını kontrol edebilirsiniz. Bu satırları onSurfaceCreated yönteminin içine, virtualObject yapılandırıldıktan sonra ekleyin:
if (isDepthSupported) {
  occludedVirtualObject.createOnGlThread(/*context=*/ this, "models/andy.obj", "models/andy.png");
  occludedVirtualObject.setDepthTexture(
     depthTexture.getDepthTexture(),
     depthTexture.getDepthWidth(),
     depthTexture.getDepthHeight());
  occludedVirtualObject.setMaterialProperties(0.0f, 2.0f, 0.5f, 6.0f);
}

Derinliğin desteklenmediği cihazlarda occludedVirtualObject örneği oluşturulur ancak kullanılmaz. Derinlik sensörlü telefonlarda her iki sürüm de başlatılır ve çizim sırasında hangi oluşturucu sürümünün kullanılacağına çalışma zamanında karar verilir.

onDrawFrame() yönteminin içinde mevcut kodu bulun:

virtualObject.updateModelMatrix(anchorMatrix, scaleFactor);
virtualObject.draw(viewmtx, projmtx, colorCorrectionRgba, OBJECT_COLOR);

Bu kodu aşağıdakiyle değiştirin:

if (isDepthSupported) {
  occludedVirtualObject.updateModelMatrix(anchorMatrix, scaleFactor);
  occludedVirtualObject.draw(viewmtx, projmtx, colorCorrectionRgba, OBJECT_COLOR);
} else {
  virtualObject.updateModelMatrix(anchorMatrix, scaleFactor);
  virtualObject.draw(viewmtx, projmtx, colorCorrectionRgba, OBJECT_COLOR);
}

Son olarak, derinlik görüntüsünün çıkış oluşturma işlemine doğru şekilde eşlendiğinden emin olun. Derinlik görüntüsü farklı bir çözünürlüğe ve muhtemelen ekranınızdan farklı bir en-boy oranına sahip olduğundan doku koordinatları, derinlik görüntüsü ile kamera görüntüsü arasında farklı olabilir.

  • Dosyanın en altına getTextureTransformMatrix() yardımcı yöntemini ekleyin. Bu yöntem, uygulandığında ekran alanı UV'lerinin kamera feed'ini oluşturmak için kullanılan dörtgen doku koordinatlarıyla doğru şekilde eşleşmesini sağlayan bir dönüşüm matrisi döndürür. Cihazın yönünü de dikkate alır.
private static float[] getTextureTransformMatrix(Frame frame) {
  float[] frameTransform = new float[6];
  float[] uvTransform = new float[9];
  // XY pairs of coordinates in NDC space that constitute the origin and points along the two
  // principal axes.
  float[] ndcBasis = {0, 0, 1, 0, 0, 1};

  // Temporarily store the transformed points into outputTransform.
  frame.transformCoordinates2d(
      Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
      ndcBasis,
      Coordinates2d.TEXTURE_NORMALIZED,
      frameTransform);

  // Convert the transformed points into an affine transform and transpose it.
  float ndcOriginX = frameTransform[0];
  float ndcOriginY = frameTransform[1];
  uvTransform[0] = frameTransform[2] - ndcOriginX;
  uvTransform[1] = frameTransform[3] - ndcOriginY;
  uvTransform[2] = 0;
  uvTransform[3] = frameTransform[4] - ndcOriginX;
  uvTransform[4] = frameTransform[5] - ndcOriginY;
  uvTransform[5] = 0;
  uvTransform[6] = ndcOriginX;
  uvTransform[7] = ndcOriginY;
  uvTransform[8] = 1;

  return uvTransform;
}

getTextureTransformMatrix() için dosyanın en üstüne şu içe aktarma işlemi gerekir:

import com.google.ar.core.Coordinates2d;

Ekran dokusu her değiştiğinde (ör. ekran döndürüldüğünde) bu doku koordinatları arasındaki dönüşümü hesaplamak istiyorsunuz. Bu işlev sınırlı erişime sahiptir.

Dosyanın en üstüne aşağıdaki işareti ekleyin:

// Add this member at the top of the file.
private boolean calculateUVTransform = true;
  • onDrawFrame() içinde, çerçeve ve kamera oluşturulduktan sonra depolanan dönüşümün yeniden hesaplanması gerekip gerekmediğini kontrol edin:
// Add these lines inside onDrawFrame() after frame.getCamera().
if (frame.hasDisplayGeometryChanged() || calculateUVTransform) {
  calculateUVTransform = false;
  float[] transform = getTextureTransformMatrix(frame);
  occludedVirtualObject.setUvTransformMatrix(transform);
}

Bu değişiklikler yapıldıktan sonra uygulamayı artık sanal nesne kapatma özelliğiyle çalıştırabilirsiniz.

Uygulamanız artık tüm telefonlarda sorunsuz bir şekilde çalışmalı ve desteklendiğinde otomatik olarak derinlik-kapanma özelliğini kullanmalıdır.

Derinlik API'si desteğiyle uygulama çalıştırma

Uygulamayı Depth API desteği olmadan çalıştırma

9. [İsteğe bağlı] Kapanma kalitesini iyileştirme

Yukarıda uygulanan derinliğe dayalı kapatma yöntemi, keskin sınırlara sahip kapatma sağlar. Kamera nesneden uzaklaştıkça derinlik ölçümleri daha az doğru olabilir ve bu durum görsel bozulmalara neden olabilir.

Bu sorunu, kapama testine ek bulanıklık uygulayarak çözebiliriz. Bu sayede, gizli sanal nesnelerin kenarları daha yumuşak olur.

occlusion_object.frag

occlusion_object.frag dosyasının en üstüne aşağıdaki tek tip değişkeni ekleyin:

uniform float u_OcclusionBlurAmount;

Bu yardımcı işlevi, gölgelendiricide main()'nın hemen üstüne ekleyin. Bu işlev, tıkanma örneklemeye çekirdek bulanıklığı uygular:

float GetBlurredVisibilityAroundUV(in vec2 uv, in float asset_depth_mm) {
  // Kernel used:
  // 0   4   7   4   0
  // 4   16  26  16  4
  // 7   26  41  26  7
  // 4   16  26  16  4
  // 0   4   7   4   0
  const float kKernelTotalWeights = 269.0;
  float sum = 0.0;

  vec2 blurriness = vec2(u_OcclusionBlurAmount,
                         u_OcclusionBlurAmount * u_DepthAspectRatio);

  float current = 0.0;

  current += GetVisibility(uv + vec2(-1.0, -2.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+1.0, -2.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-1.0, +2.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+1.0, +2.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-2.0, +1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+2.0, +1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-2.0, -1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+2.0, -1.0) * blurriness, asset_depth_mm);
  sum += current * 4.0;

  current = 0.0;
  current += GetVisibility(uv + vec2(-2.0, -0.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+2.0, +0.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+0.0, +2.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-0.0, -2.0) * blurriness, asset_depth_mm);
  sum += current * 7.0;

  current = 0.0;
  current += GetVisibility(uv + vec2(-1.0, -1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+1.0, -1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-1.0, +1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+1.0, +1.0) * blurriness, asset_depth_mm);
  sum += current * 16.0;

  current = 0.0;
  current += GetVisibility(uv + vec2(+0.0, +1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-0.0, -1.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(-1.0, -0.0) * blurriness, asset_depth_mm);
  current += GetVisibility(uv + vec2(+1.0, +0.0) * blurriness, asset_depth_mm);
  sum += current * 26.0;

  sum += GetVisibility(uv , asset_depth_mm) * 41.0;

  return sum / kKernelTotalWeights;
}

main() içinde mevcut olan bu satırı değiştirin:

gl_FragColor.a *= GetVisibility(depth_uvs, asset_depth_mm);

şu satırla değiştirin:

gl_FragColor.a *= GetBlurredVisibilityAroundUV(depth_uvs, asset_depth_mm);

Bu yeni gölgelendirici işlevinden yararlanmak için oluşturucuyu güncelleyin.

OcclusionObjectRenderer.java

Sınıfın en üstüne aşağıdaki üye değişkenlerini ekleyin:

private int occlusionBlurUniform;
private final float occlusionsBlur = 0.01f;

createOnGlThread yönteminin içine aşağıdakileri ekleyin:

// Add alongside the other calls to GLES20.glGetUniformLocation.
occlusionBlurUniform = GLES20.glGetUniformLocation(program, "u_OcclusionBlurAmount");

draw yönteminin içine aşağıdakileri ekleyin:

// Add alongside the other calls to GLES20.glUniform1f.
GLES20.glUniform1f(occlusionBlurUniform, occlusionsBlur);

Görsel Karşılaştırma

Bu değişikliklerle birlikte artık tıkanma sınırı daha sorunsuz olacaktır.

10. Geliştirme-Çalıştırma-Test Etme

Uygulamanızı oluşturup çalıştırma

  1. Android cihazı USB ile bağlayın.
  2. Dosya > Oluştur ve Çalıştır'ı seçin.
  3. Farklı Kaydet: ARCodeLab.apk.
  4. Uygulamanın oluşturulup cihazınıza dağıtılmasını bekleyin.

Uygulamayı cihazınıza dağıtmayı ilk kez denediğinizde:

  • Cihazda USB üzerinden hata ayıklamaya izin vermeniz gerekir. Devam etmek için Tamam'ı seçin.
  • Uygulamanın cihaz kamerasını kullanma izni olup olmadığı sorulur. AR işlevini kullanmaya devam etmek için erişime izin verin.

Uygulamanızı test etme

Uygulamanızı çalıştırdığınızda cihazınızı tutarak, bulunduğunuz alanda hareket ederek ve bir alanı yavaşça tarayarak uygulamanızın temel davranışını test edebilirsiniz. Bir sonraki adıma geçmeden önce en az 10 saniyelik veri toplamaya çalışın ve alanı birkaç yönden tarayın.

Sorun giderme

Android cihazınızı geliştirme için ayarlama

  1. Cihazınızı bir USB kablosuyla geliştirme makinenize bağlayın. Windows kullanarak geliştirme yapıyorsanız cihazınız için uygun USB sürücüsünü yüklemeniz gerekebilir.
  2. Geliştirici seçenekleri penceresinde USB üzerinden hata ayıklama'yı etkinleştirmek için aşağıdaki adımları uygulayın:
  3. Ayarlar uygulamasını açın.
  4. Cihazınızda Android 8.0 veya sonraki bir sürüm yüklüyse Sistem'i seçin. Aksi takdirde bir sonraki adıma geçin.
  5. En alta kaydırıp Telefon hakkında'yı seçin.
  6. En alta kaydırıp Derleme numarası'na 7 kez dokunun.
  7. Önceki ekrana dönün, en alta kaydırın ve Geliştirici seçenekleri'ne dokunun.
  8. Geliştirici seçenekleri penceresinde aşağı kaydırarak USB üzerinden hata ayıklama'yı bulun ve etkinleştirin.

Bu süreçle ilgili daha ayrıntılı bilgiyi Google'ın Android geliştirici web sitesinde bulabilirsiniz.

cfa20a722a68f54f.png

Lisanslarla ilgili bir derleme hatasıyla (Failed to install the following Android SDK packages as some licences have not been accepted) karşılaşırsanız bu lisansları incelemek ve kabul etmek için aşağıdaki komutları kullanabilirsiniz:

cd <path to Android SDK>

tools/bin/sdkmanager --licenses

11. Tebrikler

Tebrikler, Google'ın ARCore Depth API'sini kullanarak ilk derinliğe dayalı artırılmış gerçeklik uygulamanızı başarıyla oluşturup çalıştırdınız.

Sık Sorulan Sorular