El problema con el uso de atlas de textura y fugas de texels adyacentes tiene que ver con la forma en que funciona el filtrado de textura lineal.
Para cualquier punto de la textura que no se muestrea exactamente en el centro de un texel, el muestreo lineal muestreará 4 texels adyacentes y calculará el valor en la ubicación que solicitó como el promedio ponderado (basado en la distancia desde el punto de muestra) de los 4 muestras
Aquí hay una buena visualización del problema:
Dado que no puede usar algo como GL_CLAMP_TO_EDGE
en un atlas de texturas, debe crear elementos de borde alrededor del borde de cada textura. Estos texels de borde evitarán que las muestras vecinas de texturas completamente diferentes en el atlas alteren la imagen a través de la interpolación ponderada explicada anteriormente.
Tenga en cuenta que cuando utiliza el filtro anisotrópico, es posible que deba aumentar el ancho del borde. Esto se debe a que el filtrado anisotrópico aumentará el tamaño de la vecindad de la muestra en ángulos extremos.
Para ilustrar lo que quiero decir al usar un borde alrededor del borde de cada textura, considere los diversos modos de ajuste disponibles en OpenGL. Presta especial atención a CLAMP TO EDGE
.
A pesar de que existe un modo llamado "Clamp to Border", en realidad no es lo que nos interesa. Ese modo le permite definir un solo color para usarlo como borde alrededor de su textura para cualquier coordenada de textura que quede fuera de la normalizada [0.0 -1.0] rango.
Lo que queremos es replicar el comportamiento de CLAMP_TO_EDGE
, donde cualquier coordenada de textura fuera del rango apropiado para la (sub) textura recibe el valor del último centro de texel en la dirección en la que estaba fuera de los límites. Dado que tiene un control casi completo sobre las coordenadas de textura en un sistema de atlas, el único escenario en el que las coordenadas de textura (efectivas) pueden referirse a una ubicación fuera de su textura es durante el paso promedio ponderado del filtrado de textura.
Sabemos que GL_LINEAR
tomará muestras de los 4 vecinos más cercanos como se ve en el diagrama anterior, por lo que solo necesitamos un borde de 1 texel. Es posible que necesite un borde de texel más ancho si usa un filtro anisotrópico, ya que aumenta el tamaño del vecindario de la muestra bajo ciertas condiciones.
Aquí hay un ejemplo de una textura que ilustra el borde más claramente, aunque para sus propósitos puede hacer que el borde tenga 1 texel o 2 texels de ancho.
(NOTA: El borde al que me refiero no es el negro alrededor de los cuatro bordes de la imagen, sino el área donde el patrón de tablero de ajedrez deja de repetirse regularmente)
En caso de que te lo estés preguntando, aquí es por qué sigo sacando el filtro anisotrópico. Cambia la forma de la vecindad de la muestra según el ángulo y puede hacer que se usen más de 4 texels para el filtrado:
http://www.arcsynthesis.org/gltut/Texturing/ParallelogramDiag.svg
Cuanto mayor sea el grado de anisotropía que use, más probabilidades tendrá de lidiar con vecindarios de muestra que contengan más de 4 texels. Un borde de 2 texel debe ser adecuado para la mayoría de las situaciones de filtrado anisotrópico.
Por último, pero no menos importante, así es como se construiría un atlas de textura empaquetado que replicaría el GL_CLAMP_TO_EDGE
comportamiento en presencia de un GL_LINEAR
filtro de textura:
( Reste 1 de X e Y en las coordenadas negras, no revisé la imagen antes de publicar ) .
Debido al almacenamiento de bordes, el almacenamiento de 4 texturas de 256x256 en este atlas requiere una textura con dimensiones de 516x516. Los bordes están codificados por colores en función de cómo los llenaría con datos de texel durante la creación del atlas:
- Rojo = Reemplazar con texel directamente debajo
- Amarillo = Reemplazar con texel directamente arriba
- Verde = Reemplazar con texel directamente a la izquierda
- Azul = Reemplazar con texel directamente a la derecha
Efectivamente en este ejemplo empaquetado, cada textura en el atlas usa una región de 258x258 del atlas, pero generará coordenadas de textura que se correlacionan con la región visible de 256x256. Los texels limítrofes solo se usan cuando el filtrado de texturas se realiza en los bordes de las texturas en el atlas, y la forma en que están diseñados imita el GL_CLAMP_TO_EDGE
comportamiento.
En caso de que se lo esté preguntando, puede implementar otros tipos de modos de ajuste utilizando un enfoque similar: GL_REPEAT
puede implementarse intercambiando los texels de borde izquierdo / derecho y superior / inferior en el atlas de textura y un poco de matemática de coordenadas de textura inteligente en un sombreador Eso es un poco más complicado, así que no te preocupes por eso por ahora. Como solo se trata de hojas de sprites, limítese a GL_CLAMP_TO_EDGE
:)
GL_NEAREST
oGL_LINEAR
para renderizar la textura?