অ্যান্ড্রয়েড এসডিকে (কোটলিন/জাভা) তে ক্যামেরা ছবি স্থির করুন

ARCore এখন ইলেকট্রনিক ইমেজ স্ট্যাবিলাইজেশন (EIS) সমর্থন করে, যা একটি মসৃণ ক্যামেরা প্রিভিউ তৈরি করতে সাহায্য করে। ইআইএস গাইরো ব্যবহার করে ফোনের গতিবিধি পর্যবেক্ষণ করে এবং ক্যামেরা টেক্সচারের সীমানার মধ্যে ক্ষতিপূরণ হোমোগ্রাফি জাল প্রয়োগ করে স্থিতিশীলতা অর্জন করে যা ছোট ঝাঁকুনিকে কাউন্টার করে। EIS শুধুমাত্র ডিভাইসের পোর্ট্রেট ওরিয়েন্টেশনে সমর্থিত। ARCore এর 1.39.0 রিলিজে সমস্ত অভিযোজন সমর্থিত হবে।

EIS সমর্থনের জন্য ক্যোয়ারী এবং EIS সক্ষম করুন

EIS সক্ষম করতে, ImageStabilizationMode.EIS ব্যবহার করতে আপনার সেশন কনফিগার করুন। ডিভাইসটি যদি EIS বৈশিষ্ট্য সমর্থন না করে, তাহলে এটি ARCore থেকে একটি ব্যতিক্রম ঘটবে।

জাভা

if (!session.isImageStabilizationModeSupported(Config.ImageStabilizationMode.EIS)) {
  return;
}
Config config = session.getConfig();
config.setImageStabilizationMode(Config.ImageStabilizationMode.EIS);
session.configure(config);

কোটলিন

if (!session.isImageStabilizationModeSupported(Config.ImageStabilizationMode.EIS)) return
session.configure(
  session.config.apply { imageStabilizationMode = Config.ImageStabilizationMode.EIS }
)

স্থানাঙ্ক রূপান্তর করুন

যখন EIS চালু থাকে, তখন রেন্ডারারকে পরিবর্তিত ডিভাইস স্থানাঙ্ক এবং ম্যাচিং টেক্সচার কোঅর্ডিনেট ব্যবহার করতে হবে যা ক্যামেরা ব্যাকগ্রাউন্ড রেন্ডার করার সময় EIS ক্ষতিপূরণকে অন্তর্ভুক্ত করে। EIS ক্ষতিপূরণকৃত স্থানাঙ্কগুলি পেতে, Frame.transformCoordinates3d() ব্যবহার করুন , ইনপুট হিসাবে OPENGL_NORMALIZED_DEVICE_COORDINATES ব্যবহার করুন এবং 3D ডিভাইস স্থানাঙ্ক পেতে আউটপুট হিসাবে EIS_NORMALIZED_DEVICE_COORDINATES ব্যবহার করুন এবং স্থানাঙ্ক পেতে EIS_TEXTURE_NORMALIZED আউটপুট হিসাবে। আপাতত, Frame.transformCoordinates3d() এর জন্য একমাত্র সমর্থিত ইনপুট স্থানাঙ্ক হল OPENGL_NORMALIZED_DEVICE_COORDINATES

জাভা

final FloatBuffer cameraTexCoords =
    ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();

final FloatBuffer screenCoords =
    ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer();

final FloatBuffer NDC_QUAD_COORDS_BUFFER =
    ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_2D)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer()
        .put(
            new float[] {
              /*0:*/ -1f, -1f, /*1:*/ +1f, -1f, /*2:*/ -1f, +1f, /*3:*/ +1f, +1f,
            });

final VertexBuffer screenCoordsVertexBuffer =
    new VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null);
final VertexBuffer cameraTexCoordsVertexBuffer =
    new VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null);

NDC_QUAD_COORDS_BUFFER.rewind();
frame.transformCoordinates3d(
    Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
    NDC_QUAD_COORDS_BUFFER,
    Coordinates3d.EIS_NORMALIZED_DEVICE_COORDINATES,
    screenCoords);
screenCoordsVertexBuffer.set(screenCoords);

NDC_QUAD_COORDS_BUFFER.rewind();
frame.transformCoordinates3d(
    Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
    NDC_QUAD_COORDS_BUFFER,
    Coordinates3d.EIS_TEXTURE_NORMALIZED,
    cameraTexCoords);
cameraTexCoordsVertexBuffer.set(cameraTexCoords);

কোটলিন

val COORDS_BUFFER_SIZE_2D = 2 * 4 * Float.SIZE_BYTES
val COORDS_BUFFER_SIZE_3D = 3 * 4 * Float.SIZE_BYTES
val cameraTexCoords =
  ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
val screenCoords =
  ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_3D)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
val cameraTexCoordsVertexBuffer = VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null)
val screenCoordsVertexBuffer = VertexBuffer(render, /* numberOfEntriesPerVertex= */ 3, null)
val NDC_QUAD_COORDS_BUFFER =
  ByteBuffer.allocateDirect(COORDS_BUFFER_SIZE_2D)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
    .apply {
      put(
        floatArrayOf(
          /* 0: */
          -1f,
          -1f,
          /* 1: */
          +1f,
          -1f,
          /* 2: */
          -1f,
          +1f,
          /* 3: */
          +1f,
          +1f
        )
      )
    }
NDC_QUAD_COORDS_BUFFER.rewind()
frame.transformCoordinates3d(
  Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
  NDC_QUAD_COORDS_BUFFER,
  Coordinates3d.EIS_NORMALIZED_DEVICE_COORDINATES,
  screenCoords
)
screenCoordsVertexBuffer.set(screenCoords)

NDC_QUAD_COORDS_BUFFER.rewind()
frame.transformCoordinates3d(
  Coordinates2d.OPENGL_NORMALIZED_DEVICE_COORDINATES,
  NDC_QUAD_COORDS_BUFFER,
  Coordinates3d.EIS_TEXTURE_NORMALIZED,
  cameraTexCoords
)
cameraTexCoordsVertexBuffer.set(cameraTexCoords)

যখন EIS বন্ধ থাকে, আউটপুট 3D স্থানাঙ্কগুলি তাদের 2D সমকক্ষের সমতুল্য, z মানগুলি কোন পরিবর্তন আনতে সেট করে না।

শেডার পরিবর্তন করুন

গণনা করা 3D স্থানাঙ্কগুলি ব্যাকগ্রাউন্ড রেন্ডারিং শেডারগুলিতে পাস করা উচিত৷ ভার্টেক্স বাফারগুলি এখন EIS সহ 3D:

layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec3 a_CameraTexCoord;
out vec3 v_CameraTexCoord;
void main() {
  gl_Position = a_Position;
  v_CameraTexCoord = a_CameraTexCoord;
}

অতিরিক্তভাবে, ফ্র্যাগমেন্ট শেডারকে দৃষ্টিকোণ সংশোধন প্রয়োগ করতে হবে:

precision mediump float;
uniform samplerExternalOES u_CameraColorTexture;
in vec3 v_CameraTexCoord;
layout(location = 0) out vec4 o_FragColor;
void main() {
  vec3 tc = (v_CameraTexCoord / v_CameraTexCoord.z);
  o_FragColor = texture(u_CameraColorTexture, tc.xy);
}

আরো বিস্তারিত জানার জন্য hello_eis_kotlin নমুনা অ্যাপটি দেখুন।