Ich habe angefangen, den Stream Handmade Hero zu sehen , in dem Casey Muratori eine Game-Engine erstellt, ohne Frameworks oder ähnliches zu verwenden. Gestern bin ich zu dem Teil gekommen, wo er gezeigt hat, wie ein Bild auf den Bildschirm gezeichnet wird. Soweit ich es verstanden habe, hat er nur einen Speicher zugewiesen, der so groß ist wie der Bildschirm, auf den er zeichnen möchte. Dann erstellte er eine Bitmap, die er an den von ihm zugewiesenen Pufferspeicher weitergab und mit einer os-spezifischen Funktion auf den Bildschirm zog.
Das scheint ganz einfach zu sein. Ich habe GameMaker verwendet, zu Love2D gewechselt, ein bisschen mit Sprite Kit gearbeitet, aber ich habe mich immer gefragt, was wirklich unter diesen manchmal verwirrenden Ebenen passiert.
Warum sollten Sie sich überhaupt die Mühe machen, Grafikbibliotheken (OpenGL, SFML, SDL usw.) zu verwenden, wenn Sie lediglich einen Puffer zuweisen, eine Bitmap übergeben und auf den Bildschirm zeichnen müssen?
Wenn Sie dann verschiedene Dinge auf Ihren Bildschirm zeichnen möchten, schreiben Sie sie einfach in Ihre Bitmap, die dann in den Puffer übertragen wird. Ich bin ziemlich neu in der Programmierung, aber das scheint mir ziemlich einfach zu sein. Bitte korrigieren Sie mich, falls ich falsch liege.
quelle
Antworten:
Es geht nicht nur um die Geschwindigkeit der Ausführung, sondern auch um die Einfachheit. Obwohl das in diesem Beispiel verwendete Software-Rendering viel langsamer ist als das Verwenden der Hardwarebeschleunigung (dh einer GPU), ist das Zeichnen einiger Bitmaps auf dem Bildschirm eine so einfache Aufgabe, dass Sie den Leistungsabfall nicht bemerken.
Aktivitäten auf niedriger Ebene wie Dreiecksrasterung, Tiefensortierung und dergleichen sind jedoch allgemein bekannte Konzepte, die die GPU mit wenigen Befehlen implizit verarbeiten kann. Die Neuimplementierung im Softwaremodus erfindet das Rad grundlegend neu. Dies ist in Ordnung, wenn Sie ein grundlegendes Verständnis für das Rendern erlangen möchten. Ich selbst habe einen 3D-Software-Renderer geschrieben, um es ein wenig zu untersuchen. In den meisten Fällen ist es jedoch Zeitverschwendung, wenn OpenGL es schneller erledigt die Kiste.
Das Beispiel, das Sie angegeben haben, klingt äußerst einfach: Es wird nur ein einzelnes Bild auf den Bildschirm gezeichnet, daher ist die Implementierung einfach. Sobald Sie jedoch anfangen, die Komplexität zu überlagern, wird es immer komplizierter, alles richtig zu rendern. Die Dinge, die die Leute in den Quake-Tagen des Renderns von 3D-Software zu tun hatten, waren verrückt, obwohl ich es zu schätzen weiß, dass Sie (noch) nicht so weit kommen.
quelle
Kurz: Weil es schnell ist (OpenGL, DirectX).
Lange:
Sie können denken, Sie können dies alles selbst tun. Zeichnen Sie Pixel auf einen Bildschirm. Sie können eine kleine Bibliothek schreiben, um Formen wie Quadrate oder Dreiecke zu zeichnen. Das wird natürlich funktionieren. Es gibt viele Bibliotheken, die genau das tun. Einige von ihnen implementieren sogar die OpenGL-Spezifikation (sozusagen eine Softwareseite für OpenGL), die genau das tut, was Casey Muratori tut. Sie berechnen alles auf der Softwareseite, setzen die Pixel auf der Softwareseite und schreiben das Ergebnis auf den Bildschirm.
Dies ist jedoch langsam . Die CPU, die letztendlich all diese Dinge ausführen wird, wurde für dieses Szenario nicht erstellt. Dafür sind GPUs da. Was OpenGL macht (es sei denn, es ist eine Software-Implementierung), ist, alles zu nehmen, was Sie sagen, und alle Daten, alle Draw-Calls, fast alles auf die Grafikkarte zu übertragen und die GPU zu beauftragen, die Arbeit zu erledigen. Die GPU ist speziell für diese Art von Arbeit gemacht. Multiplizieren von Gleitkommazahlen (das ist, was Sie viel tun, wenn Sie eine 3D-Szene zeichnen) und Ausführen von Shadern. Und das parallel. Um Ihnen ein Gefühl dafür zu geben, wie schnell die GPU ist, stellen Sie sich eine einfache 3D-Szene im Vollbildmodus mit 1920 x 1080 Pixeln vor. Dies sind multipliziert 2.073.600 zu zeichnende Pixel. Für jeden EinzelnenPixel, die GPU wird den Fragment-Shader ausführenmindestens einmal , meistens mehr als einmal. Nehmen wir an, wir laufen mit 60 Bildern pro Sekunde. Dies bedeutet, dass die GPU den Fragment-Shader 2.073.600 * 60 = 124.416.000 Mal pro Sekunde ausführt . Glaubst du, du kannst so etwas auf deiner CPU machen? (Das ist eine ziemlich vereinfachte Erklärung. Es gibt noch viel mehr Dinge zu überlegen, wie viele Pixel Sie mit näheren Objekten überzeichnen, wie viel MSAA Sie verwenden und so weiter. Die 124.416.000 Mal pro Sekunde sind jedoch wahrscheinlich die niedrigsten, die Sie erhalten können, und Sie werde mit einer einfachen Szene leicht viel mehr als 60fps haben)
Das ist, was OpenGL und Direct3D tun, für welche Engines @Uri Popovs Antwort sehen.
quelle
Was er tut, heißt Software-Rendering , was OpenGL tut, heißt GPU-Rendering
Was ist der Unterschied zwischen ihnen? Geschwindigkeit und Gedächtnis.
Die Rasterung (Ausfüllen von Dreiecken auf dem Bildschirm) dauert einige Zeit. Wenn Sie dies auf der CPU tun, nehmen Sie sich im Wesentlichen die Zeit für die Spielelogik, insbesondere wenn diese nicht gut optimiert ist.
Und egal, wie klein das Bild ist, er muss eine bestimmte Menge an Speicher dafür reservieren. GPUs haben dafür einen Videospeicher.
quelle
Während die Antworten von anderen korrekter sind als jede andere Antwort, möchte ich auf das grundsätzliche Missverständnis hinweisen, wie Softwareentwicklung funktioniert, von dem ich denke, dass es Ihrer Frage zugrunde liegt. Obwohl es immer möglich ist, Dinge "selbst" ohne ein Framework zu tun, und dies oftmals einen großen pädagogischen Vorteil mit sich bringt, ist es in der Realität nicht so, wie moderne Software erstellt wird.
Jemand hat die Hardware und die Maschinensprachen erstellt, die darauf ausgeführt werden. Jemand anderes erstellt höhere Sprachen und Compiler, Treiber und Betriebssysteme, Grafikbibliotheken und so weiter. Wir alle bauen auf der Arbeit unserer Vorgänger auf. Das ist nicht nur "okay", es ist eine Voraussetzung.
Sie zeichnen die Linie dessen, was "akzeptabel" ist oder nicht, an einem beliebigen Punkt in der Toolchain. Sie könnten genauso leicht sagen: "Warum sollten Sie C ++ verwenden, wenn Sie dasselbe in der Montage tun könnten?" Es gibt nicht genug Stunden am Tag oder Jahre im Leben, damit jeder alles selbst machen kann.
Dies gilt nicht nur für die Softwareentwicklung, sondern für das moderne Leben im Allgemeinen. Haben Sie jemals von dem Typ gehört, der selbst einen Toaster gebaut hat? http://www.thomasthwaites.com/the-toaster-project/ . Es hat sehr viel Zeit und Mühe gekostet. Für einen Toaster. Versuchen Sie, alles , was Sie brauchen, um ein Videospiel zu verwirklichen, selbst zu erstellen!
quelle
Motoren leisten viel mehr, als nur ein Bild auf den Bildschirm zu zeichnen. Sie kümmern sich um Beleuchtung, Schatten, Eingabe und Kollisionserkennung. Selbst der Rendering-Teil ist weitaus komplexer als nur ein Puffer auf den Bildschirm zu schieben. Insbesondere für 3D-Szenen müssen Sie eine Menge Berechnungen mit weitaus komplexeren Daten als einer Bitmap durchführen. Lassen Sie mich eine Analogie zu einem Auto geben: Was Sie als einfach bezeichnen, ist der Auspuff des Autos. Sie machen einfach eine Pfeife mit der richtigen Größe und schieben dann das Gas von einem Ende zum anderen. Dies ist jedoch bei weitem nicht das Einzige, was im Mechanismus des Autos passiert.
quelle
Die obigen Antworten sind ausgezeichnet, aber keiner geht wirklich über den wichtigsten Grund, warum OpenGL und dergleichen bevorzugt werden. Der Hauptgrund ist die Verwendung dedizierter Hardware, die speziell für das Rendern von Millionen von Pixeln auf einem Bildschirm, der GPU, entwickelt wurde .
Beim Software-Rendering unter Verwendung der CPU durchläuft der Renderer nacheinander alle Pixel auf einer Bitmap und gibt Befehle aus, die jeweils auf dem Bildschirm angezeigt werden. Wenn Sie also ein Image in der Größe 1000x1000 rendern, werden 1.000.000 Loops für Ihre CPU ausgeführt. Sie sind schließlich auf Kontrolle ausgelegt; viele if-Bedingungen, Springen von einem Befehlssatz zum nächsten und eine strikte Richtung des Kontrollflusses. Eine GPU ist jedoch so konzipiert, dass sie genau weiß, was sie tun wird eine Menge ähnlicher Schleifen über Pixel auf dem Bildschirm ausführt.Eine GPU nimmt eine for-Schleife mit 1000000 Iterationen und teilt die Arbeit auf die große Anzahl von Kernen auf, damit jede parallel und unabhängig voneinander arbeitet. Im Gegensatz zur CPU verarbeitet eine GPU jedes Mal, wenn sie auf eine if-else-Bedingung stößt, beide Codezweige zu zwei Kernen von sich selbst, UND DANN wird ganz am Ende geprüft, wie die Bedingung ausgewertet und verworfen wird Ergebnis der nicht benötigten Verzweigung (daher werden viele If-else-Bedingungen in GPU-Shadern missbilligt; sie sind immer für eine Verschwendung verantwortlich).
Also ja, GPUs basieren auf Parallelität . Das macht das Arbeiten mit Pixeln für sie im Vergleich zu CPUs viel schneller.
quelle
Siehe Muss ich wirklich eine Grafik-API verwenden?
Sicher, Sie können nach einem Puffer fragen, einige Bits darin setzen und ihn auf den Bildschirm schreiben. Dies war im Wesentlichen die einzige Möglichkeit, die Grafikprogrammierung auf dem PC durchzuführen, bis Mitte der 90er-Jahre Grafikbeschleuniger von 3DFX zur Verfügung standen. Selbst unter Windows wurde DirectX entwickelt, um direkten Zugriff auf den Videospeicher zu ermöglichen.
Auf Nicht-PC-Hardware, dedizierten Spielautomaten, gab es jedoch schon immer Techniken zur Beschleunigung der Grafik, indem die Arbeit vom Prozessor abgeladen wurde. Sogar der Atari 2600 hatte "Hardware-Sprites", zum Teil, weil er nicht genug RAM für einen Framebuffer hatte.
Später (Mitte der 80er Jahre) wurden Spielekonsolen für Plattformspiele optimiert. Wieder kein Framebuffer; Stattdessen kann der Programmierer Raster von Kacheln angeben :
quelle
Moderne CPUs sind schnell genug, um 2d-Spiele in Software zu erstellen. Für 2d-Grafiken bietet OpenGL / DirectX also keine Vorteile, außer dass Sie Ihrem Projekt noch eine weitere Abhängigkeit und Komplexität hinzufügen, z. B. das Festlegen einer 3D-Projektionsmatrix zum Zeichnen einer Gruppe von Sprites und Hochladen von Daten auf die GPU.
OpenGL würde Sie auch dazu zwingen, alle Ihre Sprites in 512x512-Texturen zu packen (ein Artefakt alter Konsolen wie PSX, das Grafiken in Videospeicherseiten packt), und Sie müssten ziemlich komplexen Sprite-Packcode schreiben.
Wenn Sie dagegen 3D ausführen und Millionen von Dreiecken mit komplexer Schattierung rendern, ist eine GPU unvermeidlich. Vor langer Zeit gab es eine einfachere Nur-2d-Version von Direct3d namens DirectDraw, die das Sprite-Zeichnen mit der GPU beschleunigte. Jetzt unterstützt Microsoft sie jedoch nicht mehr .
quelle