Recién comencé a aprender openGL y obtengo este artefacto cuando texturizo una esfera con mipmaps. Básicamente, cuando el fragmento muestrea el borde de mi textura, detecta la discontinuidad (digamos de 1 a 0) y selecciona el mapa MIP más pequeño, lo que crea esta costura fea:
fea costura http://cdn.imghack.se/images/6bbe0ad0173cac003cd5dddc94bd43c7.png
Así que intenté anular manualmente los gradientes usando textureGrad:
//fragVert is the original vertex from the vertex shader
vec2 ll = vec2((atan(fragVert.y, fragVert.x) / 3.1415926 + 1.0) * 0.5, (asin(fragVert.z) / 3.1415926 + 0.5));
vec2 ll2 = ll;
if (ll.x < 0.01 || ll.x > 0.99)
ll2.x = .5;
vec4 surfaceColor = textureGrad(material.tex, ll, dFdx(ll2), dFdy(ll2));
Ahora tengo dos costuras en lugar de una. ¿Cómo puedo deshacerme de ellos? ¿Y por qué el código anterior genera 2 costuras?
2 eams http://cdn.imghack.se/images/44a38ef13cc2cdd801967c9223fdd2d3.png
No se puede distinguir de las dos imágenes, pero las 2 costuras están a ambos lados de la costura original.
Respuestas:
Según el código de sombreador que publicó, no está interpolando los UV de los vértices, sino que parece que está interpolando la posición 3D (
fragVert
), luego calculando los UV transformándolos en coordenadas esféricas.Su análisis es correcto porque el mipmap más pequeño se elige cuando hay una discontinuidad, ya que la selección de mipmap se basa en derivados que se estiman numéricamente a partir de los UV utilizados en los píxeles vecinos. Cuando un píxel tiene u = 0 y otro tiene u = 1, obtienes una derivada muy grande. Su intento de reparación tiene el mismo problema porque las grandes derivaciones ocurren alrededor de u = 0.01 yu = 0.99, razón por la cual aparecen dos costuras a cada lado de donde estaba la costura original.
Un enfoque relativamente simple para solucionar el problema sería decidir qué nivel de mip usar y llamar
textureLod
para probarlo directamente. Si el planeta siempre va a estar bastante cerca de la cámara, simplemente puede codificar el nivel de mip a 0 (o, para el caso, simplemente no incluir niveles de mip en la textura). De lo contrario, podría basarse en el log2 de la distancia del punto desde la cámara, escalado por algunos factores adecuados. Tenga en cuenta que esto deshabilitará efectivamente el filtrado anisotrópico.Un enfoque más "correcto" sería calcular algunos derivados de mayor calidad. En vez de usar
dFdx
ydFdy
sobre los UV, que tienen discontinuidades debido a laatan2
, se podría aplicardFdx
ydFdy
parafragVert
(que será continua todo el camino alrededor de la esfera), a continuación, utilizar algunos (regla de la cadena) el cálculo para encontrar la fórmula para obtener los derivados UV desde la posición derivados. Esto será más complicado y más lento, pero tiene la ventaja de que el filtrado anisotrópico debería funcionar.Finalmente, dado que eres nuevo en OpenGL, solo notaré que si bien calcular los UV a partir de coordenadas esféricas es una forma perfectamente válida de texturizar una esfera, no es la forma "habitual" que la mayoría de la gente elige. Es más común construir una malla de esfera que tenga UV especificados por vértice, y simplemente pase del sombreador de vértices al sombreador de píxeles (interpolado linealmente a través de cada triángulo). Los vértices se colocan a lo largo de la costura, de esta manera , de modo que hay dos copias de cada vértice, en exactamente las mismas posiciones, pero la mitad con u = 0 conectado a los triángulos en un lado, y la otra mitad con u = 1 conectado a Los triángulos del otro lado. Esto elimina cualquier costura visible y no requiere ningún truco en el sombreador de píxeles.
fuente