opengl opengl-es libgdx opengl-es-2.0

opengl - Apagar todo fuera de un polígono



opengl-es libgdx (1)

Tengo un mapa, por simplicidad digamos que es solo una textura. En la parte superior de este mapa, tengo un polígono que indica la ruta que el usuario debe seguir.

Lo que quiero es dibujar todo fuera del polígono negro. O, por supuesto, solo dibujar cosas dentro del polígono.

Para explicarlo mejor, hice una foto. Las líneas azules definen el polígono, siendo cada esquina un punto en el polígono. El rojo con líneas amarillas es la parte que quiero borrar de la imagen, y solo deja el rojo con las líneas violetas. El polígono comienza desde A y termina en B.


El principal desafío aquí es que debe dibujar un polígono no convexo, que OpenGL no admite directamente. Un enfoque para dibujarlo es dividirlo en triángulos. Dependiendo de cuánto sabe sobre la forma del polígono, y cómo es la restricción, esto podría ser bastante fácil. Para un polígono general no convexo, es un poco doloroso. Pero existen algoritmos que puede encontrar si busca palabras clave como "triangulación de polígonos".

OpenGL tiene otro mecanismo que funciona muy bien para este tipo de casos de uso: memorias intermedias de esténcil. Puede encontrar una explicación de este enfoque en el Libro rojo bajo Dibujo relleno, polígonos cóncavos utilizando el tampón de esténcil . La idea principal es que puedes dibujar un triángulo de abanico con un origen arbitrario y tus vértices de polígono. Los píxeles que están dentro del polígono se dibujarán un número impar de veces, mientras que los píxeles fuera de los polígonos se dibujarán un número par de veces. El buffer de esténcil se usa para rastrear el conteo impar / par de cuantas veces se dibuja cada píxel.

Para delinear los pasos principales:

  1. Mientras configura su contexto y superficie de dibujo, asegúrese de solicitar una configuración con un buffer de esténcil.
  2. Durante el dibujo, borre el tampón del esténcil junto con el tampón de color y active la prueba del esténcil.

    glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glEnable(GL_STENCIL_TEST);

  3. Configure el estado para el pase de representación que cuenta si los píxeles se representan como un número impar / par de veces. Tenga en cuenta que esto solo debe escribir en el buffer de esténcil, por lo que las escrituras en color están deshabilitadas. La parte clave es GL_INVERT para la GL_INVERT de símbolos, que invierte el valor de la plantilla cada vez que se representa un píxel, lo que nos da el conteo impar / par.

    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glStencilFunc(GL_ALWAYS, 0, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); glStencilMask(1);

  4. Representa un abanico de triángulos con un punto arbitrario, por ejemplo, (0.0, 0.0), como el primer vértice, y las esquinas del polígono como los vértices restantes. El polígono debe estar cerrado, por lo que la primera y la última esquina del polígono deben ser iguales. Si p1, p2, ..., pN son las esquinas de tu polígono, la secuencia de vértices para la GL_TRIANGLE_FAN sorteo GL_TRIANGLE_FAN es:

    (0.0f, 0.0f), p1, p2, ... , pN, p1

    Puede usar un sombreador trivial para este pase ya que el valor del color ni siquiera está escrito.

  5. Habilite las escrituras de color nuevamente y configure los atributos de prueba de galería de símbolos para representar solo los píxeles que se representaron un número impar de veces en la pasada anterior.

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilFunc(GL_EQUAL, 1, 1); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

  6. Dibuja todo tu contenido. Solo se representará la parte dentro del contorno del polígono, el resto se eliminará mediante la prueba del esténcil.