En OpenGL, ¿es una mala idea "combinar" el modo inmediato y el modo retenido en aras de las GUI?


8

Supongamos que tengo una escena 3D dibujada glDrawArrays(...)y quiero renderizar algo simple, como una superposición 2D. ¿Sería una mala idea usar el modo inmediato para tal cosa, en lugar de configurar un renderizador 2D con modo retenido?

Ejemplo:

void Draw()
{
    // Draw the 3D scene:
    // *does stuff*
    glDrawArrays(...);
    // *some other stuff*

    // Setup a quad with immediate mode (for something like a vignette overlay)
    glBegin(GL_QUADS);
    glTexCoord2f(...); glVertex2f(...);
    glEnd();
}

Minecraft hace esto. Funciona bien, excepto por limitar su versión de OpenGL (a <3.1 o un perfil de compatibilidad) y hacer que su GUI sea menos rápida.
user253751

Nota: Minecraft también tiene su propio conjunto de funciones que simulan el modo inmediato utilizando matrices de vértices; no es difícil escribir. Todavía no estoy seguro de si los están usando para la GUI.
user253751

Respuestas:


7

Es una mala idea en la medida en que no tiene sentido. No hay nada que "configurar" que aún no haya hecho, excepto una matriz de proyección ortopédica (que deberá hacer en cualquier caso).

La portabilidad probablemente no sea un problema, aunque debería serlo. Los IHV parecen ser muy reacios a abandonar el soporte para el modo inmediato en el futuro previsible (parece "funcionar bien" incluso en los perfiles principales), por lo que aunque el modo inmediato debería haberse extinguido hace mucho tiempo, probablemente se quedará para siempre. El rendimiento es otra historia. ¿Realmente desea que algo que represente el 0.1% de la complejidad de la escena consuma el 15-20% del tiempo de la CPU? Las llamadas GL son relativamente ligeras, en comparación con, por ejemplo, DX, pero no son gratuitas, y el 15-20% de tiempo de fotograma real debido al estancamiento de la tubería? ¿Incluso puede permitirse eso con su presupuesto de tiempo? La mayoría de los juegos no pueden.

Y luego, por supuesto, las peculiaridades. Oh las peculiaridades. La aparente belleza del modo inmediato es que es (aparentemente) fácil y directo hacer algo como dibujar un par de quads rápidamente. En realidad, el modo inmediato puede ser una molestia en la parte trasera, está lleno de trampas no obvias.
Por otro lado, es igual de fácil (¡y más sencillo si me preguntas!) Solo escribir una pequeña función de 5 LOC DrawQuadque cuando se llama agrega coordenadas e índices de vértice a un búfer de memoria e incrementa un contador. Con lo cual, sorprende, puedes dibujar glDrawArrays/Elementsy reutilizar (¡la copia de la GPU, no solo la copia del usuario!) El siguiente marco tal cual, siempre que no se cambie nada.
El modo inmediato debe, no hay otra manera, asignar un búfer y hacer una transferencia PCIe cada vez. O, algo equivalente en latencia (GPU leyendo la memoria principal a través del bus, lo que sea). El controlador no puede saber (o suponer) que los datos permanecieron exactamente igual que el marco anterior.

Llevar datos a la GPU es una operación de alta velocidad, pero también de alta latencia . No sólo es el traslado en autobús de por sí complicado protocolo de latencia a, alta (varias capas de protocolo, en paquetes, reconocimientos, etc.), sino que además no todas las GPU son incluso capaces de transferir y dibujar al mismo tiempo, o si ellos pueden hacerlo , es posible que no siempre puedan cambiar o iniciar nuevas operaciones libremente mientras hacen algo diferente. Lea como: No transferirás en vano .


"No hay nada que" configurar "que aún no haya hecho" ¿Procesamiento por lotes?
HolyBlackCat

2
Aunque los IHV son reacios a abandonar el modo inmediato, también hay controladores de video en Linux que no admiten una versión superior de OpenGL a menos que solicite Core Profile. Esto en particular significa gráficos Intel HD ( intelcontrolador), pero también chips NVidia y AMD cuando se utilizan controladores de código abierto ( nouveauy amdgpurespectivamente). Del mismo modo, en MacOS tampoco tiene el perfil de compatibilidad con OpenGL> 2.1.
Ruslan

@HolyBlackCat: ¿No estoy seguro de lo que quieres decir? OP afirma tener una tubería 3D en funcionamiento basada en glDrawArrays. Entonces, hay todo lo que se necesita para hacer otra llamada a glDrawElements(o Array, lo que sea) para dibujar todos los quads para la GUI (después de escribir los vértices en un búfer). Se cargan las funciones, tiene un marco para asignar buffers, etc. Nada especial que hacer para agrupar la GUI, realmente. Simplemente vincule (o no, si le quedan suficientes UT para dejarla unida) la textura de la GUI, configure la matriz orto y realice una llamada de sorteo adicional. ¿Cómo quieres lotes mejor?
Damon

(Por supuesto, estoy de acuerdo en que el modo inmediato es malo). Lo siento si no estaba claro. Me refiero al proceso de llenar dicho búfer de vértices. Eso es fácil, pero es un poco más trabajo que usar el modo inmediato.
HolyBlackCat

12

Personalmente solo lo veo como malo por dos razones:

  1. Está muy desactualizado y en desuso. Y,
  2. Es mucho más lento que las formas modernas de dibujar con OpenGL.

Pero, si está funcionando, y el rendimiento no va a ser un problema, y ​​si no es un problema para usted usar funciones OpenGL obsoletas en su programa, entonces creo que podría hacerlo. Será más lento tener TONELADAS y TONELADAS de GUI, pero si no son tantas, de nuevo, adelante.

Sin embargo, comprenda esto. Que al final del día, OpenGL está haciendo lo mismo; dibujando a la pantalla. El modo inmediato es mucho más lento si se procesan muchas cosas. Por lo tanto, debe elegir qué es lo más útil para la tarea que tiene en mente. ¡Espero que esto te ayude!


1

Otra desventaja es que hace que su código sea menos portátil. Ciertas variantes de OpenGL no admiten el modo inmediato en absoluto, por ejemplo, OpenGL ES. (y a medida que los dispositivos basados ​​en Android de mayor calibre, como las tabletas, ganan más tracción, podría ser importante)


0

Usar el modo inmediato es completamente innecesario para el trabajo relacionado con la interfaz gráfica de usuario.

Para crear un elemento gui simple, digamos, un botón:

  1. Necesitas una malla de tiras cuádruples / triangulares,
  2. Una textura para la malla
  3. Una transformación de proyección ortográfica

De esta manera, puede escribir un sombreador de paso simple que ignore las consideraciones de iluminación, y simplemente escale el elemento gui a una escala de píxeles, o algún porcentaje de la ventana, y luego haga un algoritmo de pintores para renderizar.

De esta manera, puede hacer un sistema de interfaz de usuario completo con todos los beneficios de rendimiento del modo retenido.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.