¿Es posible el renderizado / sombreado diferido con OpenGL ES 2.0?

20

Pregunté esto en StackOverflow , pero podría tener más sentido aquí:

¿Alguien ha implementado renderizado / sombreado diferido en OpenGL ES 2.0? No es compatible con MRT, por lo que con un solo búfer de color, no es algo que pueda implementarse de la manera "habitual".

Específicamente, estoy explorando en iPad, iPhone4 (maaaybe iPhone 3gs) y Android. En la aplicación GLESView en iPad / iPhone4 / iPhone3gs, la extensión GL_OES_RGB8_RGBA8 está presente, y aún no he buscado demasiado, pero con 8 bits / canal, esta idea es interesante: http://www.gamedev.net/topic/ 562138-opengl-es-20-and-diferido-sombreado /

¿Alguna otra idea? ¿Vale la pena hacerlo, en cuanto al rendimiento?

Jim Buck
fuente
Si es posible.
Quazi Irfan
77
¿A través de qué técnica (s)?
Jim Buck

Respuestas:

15

Sí, es posible. Sin embargo, no vale particularmente la pena.

Primero, a menos que tenga acceso a la extensión NV_draw_buffers (como su nombre lo indica, es solo NVIDIA. Por lo tanto, a menos que esté ejecutando en Tegra, no lo tiene), los objetos framebuffer en ES 2.0 solo pueden renderizar a una imagen a la vez Por lo tanto, para generar sus G-buffers, deberá renderizar su escena varias veces, eliminando así una de las ventajas del renderizado diferido.

En segundo lugar, el ancho de banda en las plataformas móviles no es el mismo que obtendría incluso en las GPU de grado medio. Y el ancho de banda es crítico para hacer que el renderizado diferido (para muchas luces) valga la pena. Sin ese ancho de banda, los pases de luz realmente van a doler, en cuanto al rendimiento.

En tercer lugar, el hardware PowerVR realmente no está diseñado para este tipo de cosas. Optimiza la representación con su hardware de representación basado en mosaicos. Por lo tanto, el renderizado diferido sería menos útil que en una arquitectura de conversión de escaneo tradicional.

Nicol Bolas
fuente
6

El principal problema es Fillrate. En las GPU móviles, su tasa de relleno es baja que no puede hacer Sombreado diferido en tiempo real con resolución nativa.

En iPhone 4 y iPad 1, el índice de llenado es simplemente ridículo. El único dispositivo IOS con buena velocidad de llenado es iPad 2, pero dudo que haya suficiente ... En Android, solo los dispositivos Tegra tienen GL_NV_draw_buffers para usar MRT pero la velocidad de llenado también es muy baja. El Mali 400 parece tener el mejor índice de llenado. Si quieres llorar, solo intenta llenar un rectángulo de color con resolución de pantalla completa 4 veces ... Muchos dispositivos no pueden hacerlo 60 fps.

En las GPU de escritorio, tiene una tasa de relleno 10 veces (o más) como gpus móvil. No olvide que las GPU móviles usan la misma memoria que la CPU y no tiene memoria dedicada.

Hay algunos ejemplos en WebGL (misma API), por lo que no es una limitación de la API.

Ellis
fuente
1
+1 para llenar la debilidad. Ni siquiera pude lograr que el desenfoque gaussiano se ejecutara con una resolución de 1536x2048 a 60 fps (inmediatamente bajó la velocidad de fotogramas a 30 fps, incluso con solo 4 muestras)
bobobobo
1
Creo que esto depende en gran medida de las sutilezas de su implementación y de comprender qué es lo que más impacta en el hardware móvil. Por ejemplo, estos chicos hicieron un desenfoque DoF moderadamente eficiente en 2012.
Ingeniero
1

Realmente debe considerar cuál es el mínimo absoluto que necesita para un renderizador diferido. Si recurre a la iluminación diferida, reduce la cantidad de datos que deben almacenarse en el GBuffer, y realmente es muchísimo más barato que renderizar la mitad de la escena 3 veces o más para admitir una cantidad baja de luces.

Yo elegiría el siguiente formato GBuffer:

  • Reutilice el búfer de profundidad para el pase de iluminación, no estoy seguro de cuán ampliamente se admite esto en dispositivos móviles, pero es una textura de profundidad libre.
  • Una sola textura GBuffer, dentro de ella, almacenaría: Normal U, Normal V, Param 0, Param 1. La codificación Lambert-Azimuthal se ve muy bien para los normales y los comprime en solo dos componentes, relativamente baratos para codificar y decodificar también.
  • Dos parámetros para las variables de iluminación son muchos, podría usar uno como una enumeración para múltiples funciones de iluminación si el hardware funciona bien con la ramificación dinámica.

La iluminación diferida es similar a la representación diferida, excepto que renderiza la escena dos veces:

  1. Procese los parámetros de profundidad de geometría, normales e iluminación en el GBuffer.
  2. Renderiza luces en el búfer de acumulación.
  3. Renderice geometría con sombreadores de materiales, componga su iluminación aquí también. Si eres bueno trabajando con operadores inversos de ecuaciones de iluminación, puedes hacer MUCHAS cosas realmente geniales con este paso.
  4. Haga cualquier procesamiento posterior que pueda pagar, asegúrese de abusar de la profundidad y las texturas normales hasta la muerte aquí por razones de eficiencia.

Sobre el almacenamiento de los resultados de iluminación. Me gusta almacenar el color difuso y la luminancia especular para que el búfer de acumulación solo tenga que ser una textura de color estándar de 32 bits. Puede estimar el color especular calculando el croma de color difuso y combinándolo con la luminancia especular.

Sin embargo, la parte más importante será usar el búfer de plantilla de profundidad al máximo, asegúrate de no mostrar nada del código de iluminación donde no es necesario. Incluso iría tan lejos como para agregar algunas declaraciones de descarte en los sombreadores de fragmentos en términos que disminuirán la visibilidad de la luz por debajo del rango visualizable del dispositivo (1e-3 suele ser un límite seguro).

cronosifter
fuente
discardes muy, muy malo para las tuberías basadas en mosaicos que utilizan muchas / la mayoría de las GPU móviles.
Ingeniero
1

Considere la iluminación diferida. En pocas palabras, la iluminación diferida es una técnica que utiliza una versión reducida de sombreado diferido para calcular un mapa de luz del espacio de pantalla. En una segunda pasada, la geometría se representa nuevamente utilizando el mapa de luz del espacio de pantalla como información de iluminación.

Esta técnica se utiliza para reducir el tamaño del G-Buffer, ya que se necesitan menos atributos. También le ofrece la ventaja de que el G-Buffer y el mapa de luz del espacio de pantalla pueden ser de menor resolución que la pantalla.

Había implementado un renderizador estricto basado en GLES 2.0 (aunque experimental), y logré reducir el G-Buffer a una textura RGBA (sí, usé una texture2D en lugar de un renderbuffer). Contenía el mapa normal del espacio de pantalla + el búfer de profundidad en el canal alfa (que estaba comprimido usando un logaritmo, hasta donde recuerdo).

Los atributos de posición (llamados mundo aquí) se pueden calcular durante el pase de iluminación utilizando el hecho de que, en una proyección en perspectiva, .xy se divide por .z , de modo que:

XyFrtusttumetro=Xyworlre/ /zworlre

Aproximé el atributo de posición xy haciendo:

Xyworlre=XyFrtusttumetrozworlre

Nota: Tuve que hacer más ajustes dependiendo de la configuración de la matriz de proyección.

También vale la pena señalar que fui capaz de omitir el componente .z de los vectores normales, ya que podría reconstruir .z a partir de .xy ya que el vector normal está normalizado de modo que:

X2+y2+z2=1X2+y2+z2=1z2=1-(X2+y2)z=1-(X2+y2)

Usando esta técnica, pude liberar otro canal en mi RGBA G-Buffer y lo usé para almacenar el espacio especular del mapa especular (o brillo, si lo desea).

Simon Schmidt
fuente
Por cierto: mi procesador no estaba conectado a ningún motor de juego. Fue merly aa hello world demo, representando a Suzanne.
Simon Schmidt
0

Sí, es absolutamente posible. La tasa de relleno no es un problema porque los chips de gráficos móviles están diseñados para manejar pantallas de muy alta resolución. De hecho, el renderizado diferido ayuda con esto porque su cálculo de iluminación es independiente de la complejidad de la escena, por lo que el sobregiro no causa una desaceleración. Aquí está mi implementación en un iPad de cuarta generación: http://www.youtube.com/watch?v=K4X1oF6b4V8

Si desea cuatro veces el rendimiento, solo la mitad de la resolución de la textura a la que renderiza. De todos modos, no puedo ver nada diferente con los gráficos 3D en una pantalla de retina.

Los chips de gráficos móviles son extremadamente buenos en el renderizado diferido debido a la forma en que manejan el renderizado a la textura. A diferencia de las tarjetas gráficas para PC, que generalmente sufren un gran impacto en el rendimiento cuando comienza a renderizar en una textura en lugar de un contexto de ventana, los gráficos móviles están diseñados para hacer esto sin impacto en el rendimiento. Por lo tanto, obtiene la escalabilidad de un renderizador diferido, sin la penalización de rendimiento inicial que experimenta en una tarjeta gráfica de escritorio.

En el momento de mi implementación, a OpenGLES le faltaba renderizar en múltiples objetivos, por lo que tuve que dibujar el color de la pantalla y lo normal en pasadas separadas. Esto puede solucionarse en versiones más recientes de OpenGLES, pero no se sabe si las soluciones todavía están disponibles en hardware móvil de consumo.

JoshKlint
fuente
3
"Los chips de gráficos móviles son extremadamente buenos en el renderizado diferido debido a la forma en que manejan el renderizado a la textura. A diferencia de las tarjetas gráficas de PC, que generalmente sufren un gran impacto de rendimiento cuando comienzas a renderizar en una textura en lugar de un contexto de ventana, los gráficos móviles son diseñado para hacer esto sin afectar el rendimiento ". Esa es una gran afirmación allí. ¿Tiene alguna referencia acreditada para respaldar este reclamo?
Panda Pyjama