¿Cómo se calculan los niveles de mipmap en Metal?

14

Mi pregunta es específicamente con respecto al Metal, ya que no sé si la respuesta cambiaría para otra API.

Lo que creo que entiendo hasta ahora es esto:

  • Una textura mipmappeada tiene "niveles de detalle" calculados previamente, donde se crean niveles más bajos de detalle reduciendo el muestreo de la textura original de alguna manera significativa.

  • Se hace referencia a los niveles de Mipmap en un nivel de detalle descendente, donde el nivel 0es la textura original y los niveles superiores son reducciones de potencia de dos.

  • La mayoría de las GPU implementan el filtrado trilineal, que selecciona dos niveles de mipmap vecinos para cada muestra, muestras de cada nivel utilizando filtrado bilineal y luego combina linealmente esas muestras.

Lo que no entiendo es cómo se seleccionan estos niveles de mipmap. En la documentación de la biblioteca estándar de Metal, veo que se pueden tomar muestras, con o sin especificar una instancia de un lod_optionstipo. Supongo que este argumento cambia la forma en que se seleccionan los niveles de mipmap, y aparentemente hay tres tipos de lod_optionstexturas 2D:

  • bias(float value)
  • level(float lod)
  • gradient2d(float2 dPdx, float2 dPdy)

Desafortunadamente, la documentación no se molesta en explicar qué hace cualquiera de estas opciones. Puedo adivinar que bias()sesga algún nivel de detalle elegido automáticamente, pero entonces, ¿qué significa el sesgo value? ¿En qué escala opera? Del mismo modo, ¿cómo es el lodde level()traducirse en niveles discretos mipmap? Y, operando bajo el supuesto de que gradient2d()usa el gradiente de la coordenada de textura, ¿cómo usa ese gradiente para seleccionar el nivel de mipmap?

Más importante aún, si omito el lod_options, ¿cómo se seleccionan los niveles de mipmap? ¿Esto difiere según el tipo de función que se ejecuta?

Y, si la operación predeterminada de la sample()función especificada sin opciones de alojamiento es hacer algo como gradient2D()(al menos en un sombreador de fragmentos), ¿utiliza derivados simples del espacio de pantalla o funciona directamente con rasterizador y coordenadas de textura interpoladas? calcular un gradiente preciso?

Y finalmente, ¿qué tan consistente es este comportamiento de un dispositivo a otro? Un artículo antiguo (antiguo como en DirectX 9) que leí se refería a la selección compleja de mipmap específica del dispositivo, pero no sé si la selección de mipmap está mejor definida en arquitecturas más nuevas.

lcmylin
fuente

Respuestas:

17

La selección de MIP está bastante bien estandarizada en todos los dispositivos hoy en día, con la excepción de algunos de los detalles esenciales del filtrado anisotrópico, que aún depende de los fabricantes de GPU individuales para definir (y sus detalles precisos generalmente no se documentan públicamente).

Un buen lugar para leer sobre la selección de mip en detalle es en la especificación OpenGL, sección 8.14, "Minificación de texturas" . Supongo que funciona de la misma manera en Metal. (Apple podría haber cambiado algo, considerando que fabrican tanto el hardware como la API ... pero dudo que lo hayan hecho). Lo resumiré aquí.

La selección de mip predeterminada (que no usa ninguno de los lod_optionsmodificadores) usa los gradientes de espacio de pantalla de las coordenadas de textura para elegir los niveles de mip. Básicamente, trata de elegir los niveles de mip que producen lo más cerca posible de una asignación 1: 1 de texels a píxeles. Por ejemplo, si los gradientes tienen una longitud de 4 texels por píxel, elegiría mip nivel 2 (que es 1 / 4th del tamaño del nivel 0 y, por lo tanto, le da 1 texel mipped por píxel).

Con el filtrado trilineal, dado que generalmente no aterriza en un mapeo exacto 1: 1, selecciona los dos niveles más cercanos y los interpola linealmente entre ellos, para que tenga una transición suave entre los niveles de mip a medida que la cámara u objetos en su escena se mueven alrededor.

λλλλ=2.8

λIniciar sesión2(1/ /4 4)=-2

Ahora, en cuanto a las opciones del modificador:

  • biasλ
  • levelλλlod
  • gradient2dle permite poner sus propios vectores de gradiente, que sustituyen los gradientes implícitos del espacio de pantalla de las coordenadas de textura. El resto del proceso de selección y muestreo de mip continúa normalmente, pero con los gradientes alterados. Esto le permite personalizar el filtrado anisotrópico.

En otros tipos de sombreadores, además de los sombreadores de fragmentos, no existe la noción de "gradientes de espacio de pantalla", por lo que las dos últimas operaciones suelen ser las únicas permitidas: cualquier operación que intente utilizar gradientes implícitos daría un error de compilación. No estoy seguro de que así sea Metal, pero eso es lo que esperaría de trabajar con otras API.

Nathan Reed
fuente