Creo que es comúnmente aceptado que el tiempo real es todo lo que está por encima de lo interactivo. Y interactivo se define como "responde a la entrada pero no es uniforme en el hecho de que la animación parece irregular".
Entonces, el tiempo real dependerá de la velocidad de los movimientos que uno necesita representar. El cine proyecta a 24 FPS y es lo suficientemente real como para muchos casos.
Entonces, cuántos polígonos puede manejar una máquina es fácilmente verificable comprobándolo usted mismo. Simplemente cree un pequeño parche VBO como una prueba simple y un contador FPS, muchas muestras DirectX u OpenGL le darán el banco de pruebas perfecto para este punto de referencia.
Si tiene una tarjeta gráfica de gama alta, podrá ver aproximadamente 1 millón de polígonos en tiempo real. Sin embargo, como dijiste, los motores no reclamarán soporte tan fácilmente porque los datos de la escena del mundo real causarán una cantidad de cerdos de rendimiento que no están relacionados con el recuento de polígonos.
Tienes:
- tasa de relleno
- muestreo de textura
- Salida ROP
- dibujar llamadas
- renderizar interruptores de destino
- actualizaciones de búfer (uniforme u otro)
- girar en descubierto
- complejidad del sombreador
- complejidad de la tubería (¿alguna retroalimentación utilizada? ¿sombreado de geometría iterativa? ¿oclusión?)
- puntos de sincronización con la CPU (¿lectura de píxeles?)
- riqueza poligonal
Dependiendo de los puntos débiles y fuertes de una tarjeta gráfica en particular, uno u otro de estos puntos será el cuello de botella. No es como si pudieras decir con certeza "ahí, ese es".
EDITAR:
Quería agregar que, uno no puede usar la figura de especificaciones GFlops de una tarjeta específica y asignarla linealmente a la capacidad de empuje de polígonos. Debido al hecho de que el tratamiento de polígonos tiene que pasar por un cuello de botella secuencial en la tubería de gráficos como se explica con gran detalle aquí: https://fgiesen.wordpress.com/2011/07/03/a-trip-through-the-graphics -pipeline-2011-part-3 /
TLDR: los vértices tienen que caber en una pequeña caché antes del ensamblaje primitivo, que es una secuencia nativa (el orden del búfer de vértices es importante).
Si compara la GeForce 7800 (¿tiene 9 años?) Con la 980 de este año, parece que la cantidad de operaciones por segundo que es capaz de hacer se ha multiplicado por mil. Pero puede apostar que no va a empujar polígonos mil veces más rápido (lo que sería alrededor de 200 mil millones por segundo con esta simple métrica).
EDIT2:
Para responder a la pregunta "¿qué se puede hacer para optimizar un motor", como en "no perder demasiada eficiencia en los interruptores de estado y otros gastos generales".
Esa es una pregunta tan antigua como los propios motores. Y se está volviendo más complejo a medida que avanza la historia.
De hecho, en una situación del mundo real, los datos típicos de la escena contendrán muchos materiales, muchas texturas, muchos sombreadores diferentes, muchos objetivos y pases de renderizado, y muchos búferes de vértices, etc. Un motor con el que trabajé trabajó con la noción de paquetes:
Un paquete es lo que se puede representar con una llamada de sorteo.
Contiene identificadores para:
- tampón de vértice
- búfer de índice
- cámara (da el pase y el objetivo de renderizado)
- Identificación del material (da sombreador, texturas y UBO)
- distancia al ojo
- es visible
Entonces, el primer paso de cada cuadro es ejecutar una clasificación rápida en la lista de paquetes utilizando una función de clasificación con un operador que da prioridad a la visibilidad, luego pasar, luego material, luego geometría y finalmente distancia.
Dibujar objetos cercanos obtiene priroridad para maximizar el sacrificio Z temprano.
Los pases son pasos fijos, por lo que no tenemos más remedio que respetarlos.
El material es lo más caro para cambiar de estado después de renderizar objetivos.
Incluso entre diferentes ID de materiales, se puede realizar un suborden utilizando un criterio heurístico para disminuir el número de cambios de sombreado (más costoso dentro de las operaciones de cambio de estado del material) y, en segundo lugar, cambios de unión de textura.
Después de todo este pedido, uno puede aplicar mega texturizado, texturizado virtual y renderizado ( enlace ) sin atributos si lo considera necesario.
Acerca de la API del motor también una cosa común es diferir la emisión de los comandos de configuración de estado requeridos por el cliente. Si un cliente solicita "establecer cámara 0", es mejor simplemente almacenar esta solicitud y si más tarde el cliente llama "establecer cámara 1" pero sin otros comandos intermedios, el motor puede detectar la inutilidad del primer comando y soltarlo . Esta es la eliminación de la redundancia, que es posible mediante el uso de un paradigma "totalmente retenido". Por oposición al paradigma "inmediato", que sería solo un contenedor por encima de la API nativa y emitir los comandos correctamente según lo ordenado por el código del cliente. ( ejemplo: virtrev )
Y, por último, con el hardware moderno, un paso muy costoso (para desarrollar), pero potencialmente muy gratificante, es cambiar la API al estilo metal / mantle / vulkan / DX12 y preparar los comandos de renderizado a mano.
Un motor que prepara los comandos de representación crea un búfer que contiene una "lista de comandos" que se sobrescribe en cada cuadro.
Por lo general, existe una noción de "presupuesto" de marco, que un juego puede permitirse. Debe hacer todo en 16 milisegundos, por lo que debe dividir claramente el tiempo de GPU "2 ms para el paso de lightpre", "4 ms para el paso de materiales", "6 ms para la iluminación indirecta", "4 ms para los posprocesos" ...