2012-02-11 17 views
13

Estoy trabajando en un motor similar a Minecraft como un proyecto de pasatiempo para ver hasta qué punto el concepto de terrenos de voxel se puede impulsar en hardware moderno y OpenGL> = 3. Por lo tanto, toda mi geometría consiste en cuadrículas o casillas preciso.¿Cómo hacer la interpolación bilineal de normales en un quad?

He construido un raycaster para estimar la oclusión ambiental, y uso la técnica de "normales doblados" para hacer la iluminación. Entonces mis normales no son perpendiculares al quad, ni tienen longitud de unidad; más bien, señalan aproximadamente hacia el espacio donde está ocurriendo la menor oclusión, y son más cortos cuando el cuadrante recibe menos luz. La ventaja de esta técnica es que solo requiere un cálculo de una vez de la oclusión, y es esencialmente libre en el tiempo de renderizado.

Sin embargo, me encuentro con problemas cuando trato de asignar diferentes normales a diferentes vértices del mismo quad para obtener una iluminación suave. Debido a que el quad se divide en triángulos, y la interpolación lineal ocurre sobre cada triángulo, el resultado de la interpolación muestra claramente la presencia de los triángulos como artefactos diagonales feas:

Diagonal lines visible in the rendered result

El problema es que OpenGL utiliza barycentric interpolación sobre cada triángulo, que es una suma ponderada en 3 de las 4 esquinas. Idealmente, me gustaría utilizar la interpolación bilineal, donde las 4 esquinas se utilizan para calcular el resultado.

puedo pensar en algunas soluciones:

  1. Stuff las normales en una textura 2x2 RGB, y dejar que el procesador de la textura de hacer la interpolación bilineal. Esto ocurre a costa de una búsqueda de textura en el sombreador de fragmentos. También necesitaría empacar todas estas mini texturas en más grandes para mayor eficiencia.

  2. Utilice los atributos de vértice para unir las 4 normales a cada vértice. También adjunte algunos coeficientes [0..1] a cada vértice, al igual que las coordenadas de textura, y realice la interpolación bilineal en el sombreador de fragmentos. Esto ocurre a costa de pasar 4 normales al sombreado en lugar de sólo 1.

creo que estas dos técnicas se pueden hacer para trabajar, pero me parece que sea kludges para algo que debería ser mucho más simple. Tal vez podría transformar las normales de alguna manera, de modo que la interpolación de OpenGL daría un resultado que no depende de la triangulación particular utilizada.

(Tenga en cuenta que el problema no es específico de las normales, sino que es igualmente aplicable a los colores o cualquier otro valor que debe ser interpolado suavemente a través de un quad.)

¿Alguna idea de qué otra manera de abordar este problema? Si no, ¿cuál de las dos técnicas anteriores sería la mejor?

Respuesta

4

Como comprenderá claramente, la interpolación de triángulos que GL hará no es lo que desea. Entonces, los datos normales no pueden venir directamente de los datos de vértice.

Me temo que las soluciones que está visualizando son acerca de lo mejor que puede lograr. Y no importa lo que elijas, tendrás que pasar los coeficientes [0..1] del vértice al sombreador (incluidas las texturas 2x2. Las necesitas para las coordenadas de textura).

Sin embargo, hay algunos trucos que puede hacer para simplificar un poco el proceso.

  • Utilizando el ID de vértice puede ayudar a salir de la constatación qué vértice "esquina" para pasar de vértice a fragmentar shader (nuestros valores [0..1]). Una simple prueba de bits en los 2 bits más bajos puede hacerle saber qué esquina pasar, sin la entrada de datos de vértice real. Si empaca datos de textura, aún necesita pasar un identificador dentro de la textura, por lo que puede ser discutible.
  • si usa texturas 2x2 para permitir la interpolación, hay (¿hay?) Algunos errores. Algunos interpoladores de textura no necesariamente dan una interpolación de alta precisión si la fuente tiene poca precisión para empezar. Esto puede requerir que cambie el tipo de datos de textura a algo de mayor precisión para evitar artefactos de bandas.
0

Bueno ... como está utilizando la técnica de Bent normales, la mejor manera de aumentar el resultado es pre testar malla y volver a calcular con malla con mayor teselación.

Otra forma sería algunos trucos dentro del sombreador de píxeles ... una posible forma: en realidad, puede interpolar la textura por su cuenta (y no utilizar el interpolador incorporado) en el sombreador de píxeles, lo que podría ayudarlo mucho. Y no está limitado solo a la interpolación bilineal, podría hacerlo mejor, por ej. interpolación bicúbica;)

+0

No quiero aumentar la densidad de malla, ya que estoy tratando de expulsar la mayor cantidad de bloques posible. Sé cómo interpolar texturas por mi cuenta, pero no quiero almacenar mis normales en una textura si puedo evitarlo, ¡de ahí esta pregunta! – Thomas

Cuestiones relacionadas