lights example javascript opengl-es rotation textures webgl

javascript - example - Las texturas repetidas se distorsionan/agitan gravemente al girar la cámara



webgl lighting example (2)

Originalmente formulé esta pregunta en gamedev , pero ninguna de las respuestas me ayudó a resolver el problema, y ​​todavía no tengo idea de cuál es la verdadera causa. No vi nada acerca de volver a publicar preguntas en SE en las preguntas frecuentes, por lo que solo puedo esperar que todo esté bien. Además, en retrospectiva, la pregunta probablemente esté más relacionada con la programación de gráficos en general que con el desarrollo del juego.

Editar 1 comienza

El comportamiento de la publicación original se aplica solo a Windows XP y Windows 7, navegadores Firefox y Chrome. En Ubuntu, no existe esa distorsión, sino que las texturas se "agitan" mientras se gira la cámara. Cuando se detiene la rotación, la sacudida se detiene, pero las texturas pueden no estar en la posición completamente correcta.

Editar 1 final

Editar 3 comienza

El programa ha sido probado en 4 computadoras diferentes, y no funcionó según lo previsto en ninguna de ellas.

Editar 3 extremos

Tengo un voxel grande en WebGL que quiero cubrir con textura de mosaico. Cada mosaico tiene una longitud lateral de 1 en el espacio del vértice. En este escenario de prueba, la cámara apunta a la dirección z negativa y los lados del vóxel están en los planos xy, xz, yz.

Vóxeles más pequeños (es decir, menos repeticiones) funcionan bastante bien, pero a aproximadamente 2000 xey se repiten por cara (es decir, tamaño de vóxel 2000 * 2000 * 2000) las texturas comienzan a verse realmente feas. Cuando la cámara apunta perpendicularmente a la cara, las texturas se ven correctas independientemente del tamaño / cantidad de repeticiones, pero para los vóxeles del tamaño mencionado anteriormente, cualquier rotación de incluso un par de grados causa un problema visible. Aumentar el tamaño del vóxel aumenta la distorsión. Lo inverso también es cierto: con vóxeles pequeños, las texturas se ven correctas independientemente de la rotación de la cámara. Me parece que no existe un valor límite estricto para el tamaño, pero que el efecto comienza a aumentar gradualmente desde cero cuando el vóxel aumenta en tamaño desde aproximadamente 2000 por lado.

Vea http://imgur.com/a/spQIv para una visualización. La primera imagen es cómo debería verse, pero cuando se gira la cámara, las líneas comienzan a distorsionarse como en la segunda imagen. El efecto empeora al aumentar el tamaño del vóxel y al girar más la cámara. http://imgur.com/a/wRndy contiene dos imágenes adicionales con un efecto más severo.

Las texturas (una X por textura) son originalmente 512 * 512 px. Las capturas de pantalla no han sido escaladas de ninguna manera.

Mi primera conjetura fueron las inexactitudes de flotación, pero eso es bastante difícil de creer, ya que el objeto tiene solo las dimensiones del orden de 1000.

Mi segunda suposición fue algún tipo de error de redondeo de flotante / int extraño, pero como todo se maneja siempre en flotadores, no veo cómo podría suceder esto.

La tercera posibilidad en la que podría pensar es que esto es simplemente imposible y que las texturas no deberían repetirse tantas veces. Sin embargo, esto parece bastante improbable IMO. Mi suposición (y espero) es que haya algún tipo de problema bastante elemental.

Cualquier sugerencia sobre lo que puede causar o comúnmente causa este tipo de cosas es muy apreciada, porque parece que me está costando mucho tiempo tratar de reducir el origen de este problema por mi cuenta.

Estoy usando:

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); gl.generateMipmap(gl.TEXTURE_2D);

y en el sombreador:

#ifdef GL_ES precision highp float; #endif

También realicé algunos cálculos muy elementales: para flotantes de 32 bits, el valor máximo es de alrededor de 8.4 millones. Para la longitud del lado del voxel 2000 (que noté que era el nivel donde el efecto se hacía visible), se podía esperar ingenuamente aproximadamente 0,00025 de un error de redondeo del flotador en las coordenadas. Suponiendo que cada repetición toma alrededor de 100 píxeles en la pantalla, el error debe ser significativamente menor que 1 píxel, que no es el caso. A menos que mi cálculo anterior se haya realizado incorrectamente, yo nominaría que Float32 no tiene la culpa y que el motivo debe ser otro.

La textura de línea se usa solo para visualizar el problema. El problema persiste también con otros tipos de texturas (más naturales).

Editar 2 comienza

Habilitar o deshabilitar el antialiasing no hace diferencia visible

Editar 2 extremos


Creo que lo que estás viendo puede ser causado por la precisión. Calculó correctamente que las coordenadas de coma flotante deberían ser bastante bonitas, el problema es que el hardware no usa flotadores para buscar las texturas. Las unidades de interpolador de textura tienen una precisión considerablemente menor (no sé cómo es hoy, pero solía ser tan baja como 16 bits en tarjetas GeForce más antiguas).

Entonces ... ¿cómo se puede superar la precisión del interpolador? Al usar coordenadas de textura grandes (muchas repeticiones) en una geometría grande, que es exactamente lo que estás haciendo. ¿Remedio? Subdividir su geometría para usar coordenadas de textura más pequeñas (puede cambiar las coordenadas de la textura en pasos enteros para que estén más cerca de 0).

Aquí hay una captura de pantalla de cuán extrema puede parecer (no pude reproducir el error en mi GeForce 260, pero es claramente visible en mi tableta Tegra 2, como se muestra en la imagen a continuación).


Me encontré con un problema similar en iOS. Después de repetir la textura 127 veces, comenzaron a suceder cosas malas.

La solución que funcionó fue esta:

GL_TRIANGLE_STRIP con algunos triángulos degenerados. La textura se alinea con los vertieces, por lo que en el borde de la textura hay un triángulo invisible (degenerado), donde la textura se "muestra" reflejada cuando configuro la coordenada de textura en el origen. Por lo tanto, el siguiente triángulo visible muestra la textura de la coordenada (0.0, 0.0) y nunca pasa por la coordenada (x, 127.0) .

Hay una publicación en el blog que explica esto con algunos ejemplos e imágenes.