Comencé a ver la transmisión de Handmade Hero , donde Casey Muratori crea un motor de juego sin usar frameworks o tal. Ayer llegué a la parte donde mostró cómo se dibuja una imagen en la pantalla. Según tengo entendido, él solo asignó un poco de memoria tan grande como el tamaño de la pantalla a la que quiere dibujar. Y luego creó un mapa de bits que pasó a la memoria intermedia que asignó y lo dibujó en la pantalla usando una función específica del sistema operativo.
Esto parece bastante sencillo. Usé GameMaker, cambié a Love2D, trabajé un poco con Sprite Kit, pero siempre me preguntaba qué estaba pasando realmente debajo de estas capas a veces confusas.
Dado eso, ¿por qué molestarse en usar bibliotecas de gráficos (OpenGL, SFML, SDL, ...) cuando todo lo que tiene que hacer es simplemente asignar algo de búfer, pasar un mapa de bits y dibujarlo en la pantalla?
Si luego desea dibujar cosas distintas en su pantalla, simplemente escríbalas en su mapa de bits que luego se pasa al búfer. Soy bastante nuevo en programación, pero esto me parece bastante simple. Por favor corrígeme si estoy equivocado.
fuente
Respuestas:
No se trata solo de la velocidad de ejecución, sino también de la simplicidad. Aunque la representación del software utilizada en este ejemplo sería mucho más lenta que el uso de la aceleración de hardware (es decir, una GPU), dibujar algunos mapas de bits en la pantalla es una tarea tan trivial que no notará la caída del rendimiento.
Sin embargo, la actividad de bajo nivel como la rasterización de triángulos, la clasificación de profundidad y similares son conceptos bien entendidos que la GPU puede manejar implícitamente con unos pocos comandos. Re-implementar aquellos en modo software es esencialmente reinventar la rueda. Esto está bien si desea obtener una comprensión de bajo nivel de cómo se realiza el renderizado, yo mismo escribí un renderizador de software 3D solo para explorarlo un poco, pero para la mayoría de las circunstancias es una pérdida de tiempo cuando OpenGL puede hacerlo más rápido. la caja.
El ejemplo que ha dado suena extremadamente básico, simplemente dibujando una sola imagen en la pantalla, por lo tanto, la implementación es fácil. Sin embargo, una vez que comience a superponer la complejidad, verá que se vuelve cada vez más complicado hacer que todo se represente correctamente. Lo que la gente tenía que hacer en los días del terremoto de la representación del software 3D era una locura, aunque aprecio que no vayas tan lejos (todavía).
fuente
Corto: porque es rápido (OpenGL, DirectX).
Largo:
Puede pensar que puede hacerlo todo usted mismo. Dibuja píxeles en una pantalla. Puede escribir una pequeña biblioteca para dibujar formas, como quads o triángulos. Esto funcionará, por supuesto. Hay muchas bibliotecas por ahí para hacer exactamente esto. Algunos de ellos incluso implementan la especificación OpenGL (por lo que son como un lado del software para opengl) que hará exactamente lo que hace Casey Muratori. Calculan todo en el lado del software, establecen los píxeles en el lado del software y escriben el resultado en la pantalla.
Sin embargo esto es lento . La CPU que eventualmente ejecutará todas estas cosas no fue hecha para este escenario. Para eso están las GPU. Lo que hace OpenGL (a menos que sea una implementación de software, por supuesto) es tomar todo lo que le diga que haga y enviar todos los datos, todas las llamadas de extracción, casi todo a la tarjeta gráfica y decirle a la GPU que haga el trabajo. La GPU está hecha específicamente para este tipo de trabajo. Multiplicar números de coma flotante (eso es lo que hace mucho cuando dibuja una escena 3D) y ejecutar sombreadores. Y esto en paralelo. Solo para tener una idea de lo rápido que es la GPU, piense en una escena simple en 3D en pantalla completa con 1920x1080 píxeles. Estos son, multiplicados, 2,073,600 píxeles para dibujar. Por cadapíxel, la GPU ejecutará el fragment-shader al menos una vez , la mayoría de las veces más de una vez. Ahora, digamos que corremos a 60 cuadros por segundo. Esto significa que la GPU ejecuta el fragment-shader 2,073,600 * 60 = 124,416,000 veces por segundo . ¿Crees que puedes hacer algo así en tu CPU? (Esa es una explicación bastante simplificada, hay muchas más cosas a tener en cuenta, como cuántos píxeles dibuja sobre objetos cercanos, cuánto MSAA usa, etc., sin embargo, las 124,416,000 veces por segundo son probablemente las más bajas que puede obtener, y usted fácilmente tendrá mucho más de 60 fps con una escena simple)
Eso es lo que hacen OpenGL y Direct3D, para lo que hacen los motores, vea la respuesta de @Uri Popovs.
fuente
Lo que hace se llama representación de software , lo que hace OpenGL se llama representación de GPU
¿Cual es la diferencia entre ellos? Velocidad y memoria.
La rasterización (completar triángulos en la pantalla) lleva algún tiempo. Si lo hace en la CPU, esencialmente le quita ese tiempo a la lógica del juego, especialmente si no está bien optimizado.
Y no importa cuán pequeña sea la imagen, necesita asignarle cierta cantidad de memoria. Las GPU tienen una memoria de video para esto.
fuente
Si bien las respuestas de otros son más correctas que cualquier respuesta que pueda dar, quiero señalar el malentendido fundamental sobre cómo funciona el desarrollo de software que creo que subyace en su pregunta. Si bien siempre es posible hacer las cosas "solo" sin un marco, y a menudo hay un gran beneficio educativo al hacerlo, la realidad es que no es así como se crea el software moderno.
Alguien creó el hardware y los lenguajes de máquina que se ejecutan en él. Alguien más crea lenguajes y compiladores de nivel superior, controladores y sistemas operativos, bibliotecas de gráficos y así sucesivamente. Cada uno de nosotros construimos sobre el trabajo de nuestros predecesores. Eso no es solo "está bien", es un requisito.
Estás dibujando la línea de lo que es "aceptable" o no en un punto arbitrario de la cadena de herramientas. Podría decir con la misma facilidad "¿por qué usar C ++ cuando podría hacer lo mismo en el ensamblaje?", O "¿por qué confiar en los controladores del teclado cuando podría leer fácilmente los voltajes que salen de sus cables y calcularlos usted mismo?" No hay suficientes horas en el día o años en la vida para que todos puedan hacer todo por sí mismos.
Esto no se aplica solo al desarrollo de software, sino a la vida moderna en general. ¿Alguna vez has oído hablar del chico que construyó una tostadora, desde cero? http://www.thomasthwaites.com/the-toaster-project/ . Tomó mucho tiempo y mucho esfuerzo. Para una tostadora ¡Intenta construir todo lo necesario para actualizar un videojuego fuera del éter por tu cuenta!
fuente
Los motores hacen mucho más que simplemente dibujar una imagen en la pantalla. Manejan la iluminación, las sombras, la entrada, la detección de colisiones. Incluso solo la parte de representación es mucho más compleja que simplemente empujar un búfer en la pantalla. Especialmente para escenas 3D, debe hacer muchos cálculos con datos mucho más complejos que un mapa de bits. Permíteme darte una analogía con un automóvil: lo que estás describiendo como simple es el escape del automóvil. Simplemente haces una tubería con el tamaño correcto y luego empujas el gas de un extremo al otro. Sin embargo, esto está lejos de ser lo único que sucede en el mecanismo del automóvil.
fuente
Las respuestas anteriores son excelentes, pero ninguna realmente pasa por la razón más importante de por qué se prefiere OpenGL y tal. La razón principal es hacer uso de hardware dedicado diseñado especialmente para trabajar con cosas como renderizar millones de píxeles en una pantalla, la GPU .
Con el renderizado de software, usando la CPU, el renderizador se repetirá, uno por uno, sobre todos los píxeles en un mapa de bits y emitirá órdenes para mostrar cada uno en la pantalla. Entonces, si está renderizando una imagen de tamaño 1000x1000, esos 1,000,000 bucles para que su CPU repita. Están diseñados teniendo en cuenta el control después de todo; muchas condiciones, saltando de un conjunto de instrucciones a otro y una estricta dirección de flujo de control. Sin embargo, una GPU está diseñada con el conocimiento de que realizará muchos bucles similares sobre píxeles en la pantalla.Una GPU tomaría un ciclo for con 1000000 iteraciones y dividiría el trabajo entre su gran cantidad de núcleos para que cada uno trabaje ** en paralelo e independiente el uno del otro **. Entonces, a diferencia de la CPU, cada vez que una GPU se encuentra con una condición if-else, manejará ambas ramas de código en dos núcleos de sí misma Y LUEGO, al final, verá qué evalúa la condición y descarta el resultado de la rama innecesaria (es por eso que muchas condiciones if-else en sombreadores GPU están mal vistas; siempre son responsables de un desperdicio).
Entonces, sí, las GPU se basan en el paralelismo . Eso hace que trabajar en píxeles para ellos sea mucho más rápido en comparación con las CPU.
fuente
Consulte ¿Realmente necesito usar una API de gráficos?
Claro, puede solicitar un búfer, configurar algunos bits y escribirlo en la pantalla. Esa era esencialmente la única forma de hacer programación de gráficos en la PC hasta la disponibilidad de aceleradores de gráficos a mediados de los 90 de 3DFX. Incluso en Windows, DirectX fue desarrollado para dar acceso directo a la memoria de video.
Pero en el hardware que no es de PC, máquinas de juegos dedicadas, siempre ha habido técnicas para acelerar los gráficos al descargar el trabajo del procesador. Incluso el Atari 2600 tenía "sprites de hardware", en parte porque no tenía suficiente RAM para un framebuffer.
Las consolas de juegos posteriores (mediados de los 80) fueron optimizadas para juegos de plataforma. De nuevo, no framebuffer; en cambio, el programador podría especificar cuadrículas de mosaicos :
fuente
Las CPU modernas son lo suficientemente rápidas como para hacer cualquier juego 2D en software, por lo que para gráficos 2D OpenGL / DirectX no ofrecería ventajas, además de agregar otra dependencia y una capa de complejidad a su proyecto, como, por ejemplo, configurar una matriz de proyección 3D para dibujar un montón de sprites y cargando datos a GPU.
OpenGL también lo obligaría a empaquetar todos sus sprites dentro de texturas de 512x512 (un artefacto de consolas antiguas, como PSX, empaquetando gráficos en páginas de memoria de video), requiriéndole que escriba un código de empaque de sprites bastante complejo.
Por otro lado, si está haciendo 3d, renderizando millones de triángulos con sombreado complejo, entonces la GPU es inevitable. Hace mucho tiempo, existía una versión más simple en 2D de Direct3d, llamada DirectDraw, que GPU aceleró el dibujo de sprites, pero ahora Microsoft ya no lo admite, posiblemente porque las CPU son lo suficientemente rápidas para hacer 2D sin aceleración, si no le importa el ahorro de energía. .
fuente