Registro de errores de AR del mini programa

Utilice la propia API de WeChat VisionKitpara proporcionar capacidades de AR. Dirección oficial del manual: Conceptos básicos de VisionKit

Aunque se proporciona el código oficial demo, todavía hay muchos pozos ocultos. Aquí hay un resumen.

Caso de demostración

Para ser agregado

flujo lógico

El proceso general es el siguiente: el usuario accede a la página AR, se inicializa el programa, se VKSessionobtienen los datos de la cámara y la imagen se envía al backend para su reconocimiento, se obtiene la información de coordenadas del objeto objetivo y luego el 3D. El modelo se coloca en la ubicación de destino.

Los detalles del proceso son los siguientes:

  1. Inicialice el tamaño del lienzo y establezca la información de ancho y alto correspondiente a la densidad de píxeles del dispositivo.
  2. Inicializa threejs.
    1. Inicializa escena, cámara, luz. WeChat debe proporcionar la biblioteca threejs threejs-miniprogram. Después de usarlo, three-platformizedescubrí que los datos de la cámara no se pueden mostrar en la pantalla.
    2. InicializarGLTFLoader. Habrá problemas cuando GLTFLoader cargue modelos de textura, porque el entorno del subprograma WeChat no admite API relacionadas con Blob. Si desea admitirlo, debe implementarlo usted mismo.
    3. Inicialice WebGL. initGLEn este paso, el sombreador de fragmentos y el sombreador de vértices se configuran para representar los datos de la cámara en el lienzo webgl. (El código de sombreado proporcionado oficialmente tiene errores en nuestra escena)
  3. Inicialice VKSession. Obtenga los datos del marco en requestAnimationFrame y renderice dinámicamente la imagen. Ejecutar render (cuadro).
  4. En la función de renderizado:
    1. La sincronización de la información de posición de la cámara requiere la derivación de la matriz inversa de la matriz VKSession. Y sincronice la información de ubicación con la cámara threejs para garantizar que la dirección del modelo 3D siga la dirección del movimiento del teléfono móvil.
  5. Obtenga la imagen del marco actual y cárguela en segundo plano para su reconocimiento.
    1. Lea la información de píxeles de webgl y proporcione canvasPutImageData para dibujar en un lienzo invisible.
    2. Utilice canvasToTempFilePath y getFileSystemManager para convertir imágenes en lienzo a base64.
    3. Interfaz de identificación de llamadas
      1. Reconocimiento exitoso, cargando modelo 3D
      2. Si el reconocimiento no tiene éxito, espere un momento y vuelva a intentarlo.

problema principal

  1. adquisición de imágenes webgl
    1. Obtener información de píxeles de la imagen
    2. Problema al voltear la imagen
  2. Convertir la imagen a base64
  3. Problema de desgaste del modelo VKSession
  4. Problema de representación de datos de la cámara VKSession
  5. Problema de carga del modelo de textura gltf del miniprograma threejs
  6. Problema anormal en la exportación de animación del modelo.

solución

adquisición de imágenes webgl

problema principal:

  • Después de dibujar los datos adquiridos al revés, es necesario invertir la información de los píxeles.
  • Después de que el dispositivo iOS activa el suavizado, los datos obtenidos son 100% negro puro.

Después de usar VKSession , los datos de la cámara del teléfono móvil están en VKFrame y el componente de la cámara no se puede volver a crear. Entonces debemos usar VKFramelos datos para obtener la imagen de la cámara. La lógica de visualización de la cámara está en renderGLel método. En este punto, la imagen se ha renderizado en webglel componente de la página y necesitamos webglleer el marco de renderizado.

El código fuente para capturas de pantalla en threejs es https://github.com/mrdoob/tres.js/blob/master/src/renderers/WebGLRenderer.js#L1903

if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {

    // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)

    if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {

        _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );

    }

} else {

    console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );

}

El código central es el siguiente.


// 这里是核心步骤,获取 webgl 的像素信息 
const gl = this.gl;
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const pixels = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
// 翻转Y轴
flip(pixels, width, height, 4);

Convertir la imagen a base64

Después de obtener los datos de píxeles necesarios, puede dibujarlos en canvas( canvasPutImageDatamétodo) y luego canvasexportarlos como una imagen base64 ( canvasToTempFilePath+ getFileSystemManager).

const frame = this.canvas;
const gl = this.gl;
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const pixels = new Uint8Array(width * height * 4);
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
flip(pixels, width, height, 4);
wx.canvasPutImageData(
  {
    canvasId: "myCanvas",
    data: new Uint8ClampedArray(typedArrayToBuffer(pixels)),
    x: 0,
    y: 0,
    width: frame.width,
    height: frame.height,
    success: (res) => {
      // 图片保存到 canvas
      this.save(frame).then((base64) => {
        reslove(base64);
      });
    },
    fail(res) {
      console.log(res);
    }
  }
);

save(frame) {
      return wx
        .canvasToTempFilePath({
          x: 0,
          y: 0,
          width: frame.width,
          height: frame.height,
          canvasId: "myCanvas",
          fileType: "jpg",
          destWidth: frame.width,
          destHeight: frame.height,
          // 精度修改
          quality: 0.6
        })
        .then(
          (res) => {
            // 临时文件转base64
            return new Promise((reslove, reject) => {
              wx.getFileSystemManager().readFile({
                filePath: res.tempFilePath, //选择图片返回的相对路径
                encoding: "base64", //编码格式
                success: (res) => {
                  // 保存base64
                  reslove(res.data);
                },
                fail: (error) => {
                  reject(error);
                }
              });
            });
          },
          (tempError) => {
            console.log(tempError);
            wx.showToast({
              title: "图片生成失败,重新检测",
              icon: "none",
              duration: 1000
            });
          }
        );
    }

Problema de desgaste del molde

Oficialmente, renderGLla detección de profundidad está desactivada de forma predeterminada, lo que hará que el modelo 3D pase a través del molde, por lo que se requieren anotaciones gl.disable(gl.DEPTH_TEST);.

renderGL(frame) {
  const gl = this.renderer.getContext();
  // gl.disable(gl.DEPTH_TEST);
  const { yTexture, uvTexture } = frame.getCameraTexture(gl, "yuv");
  const displayTransform = frame.getDisplayTransform();
  ...
}

Problema de renderizado de datos de la cámara

Dado que la detección de profundidad está activada, hay un error en el código del sombreador y se mostrarán barras negras o copos de nieve en el modelo. La solución es la siguiente. Modifique el código del sombreador de la siguiente manera

		const vs = `
			attribute vec2 a_position;
			attribute vec2 a_texCoord;
			uniform mat3 displayTransform;
			varying vec2 v_texCoord;
			void main() {
			  vec3 p = displayTransform * vec3(a_position, 0);
			  gl_Position = vec4(p.x, p.y, -1, 1);
			  v_texCoord = a_texCoord;
			}
		`;

Si no ha probado las siguientes soluciones, puede probarlas.

Compatibilidad de la demostración oficial de VKSession, ¿aparecerá el área del jarrón en la esquina superior izquierda en Huawei p30 pro o Xiaomi 11?

problema de carga del modelo de textura gltf

Dado que el entorno del miniprograma no admite objetos Blob y URL, consulte el cargador del proyecto de tres plataformas e implemente la API correspondiente.

Supongo que te gusta

Origin blog.csdn.net/weixin_48408736/article/details/128314886
Recomendado
Clasificación