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?
android
ios
opengl-es2
Jim Buck
fuente
fuente
Respuestas:
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.
fuente
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.
fuente
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:
La iluminación diferida es similar a la representación diferida, excepto que renderiza la escena dos veces:
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).
fuente
discard
es muy, muy malo para las tuberías basadas en mosaicos que utilizan muchas / la mayoría de las GPU móviles.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:
Aproximé el atributo de posición xy haciendo:
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:
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).
fuente
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.
fuente