Píxeles de sangría de textura

Presentamos el cuarto artículo de nuestra serie sobre cómo trabajar con modelos 3D en Unity. Artículos anteriores: "Características de trabajar con Mesh in Unity" , "Unity: edición de procedimientos de Mesh" , "Importación de modelos 3D en Unity y dificultades" .

En el artículo anterior, mencionamos que se verificaba el escaneo de texturas para determinar la idoneidad de la sangría de píxeles en una resolución de textura dada. En esta publicación, describimos la esencia del problema con la observación de sangría de píxeles y el algoritmo para rastrearlo. No se considerará el código, sino precisamente el principio que se puede implementar en cualquier lenguaje y en cualquier entorno de desarrollo.



Problema


Un pedido de un modelo 3D suele ir acompañado de un requisito para la resolución de la textura. Debido a la naturaleza discreta de la imagen de trama, el artista 3D debe observar la sangría en píxeles entre las partes del escaneo de textura. La ausencia de la sangría necesaria conduce al hecho de que el mismo píxel se muestra en el modelo en lugares completamente diferentes cuando no es necesario.

Es especialmente importante rastrear una sangría suficiente en las primeras etapas del trabajo. Muy a menudo, algunas personas se dedican a la creación de geometría, incluido un escaneo de textura, y otras se dedican a dibujar texturas. El error detectado por el artista 3D causará menos problemas que el que encontrará el diseñador de texturas. En el último caso, la situación se vuelve aún más complicada si el paquete 3D utilizado no proporciona herramientas para dibujar sobre geometría (por ejemplo, un pincel).

También debe considerar dos matices, debido a que entre los elementos del barrido puede requerir más espacio. El primero es una disminución en la resolución de la textura durante el mipmapping. El segundo es el uso de un filtro de dilatación al formar un mapa de iluminación . Durante la tarea de crear un escaneo UV , un artista 3D debe guiarse por los requisitos para la resolución de la textura y también tener en cuenta los matices enumerados anteriormente. Sin embargo, muchas deficiencias simplemente no se pueden notar sin una verificación automática.


Un ejemplo de la aparición de artefactos con una disminución en los detalles.

Para modelos simples, se puede generar un escaneo de textura utilizando herramientas automáticas. Sin embargo, se basan en métricas internas y no tienen en cuenta la sangría de píxeles, por lo que los píxeles compartidos a menudo se encuentran a lo largo de los bordes diagonales. La verificación con las texturas del verificador no muestra todos los errores, además, estas texturas a menudo tienen una resolución más alta que las que se utilizarán en el proyecto.


Píxeles compartidos

El problema de la sangría de píxeles insuficiente en el escaneo UV es similar al problema con las superposiciones. En ambos casos, puede ocurrir el llamado sangrado : en el artículo anterior describimos qué artefactos genera.

Sin embargo, el problema con la sangría de píxeles depende del requisito mínimo de resolución de textura. Una sola comprobación es suficiente para determinar las superposiciones, mientras que los requisitos para la resolución de la textura pueden cambiar en la siguiente etapa de desarrollo. La situación se complica por el hecho de que los paquetes 3D que utilizamos no tienen herramientas para detectar automáticamente errores relacionados con la proximidad de partes del escaneo UV . Y no olvide que después de la operación del modelador automático en Unity, aún debe verificar UV2 .

Decidimos crear una herramienta que pueda verificar la sangría en píxeles y marcar los lugares de posibles huecos en el modelo. Los requisitos de sangría se determinarán en función de los siguientes parámetros:

  1. La resolución base de la textura.
  2. La resolución mínima de la textura a la que no se permite el flujo.
  3. La sangría requerida en la textura mínima.

Dado que los tamaños de las texturas que utilizamos son iguales a las potencias de dos, la fórmula para calcular la sangría necesaria en la resolución básica es bastante simple: (Resolución básica / Resolución mínima) * sangría en la MinTexture.

Obviamente, la solución a este problema está estrechamente relacionada con la rasterización. Para una declaración más clara de los requisitos y el desarrollo de un algoritmo, presentamos varios conceptos.

Conceptos clave


Considere un espacio UV y una cuadrícula uniforme de dimensión NxM en el rango 0.0–1.0. Las celdas de 1 / N de ancho y 1 / M de alto forman una partición del espacio UV .


NxM dividiendo el espacio UV

Tomamos dos puntos arbitrarios y denotamos Dn como el número de píxeles ocupados por la proyección en el eje U del segmento que conecta los puntos dados. Del mismo modo, Dm para el eje V. Luego definimos la distancia de píxeles como el máximo entre Dn y Dm.


Distancia de píxeles

Cabe señalar que en el espacio euclidiano, operaciones de movimiento como la traslación paralela y la rotación no son movimientos de la malla, si la distancia de píxeles se toma como la métrica. Este matiz complicó un poco el desarrollo de nuestra solución.



Llamamos a un cuadrado con un lado en K píxeles el núcleo de K. Entonces dos puntos con una distancia de píxel menor que K pueden ser cubiertos por un núcleo de K.


Ejemplos de núcleos de diferentes tamaños.

Dos bordes del polígono forman una concavidad del contorno si su punto medio (el centro de masa en cuatro vértices) se encuentra a la izquierda de estos bordes al girar alrededor del contorno en el sentido de las agujas del reloj. Para el recorrido en sentido antihorario, la condición es encontrar un punto a la derecha de los bordes.


Un par de costillas que forman una concavidad del contorno.

Solución


Ahora hablemos directamente sobre la comprobación de sangría de píxeles. Para implementarlo, se nos ocurrió un algoritmo que consta de tres fragmentos independientes. El orden de ejecución no es importante. El resultado de cada uno de los fragmentos es la matriz NxM, que es un búfer de las células de la partición, donde se etiquetan algunas células. La suma de los tres tampones es el resultado general.

Primero, considere el fragmento más simple. Todo se reduce a encontrar células que se cruzan cerca de triángulos y bordes degenerados, cuya longitud es menor que el lado del núcleo de una magnitud dada. Todas esas celdas están marcadas en el búfer.


Resultado de comprobar el tamaño de los elementos

Antes de describir los otros dos fragmentos, considere la lógica general de su trabajo. Ambos están relacionados con el procesamiento de grupos de triángulos llamados conchas o islas. Shell para un artista 3D es un conjunto de polígonos conectados, es decir, cada polígono en este conjunto tiene un vecino con el que comparte vértices comunes. También Shell es un campo de entrenamiento independiente. Además, por shell, isla y clúster queremos decir lo mismo.



Para encontrar todas las capas, utilizamos el algoritmo de búsqueda para todos los componentes conectados del gráfico, donde el vértice del gráfico está representado por un polígono y el borde por la presencia de vértices comunes en un par de polígonos. Dado que el único polígono en Unity es un triángulo definido por índices de vértices, consideramos que los triángulos son adyacentes si al menos un índice del vértice del primero coincide con el índice de cualquier vértice del segundo. De la analogía con el gráfico y el método para determinar las aristas, se deduce que el conjunto de índices de los vértices de un grupo no se cruza con el conjunto de vértices del otro.



Con la parte común terminada. El segundo fragmento, que consideraremos, determina las ubicaciones de los posibles errores asociados con la proximidad o superposición de diferentes grupos.

Muchos grupos se alimentan a la entrada en forma de conjuntos de triángulos en el espacio UV , la dimensión de la división UV correspondiente a la resolución de textura (NxM) y el valor de sangría P como el número de píxeles. Para una partición dada, es necesario encontrar aquellas áreas en las que la distancia en píxeles entre los grupos es menor que la sangría requerida. Una celda en la matriz de resultados se marca si ingresa al menos un núcleo del valor K = P + 1 , que intersecta dos grupos diferentes.

La esencia del fragmento se expone casi en la descripción del resultado. Es necesario encontrar todos los núcleos de magnitud K que se cruzan con triángulos de diferentes capas, y luego marque las células de estos núcleos en el búfer de resultados.

En nuestra implementación, todos los pares de clústeres se consideran a su vez. Para cada par, se determina la región de intersección de los conjuntos de núcleos de magnitud K cubiertos por estos grupos. Elija un par y denote un conjunto como Q.



Luego, todos los elementos de Q deben verificarse mediante el siguiente criterio: el núcleo dado intersecta al menos un triángulo en cada uno de los grupos del par seleccionado. Si es así, se marcan todas las celdas del núcleo probado.



El búfer con celdas marcadas para todos los pares de grupos constituye el resultado.


Resultado de sangría de clúster

Ahora nos ocuparemos del último fragmento. Aquí debe procesar un clúster. La entrada es un conjunto de triángulos en el espacio UV , la dimensión de la división UV correspondiente a la resolución de la textura (NxM) y el valor de sangría P como el número de píxeles. Una celda se puede marcar en dos casos: el clúster no es válido o tiene agujeros, o la distancia en píxeles entre los bordes de la concavidad es menor que la sangría requerida.

La parte interna del clúster no nos interesa: para empezar, obtendremos su contorno representado por una lista conectada de bordes. Los triángulos vecinos duplican los índices de los vértices, por lo tanto, el borde pertenece al contorno si un par de índices de sus vértices es único para muchos bordes del grupo. Habiendo descubierto qué bordes forman el contorno, es necesario componerlos para obtener una lista vinculada.

Si después de este paso no todos los bordes del contorno entran en la lista, entonces el clúster tiene agujeros o hay un error en los datos de la malla. En este caso, es necesario marcar adecuadamente todas las células de los núcleos cruzados por el grupo.

Si se encuentra el contorno, el procesamiento continúa. Formulamos el siguiente requisito de resultado. Deje que el par de bordes que forman la concavidad del contorno se crucen con el núcleo de K = P + 1 . Luego, las células del núcleo deben marcarse si ambas partes del contorno entre los bordes van más allá de este núcleo.


Resultado de la prueba de características del clúster

Decidimos implementar este requisito mediante la comparación por pares de los bordes del contorno. Comenzamos con la condición de concavidad, luego para cada par se verifican todos los granos que intersecan ambos bordes. Para probar el núcleo, se realizan recorridos transversales de cada parte del contorno entre un par de bordes. Si cada parte contiene al menos un punto más allá de los límites del núcleo, entonces todas las células del núcleo están marcadas.


La condición bajo la cual se marcan las celdas del núcleo verificado

Resumen


El algoritmo anterior es muy adecuado para la implementación usando computación paralela. El procesamiento de cada par de grupos y aristas se realiza de forma independiente. Dado que las comprobaciones se basan en la rasterización, si comienza a procesar no con pares de bordes, sino con núcleos, es aconsejable utilizar las capacidades de la GPU .

Transformamos el resultado del algoritmo en una textura. Para una resolución dada, esto le permite mostrar gráficamente los lugares de posibles fallas en la exploración UV . Además, la textura resultante se puede aplicar al modelo para ver las marcas directamente en la geometría.

En los ejemplos a continuación, cortamos especialmente el conejo y Suzanne con la herramienta automática Blender para obtener más artefactos. La resolución de textura verificada es 256x256, la sangría requerida es 1.

Las celdas marcadas en azul cubren grupos con agujeros, así como triángulos y bordes que son demasiado pequeños. El verde indica los núcleos celulares con las características de cada grupo individualmente. Los granos en los que no se observa la sangría entre grupos están marcados en rojo.

Ejemplos




En el próximo artículo, consideraremos un algoritmo para optimizar modelos 3D en una escena eliminando la geometría invisible. Quédate con nosotros!

Source: https://habr.com/ru/post/451794/


All Articles