提升 Android NDK (C) 上的相機影像穩定

ARCore 現已支援電子影像穩定技術 (EIS),這有助於產生流暢的相機預覽畫面。EIS 運用陀螺儀觀察手機動作,並在相機紋理邊界內套用補償色網格,藉此抵禦輕微晃動。只有裝置的直向模式支援 EIS。ARCore 1.39.0 版將支援所有方向。

查詢 EIS 支援並啟用 EIS

如要啟用 EIS,請將工作階段設為使用 AR_IMAGE_STABILIZATION_MODE_EIS。如果裝置不支援 EIS 功能,會導致 ARCore 擲回例外狀況。

int enableEis = 0;
ArSession_isImageStabilizationModeSupported(
    ar_session, AR_IMAGE_STABILIZATION_MODE_EIS, &enableEis);
if (!enableEis) {
  return;
}
// Create a session config.
ArConfig* ar_config = NULL;
ArConfig_create(ar_session, &ar_config);

// Enable Electronic Image Stabilization.
ArConfig_setImageStabilizationMode(ar_session, ar_config, AR_IMAGE_STABILIZATION_MODE_EIS);
CHECK(ArSession_configure(ar_session, ar_config) == AR_SUCCESS);

// Release config resources.
ArConfig_destroy(ar_config);

轉換座標

開啟 EIS 時,轉譯器必須在算繪相機背景時,使用修改後的裝置座標,並比對結合 EIS 補償的紋理座標。如要取得 EIS 補償座標,請使用 ArFrame_transformCoordinates3d,並將 AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES 當做輸入內容,使用 AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES 做為輸出內容來取得 3D 裝置座標,並使用 AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED 做為輸出內容來取得 3D 紋理座標。目前,ArFrame_transformCoordinates3d 唯一支援的輸入座標類型為 AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES

int kNumVertices = 4;
// Positions of the quad vertices in clip space (X, Y).
const GLfloat kVertices[] = {
    -1.0f, -1.0f, +1.0f, -1.0f, -1.0f, +1.0f, +1.0f, +1.0f,
};
float transformed_vertices_[4 * 3];
float transformed_uvs_[4 * 3];

ArFrame_transformCoordinates3d(
    session, frame, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
    kNumVertices, kVertices,
    AR_COORDINATES_3D_EIS_NORMALIZED_DEVICE_COORDINATES,
    transformed_vertices_);
ArFrame_transformCoordinates3d(
    session, frame, AR_COORDINATES_2D_OPENGL_NORMALIZED_DEVICE_COORDINATES,
    kNumVertices, kVertices, AR_COORDINATES_3D_EIS_TEXTURE_NORMALIZED,
    transformed_uvs_);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, camera_texture_id_);
glUseProgram(camera_program_);
glUniform1i(camera_texture_uniform_, 0);

// Set the vertex positions and texture coordinates.
glVertexAttribPointer(camera_position_attrib_, 3, GL_FLOAT, false, 0,
                      transformed_vertices_);
glVertexAttribPointer(camera_tex_coord_attrib_, 3, GL_FLOAT, false, 0,
                      transformed_uvs_);
glEnableVertexAttribArray(camera_position_attrib_);
glEnableVertexAttribArray(camera_tex_coord_attrib_);

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 範例應用程式。