¿Cómo implementar adecuadamente la mezcla alfa en una escena 3D compleja?

11

Sé que esta pregunta puede sonar un poco fácil de responder, pero me está volviendo loco. Hay demasiadas situaciones posibles que un buen mecanismo de mezcla alfa debería manejar, y para cada Algoritmo que se me ocurre, falta algo.

Estos son los métodos que he pensado hasta ahora:

  • En primer lugar, pensé en la ordenación de objetos por profundidad, este simplemente falla porque los objetos no son formas simples, pueden tener curvas y pueden bucle uno dentro del otro. Así que no siempre puedo decir cuál está más cerca de la cámara.

  • Luego pensé en ordenar triángulos, pero este también podría fallar, aunque no estoy seguro de cómo implementarlo, hay un caso raro que podría causar un problema, en el que dos triángulos se cruzan entre sí. De nuevo, nadie puede decir cuál está más cerca.

  • Lo siguiente fue usar el buffer de profundidad, al menos la razón principal por la que tenemos buffer de profundidad es por los problemas de clasificación que mencioné pero ahora tenemos otro problema. Como los objetos pueden ser transparentes, en un solo píxel puede haber más de un objeto visible. Entonces, ¿para qué objeto debo almacenar la profundidad de píxeles?

  • Entonces pensé que tal vez solo podría almacenar la mayor profundidad de objeto frontal, y usar eso determina cómo debería combinar las siguientes llamadas de dibujo en ese píxel. Pero nuevamente hubo un problema, piense en dos planos semitransparentes con un plano sólido en el medio. Iba a renderizar el plano sólido al final, uno puede ver el plano más distante. Tenga en cuenta que iba a fusionar cada dos planos hasta que solo quedara un color para ese píxel. Obviamente, también puedo usar métodos de clasificación por las mismas razones que he explicado anteriormente.

  • Finalmente, lo único que imagino que es capaz de trabajar es renderizar todos los objetos en diferentes objetivos de renderizado y luego ordenar esas capas y mostrar el resultado final. Pero esta vez no sé cómo puedo implementar este algoritmo.

Ali1S232
fuente

Respuestas:

11

Respuesta corta

Mira en el peeling profundo . Según mi investigación, parece ser la mejor alternativa, aunque computacionalmente costosa porque requiere múltiples pases de representación. Aquí hay otra implementación más reciente y más rápida , también de NVIDIA.

Respuesta larga

Esa es una pregunta difícil . La mayoría de los libros que he leído hojean el tema y lo dejo en:

Comience renderizando todos los objetos opacos y luego combine los objetos transparentes encima de ellos en orden de atrás hacia adelante.

Sin embargo, es más fácil decirlo que hacerlo, porque el enfoque obvio de ordenar objetos por sus centroides no garantiza el orden correcto.

Es exactamente el mismo problema por el cual el algoritmo del pintor no funciona para el caso general y se necesita un búfer de profundidad .

Dicho esto, uno de los libros que tengo menciona algunas soluciones:

  • Pelado de profundidad : una solución de múltiples pasadas que supera la limitación del búfer de profundidad al darnos los enésimos fragmentos más cercanos, no solo el más cercano. La mayor ventaja es que puede renderizar los objetos transparentes en cualquier orden, y no es necesario ordenarlos. Puede ser costoso debido a los múltiples pases, pero el enlace que proporcioné en la parte superior parece mejorar el rendimiento.

  • Stencil Routed K-Buffer : use el enrutamiento de plantilla para capturar múltiples capas de fragmentos por píxel por paso de geometría. La principal desventaja es que los fragmentos deben clasificarse en un pase de procesamiento posterior.

También menciona una solución de hardware para el problema, pero no creo que esté realmente disponible:

  • F-Buffer : un buffer FIFO de orden de rasterización para la renderización de múltiples pasadas. Sin embargo, una buena lectura y la introducción también hablan un poco sobre el problema del orden de transparencia y las soluciones actuales.

Otras soluciones que no proporcionan resultados perfectos pero son mejores que nada:

  • Después de renderizar todos los objetos opacos, siga usando las pruebas de Z-buffer para objetos transparentes pero desactive la escritura de Z-buffer . Es posible que obtenga algunos artefactos de una clasificación incorrecta, pero al menos todos los objetos transparentes serán visibles.

Y citando el documento técnico F-buffer arriba:

La solución más simple es renderizar cada polígono parcialmente transparente de manera completamente independiente (es decir, renderizar todas sus pasadas antes de pasar al siguiente polígono). Esta solución generalmente es prohibitivamente costosa debido al costo de cambio de estado en el que se incurre. Alternativamente, la aplicación o la biblioteca de sombreado puede agrupar polígonos para garantizar que solo los polígonos no superpuestos se procesen juntos. En la mayoría de los casos, esta solución tampoco es atractiva, ya que requiere que el software realice análisis de polígonos en el espacio de la pantalla.

David Gouveia
fuente
11

La respuesta correcta es la n.º 1: clasifique todas sus cosas por profundidad y renderícelas (obviamente desactive la escritura en profundidad, pero no las pruebas). ¿Qué es una "cosa"?

Cada "cosa" debe ser un objeto convexo; No puede superponerse. Si tiene un objeto cóncavo, debe dividirse en piezas convexas.

Esta es la forma estándar de renderizar una escena transparente. ¿Resuelve casos interpenetrantes? No. ¿Resuelve casos en los que tiene 3 objetos en los que no se puede determinar el orden de profundidad? No. ¿Resuelve casos en los que tienes un objeto largo que se superpone con uno pequeño que está más cerca en su profundidad central? No.

Pero funciona lo suficientemente bien . Los juegos no usan peeling profundo. No utilizan k-buffers enrutados por plantilla. No usan amortiguadores F. ¿Por qué? Porque estas cosas son increíblemente lentas.

Puede obtener artefactos con el método estándar. Pero al menos tu juego corre razonablemente rápido.

Si está dispuesto a restringirse a DX11 o un hardware mejor, hay formas de implementar la combinación con una clasificación adecuada. Son más lentos, pero no tan lentos como las técnicas anteriores. Y a diferencia de la exfoliación profunda que puede introducir artefactos, esta muestra es precisa. Además, el rendimiento del algoritmo generalmente es por fragmento (y hasta cierto punto por solapamiento dentro de cada fragmento). Entonces, si no dibujó muchas cosas transparentes, el rendimiento es mínimo.

No sé si la técnica tiene un nombre elegante, pero aquí se puede encontrar una implementación para pre-GL4.2. Puede encontrar una versión D3D11 aquí (Powerpoint, PPSX, compatible con Libre).

Nicol Bolas
fuente
Buenos puntos sobre esta respuesta. Personalmente, también me conformaré con lo suficientemente bueno (que describí en mi respuesta, como una solución alternativa) ya que la mayoría de las técnicas que enumeré probablemente sean más problemáticas de lo que valen. Además, una técnica interesante al final, no creo que estuviera en la lista de Renderizado en tiempo real en el que investigué mi respuesta. Soy un novato completo cuando se trata de características de nivel DX11.
David Gouveia
"Una implementación para pre-GL4.2 se puede encontrar aquí" 404
Jeroen van Langen