En mi juego hay un terreno similar a Minecraft hecho de cubos. Genero un búfer de vértices a partir de los datos de vóxel y uso un atlas de texturas para la apariencia de diferentes bloques:
El problema es que la textura de cubos distantes se interpola con mosaicos adyacentes en el atlas de texturas. Eso da como resultado líneas de colores incorrectos entre los cubos (es posible que deba ver la captura de pantalla a continuación en su tamaño completo para ver los defectos gráficos):
Por ahora uso esta configuración de interpolación, pero probé todas las combinaciones e incluso GL_NEAREST
sin mipmapping no proporciona mejores resultados.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
También intenté agregar un desplazamiento en las coordenadas de textura para elegir un área ligeramente más pequeña del mosaico, pero dado que el efecto no deseado depende de la distancia a la cámara, esto no puede resolver el problema por completo. A grandes distancias, las rayas ocurren de todos modos.
¿Cómo puedo resolver este sangrado de textura? Dado que el uso de un atlas de texturas es una técnica popular, puede haber un enfoque común. Lamentablemente, por algunas razones explicadas en los comentarios, no puedo cambiar a diferentes texturas o matrices de texturas.
GL_LINEAR
que da un resultado similar, o seleccionará el píxel más cercanoGL_NEAREST
que, de todos modos, también dará lugar a franjas entre bloques. La última opción mencionada disminuye pero no elimina la falla de píxeles.Respuestas:
Bien, creo que tienes dos problemas aquí.
El primer problema es con mipmapping. En general, no desea mezclar ingeniosamente atlasing con mipmapping, porque a menos que todas sus subtexturas tengan exactamente un tamaño de 1x1 píxel, experimentará un sangrado de textura. Agregar relleno simplemente moverá el problema a un nivel de mip más bajo.
Como regla general, para 2D, que es donde usualmente haces atlas, no haces mipmap; mientras que para 3D, que es donde mipmap, no atlas (en realidad, tu piel de tal manera que el sangrado no será un problema)
Sin embargo, lo que creo que está sucediendo con su programa en este momento es que probablemente no esté utilizando las coordenadas de textura correctas, y debido a eso sus texturas están sangrando.
Supongamos una textura de 8x8. Probablemente esté obteniendo el cuarto superior izquierdo utilizando coordenadas uv de (0,0) a (0.5, 0.5):
Y el problema es que en la coordenada u 0.5, la muestra interpolará el fragmento de destino utilizando la mitad del texel izquierdo y la mitad del texel derecho. Lo mismo sucederá en la coordenada u 0, y lo mismo para las coordenadas v. Esto se debe a que está abordando los límites entre los texels y no los centros.
Lo que debe hacer en su lugar es abordar el centro de cada texel. En este ejemplo, estas son las coordenadas que desea usar:
En este caso, siempre estará muestreando el centro de cada texel y no debería tener ningún sangrado ... A menos que use mipmapping, en cuyo caso siempre obtendrá sangrado comenzando en el nivel de mip donde la subtextura escalada no se limpia encajar dentro de la cuadrícula de píxeles .
Para generalizar, si desea acceder a un texel específico, las coordenadas se calculan como:
Esto se llama "corrección de medio píxel". Hay una explicación más detallada aquí si está interesado.
fuente
Una opción que será mucho más fácil que jugar con mapas MIP y agregar factores de fuzz de coordenadas de textura es usar una matriz de texturas. Las matrices de texturas son similares a las texturas 3d, pero sin mipmapping en la tercera dimensión, por lo que son ideales para atlas de texturas donde las "subtexturas" son todas del mismo tamaño.
http://www.opengl.org/wiki/Array_Texture
fuente
Después de luchar mucho con este problema, finalmente encontré una solución.
Para usar ambos, un atlas de texturas y mipmapping, necesito realizar el muestreo por mí mismo, porque OpenGL de lo contrario interpolaría sobre los límites de los mosaicos en el atlas. Además, necesitaba establecer los parámetros de textura correctos, porque la interpolación entre mapas MIP también causaría sangrado de textura.
Con estos parámetros, no se produce sangrado.
Hay una cosa que debe tener en cuenta al proporcionar mapas MIP personalizados. Dado que no tiene sentido reducir el atlas incluso si cada mosaico ya lo es
1x1
, el nivel máximo de mipmap debe establecerse de acuerdo con lo que proporcione.¡Gracias por todas las otras respuestas y comentarios muy útiles! Por cierto, todavía no sé cómo usar el escalamiento lineal, pero supongo que no hay manera.
fuente
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_FILTER, GL_NEAREST_MIPMAP_LINEAR);
GL_TEXTURE_MAX_FILTER
enGL_NEAREST_MIPMAP_LINEAR
causas de sangrado no por el mipmapping, sino por el motivo de la interpolación. Entonces, en este caso, es equivalente a,GL_LINEAR
ya que el nivel más bajo de mipmap se usa de todos modos.glTexImage2D()
. La GPU elige automáticamente el nivel correcto según el tamaño de los objetos en la pantalla.Parece que el problema podría ser causado por MSAA. Vea esta respuesta y el artículo vinculado :
La solución es usar muestreo centroide. Si está calculando el ajuste de las coordenadas de textura en un sombreador de vértices, mover esa lógica al sombreador de fragmentos también podría solucionar el problema.
fuente
Este es un tema antiguo, y tuve un problema similar al tema.
Tenía mis coordenadas de textura bien, pero moviendo la posición de la cámara (que cambió las posiciones de mi elemento) así:
Todo el problema era Util.lerp () devuelve un flotante o doble. Esto fue malo porque la cámara estaba traduciendo fuera de la red y causando algunos problemas extraños con fragmentos de textura que eran> 0 en X y> 0 en Y.
TLDR: no interpolar ni nada con flotadores
fuente