Einfache 3D Engine
-
- Establishment
- Beiträge: 140
- Registriert: 03.10.2010, 20:14
Einfache 3D Engine
Hi,
kann mir jemand von euch alten Hasen ein paar Tipps geben, wie ich am besten eine (einfache) 3D Engine (DX) aufbaue?
Ich hab bisher nur mit 2D gearbeitet und hatte da einen Renderer, der die Kommunikation zwischen Engine und DX übernommen hat.
In 2D ging das ohne Probleme, allerdings weis ich nicht, ob es da bei 3D (was ja viel Resourcen-intensiver ist) zu langsam wird. Das Ganze soll dann auch mit wxWidgets kompatibel sein.
Wie baue ich am besten eine 3D Engine auf, was muss ich beachten, um am Ende nicht in ein Frame-Loch zu fallen?
Noch eine weitere Frage: lohnt es sich für eine einfach 3D Engine mit DX11 zu arbeiten? Oder sollte man doch aus Gründen der Kompatibilität mit DX9 oder 10 arbeiten? Ich hab bisher nur Erfahrung mit DX9.
Gruß
kann mir jemand von euch alten Hasen ein paar Tipps geben, wie ich am besten eine (einfache) 3D Engine (DX) aufbaue?
Ich hab bisher nur mit 2D gearbeitet und hatte da einen Renderer, der die Kommunikation zwischen Engine und DX übernommen hat.
In 2D ging das ohne Probleme, allerdings weis ich nicht, ob es da bei 3D (was ja viel Resourcen-intensiver ist) zu langsam wird. Das Ganze soll dann auch mit wxWidgets kompatibel sein.
Wie baue ich am besten eine 3D Engine auf, was muss ich beachten, um am Ende nicht in ein Frame-Loch zu fallen?
Noch eine weitere Frage: lohnt es sich für eine einfach 3D Engine mit DX11 zu arbeiten? Oder sollte man doch aus Gründen der Kompatibilität mit DX9 oder 10 arbeiten? Ich hab bisher nur Erfahrung mit DX9.
Gruß
- Schrompf
- Moderator
- Beiträge: 5149
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Einfache 3D Engine
Das Letzte zuerst: Nimm DirectX11. Die schönere API, schneller, moderner, konsistenter, aber Du büßt aktuell noch etwa 15% des Kundenstamms ein. Daten laut Steam Hardware Survey.
Ein "einfacher" Renderer... hm. Halbwegs zukunftssicher würde ich das so aufbauen:
Engine:
- kann "Renderszene" anfangen, gibt ein entsprechendes Objekt zurück
- kann "Renderszene" beenden, nimmt Objekt entgegen und führt es aus
Renderszene:
- wird von Engine verwaltet
- wird initialisiert mit ViewMatrix, ProjectionMatrix, RenderTarget, plus Bonusparameter
- nimmt Lichter entgegen: Position, evtl. Kegelgrenzen für SpotLights, Farbe, evtl. Rotation, evtl. Farbtextur, evtl. Schatten-Textur-Referenzen als Ergebnis einer vorherigen Renderszene
- nimmt DrawCalls entgegen: Mesh, Material, WorldMatrix, SequenzID zum Sortieren untereinander
- macht bei Beenden durch Engine dann Folgendes: DrawCalls sortieren, ausführen
Mesh:
- für's erste ein VertexBuffer und evtl. ein IndexBuffer
Material:
- Shader
- Shader-Parameter
- Shader-Texturen
Ich würde außerdem so eine Art "Kontext"-ID erfinden. Das kann ein simpler Array-Index sein, wenn Du irgendwo vorab in der Engine alle möglichen Kontexte definierst. Im Shader speicherst Du dann pro KontextId einen alternativen Shader, der statt des eigentlichen Shaders eingesetzt wird. Das halte ich für Pflicht, wenn Du zum Beispiel einen Schatten-Pass für eine Lichtquelle machen willst. Es gibt dann einen Kontext "Schatten für Punktlichter" und jeder Shader gibt an, welcher Shader statt seiner selbst die ShadowMap für dieses Material ausrendert. Alle normalen Oberflächenshader verweisen dann auf einen Tiefen-Output, alle AlphaTest-Shader verweisen auf einen Tiefen-Output mit AlphaTest, usw. Darüber kann man auch Shader vereinfachen, wenn man zum Beispiel Spiegelungen ausrendert, weil viele subtile Effekte wie z.B. Reliefsimulation in flirrenden Spiegelungen verschwendete Rechenzeit sind.
Die konkrete Umsetzung der Lichter wird allerdings etwas komplizierter, je nachdem für welche Art von Renderer Du Dich entscheidest. Ich würde heutzutage wahrscheinlich wegen der einfacheren AntiAliasing-Methoden einen Tiled Forward Renderer anpeilen, aber wenn Du "einfach" willst, würde ich einen banalen MultiPass Forward Renderer nehmen und UNBEDINGT sicherstellen, dass ich in der ganzen Szene nie mehr als ein knappes Dutzend Lichtquellen verteile.
Ein "einfacher" Renderer... hm. Halbwegs zukunftssicher würde ich das so aufbauen:
Engine:
- kann "Renderszene" anfangen, gibt ein entsprechendes Objekt zurück
- kann "Renderszene" beenden, nimmt Objekt entgegen und führt es aus
Renderszene:
- wird von Engine verwaltet
- wird initialisiert mit ViewMatrix, ProjectionMatrix, RenderTarget, plus Bonusparameter
- nimmt Lichter entgegen: Position, evtl. Kegelgrenzen für SpotLights, Farbe, evtl. Rotation, evtl. Farbtextur, evtl. Schatten-Textur-Referenzen als Ergebnis einer vorherigen Renderszene
- nimmt DrawCalls entgegen: Mesh, Material, WorldMatrix, SequenzID zum Sortieren untereinander
- macht bei Beenden durch Engine dann Folgendes: DrawCalls sortieren, ausführen
Mesh:
- für's erste ein VertexBuffer und evtl. ein IndexBuffer
Material:
- Shader
- Shader-Parameter
- Shader-Texturen
Ich würde außerdem so eine Art "Kontext"-ID erfinden. Das kann ein simpler Array-Index sein, wenn Du irgendwo vorab in der Engine alle möglichen Kontexte definierst. Im Shader speicherst Du dann pro KontextId einen alternativen Shader, der statt des eigentlichen Shaders eingesetzt wird. Das halte ich für Pflicht, wenn Du zum Beispiel einen Schatten-Pass für eine Lichtquelle machen willst. Es gibt dann einen Kontext "Schatten für Punktlichter" und jeder Shader gibt an, welcher Shader statt seiner selbst die ShadowMap für dieses Material ausrendert. Alle normalen Oberflächenshader verweisen dann auf einen Tiefen-Output, alle AlphaTest-Shader verweisen auf einen Tiefen-Output mit AlphaTest, usw. Darüber kann man auch Shader vereinfachen, wenn man zum Beispiel Spiegelungen ausrendert, weil viele subtile Effekte wie z.B. Reliefsimulation in flirrenden Spiegelungen verschwendete Rechenzeit sind.
Die konkrete Umsetzung der Lichter wird allerdings etwas komplizierter, je nachdem für welche Art von Renderer Du Dich entscheidest. Ich würde heutzutage wahrscheinlich wegen der einfacheren AntiAliasing-Methoden einen Tiled Forward Renderer anpeilen, aber wenn Du "einfach" willst, würde ich einen banalen MultiPass Forward Renderer nehmen und UNBEDINGT sicherstellen, dass ich in der ganzen Szene nie mehr als ein knappes Dutzend Lichtquellen verteile.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Einfache 3D Engine
Eine kleinere 3D Engine baust du am besten, indem du viele kleinere 3D Spiele programmierst...
http://scientificninja.com/blog/write-games-not-engines ;)
http://scientificninja.com/blog/write-games-not-engines ;)
-
- Establishment
- Beiträge: 140
- Registriert: 03.10.2010, 20:14
Re: Einfache 3D Engine
Hi,
danke für die schnellen Antworten.
@Schrompf:
Ok, dann werd ich DX11 nehmen. Bis mein Spiel fertig ist (wenn überhaupt ;)) dauert es ja eh noch lange. Bis dahin sinken die 15% ja sicher noch.
Wenn ich dich richtig verstehe, könnte ich meine 3D Engine fast genauso aufbaun wie meine 2D Engine. Da gabs auch BeginScene, EndScene etc. und dazwischen DrawRectange, DrawLine, DrawText etc.
Das sollte ja auch auf 3D Objekte anwendbar sein. Meine Befürchtung war halt die Performanz gegenüber einem direkten Arbeiten mit DirectX (anstatt den Zwischenschritt über den Renderer). Der Renderer hatte halt den Vorteil, dass man die Engine auch ohne Probleme auf zB OpenGL umstellen konnte, ohne an der Engine selbst was ändern zu müssen.
@dot:
Natürlich ist mein Endziel ein Spiel zu programmieren. ;)
Allerdings möchte ich dafür erstmal eine Engine programmieren um in die 3D Programmierung einzusteigen.
Noch eine Frage zu den Mashes hab ich: Wie funktioniert das mit dem Vertex- und Indexbuffer? Erstellt man für jedes Mesh einen neuen Buffer oder schmeist man alles in Einen rein? Das ständige Lock und Unlock geht ja extrem auf die Resourcen (so zumindest die DX Warnung, wenn man einen Vertextbuffer mehrmals lockt und unlockt.
Gruß
danke für die schnellen Antworten.
@Schrompf:
Ok, dann werd ich DX11 nehmen. Bis mein Spiel fertig ist (wenn überhaupt ;)) dauert es ja eh noch lange. Bis dahin sinken die 15% ja sicher noch.
Wenn ich dich richtig verstehe, könnte ich meine 3D Engine fast genauso aufbaun wie meine 2D Engine. Da gabs auch BeginScene, EndScene etc. und dazwischen DrawRectange, DrawLine, DrawText etc.
Das sollte ja auch auf 3D Objekte anwendbar sein. Meine Befürchtung war halt die Performanz gegenüber einem direkten Arbeiten mit DirectX (anstatt den Zwischenschritt über den Renderer). Der Renderer hatte halt den Vorteil, dass man die Engine auch ohne Probleme auf zB OpenGL umstellen konnte, ohne an der Engine selbst was ändern zu müssen.
@dot:
Natürlich ist mein Endziel ein Spiel zu programmieren. ;)
Allerdings möchte ich dafür erstmal eine Engine programmieren um in die 3D Programmierung einzusteigen.
Noch eine Frage zu den Mashes hab ich: Wie funktioniert das mit dem Vertex- und Indexbuffer? Erstellt man für jedes Mesh einen neuen Buffer oder schmeist man alles in Einen rein? Das ständige Lock und Unlock geht ja extrem auf die Resourcen (so zumindest die DX Warnung, wenn man einen Vertextbuffer mehrmals lockt und unlockt.
Gruß
- Schrompf
- Moderator
- Beiträge: 5149
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: Einfache 3D Engine
Das ist die Grundform, da wird man kaum drumrum kommen. Es ist also klar, dass die alle ähnlich aussehen. Die eigentliche Intelligenz steckt in den Datenzuordnungen und in der Struktur. Die Datenzuordnungen werden Dir noch einiges an Freude machen, die habe ich ja nur grob skizziert und man kann da unglaublich viel gestalten. Und die Struktur... siehe unten.Raven280438 hat geschrieben:Wenn ich dich richtig verstehe, könnte ich meine 3D Engine fast genauso aufbaun wie meine 2D Engine. Da gabs auch BeginScene, EndScene etc. und dazwischen DrawRectange, DrawLine, DrawText etc.
Zum Einen ist eine etwas abstrakte Render-Methodik bei 3D viel notwendiger als bei 2D, weil Du heutzutage üblicherweise viele grundverschiedene Passes machst, ehe Du ein Bild erhälst. Ich wollte eine grundlegende Struktur vorschlagen, so dass Du Shadow Passes, Reflection Maps usw. halbwegs einfach integrieren kannst. Und zum Anderen wirst Du durch einen Renderer einiges an Performance gewinnen, nicht verlieren. Das Sortieren der DrawCalls und die gemeinsame Datenhaltung der States, Meshes, Texturen, Daten bringt Dir üblicherweise einiges an Rendertempo.Das sollte ja auch auf 3D Objekte anwendbar sein. Meine Befürchtung war halt die Performanz gegenüber einem direkten Arbeiten mit DirectX (anstatt den Zwischenschritt über den Renderer).
Urg... Du machst Späße. Wenn Du Linux und Konsorten brauchst, nimm nur OpenGL. Wenn Du nur Windows brauchst, nimm nur DirectX. Alles andere ist meiner Meinung nach eine Übung in akademischem Masturbieren, und ganz nebenbei eine Garantie für Jahre weiterer Pflegearbeit, die Du eigentlich ins Spiel investieren willst.Der Renderer hatte halt den Vorteil, dass man die Engine auch ohne Probleme auf zB OpenGL umstellen konnte, ohne an der Engine selbst was ändern zu müssen.
Zur Erinnerung: Du wolltest eine *einfache* 3D-Engine anfangen. Ich habe Dir (meine) Wege dargelegt, wie man eine einfache Engine bauen könnte, ohne beim ersten Extrawunsch alles wegschmeißen zu müssen. API-Abstrahierung und ähnliche Späße sind weder einfach noch notwendig.
Pro Modell ein VertexBuffer und ein IndexBuffer. Die sind nach dem Laden dann ja üblicherweise statisch, die verändert man gar nicht mehr. Darüberhinaus gibt es dann eine Menge Methoden, Bewegung ins Bild zu bekommen. Die gängigsten Methoden sind Displacement im Shader (für im Wind wiegende Vegetation z.B.), Vertex Skinning (Deformieren eines Meshes anhand eines Skeletts) oder halt dynamisch befüllte VertexBuffer (für Partikel wie Feuer, Rauch, Nebel usw.). Nur letzteres erfordert, dass man einen Buffer nach dem Erstellen nochmal locked. Und dafür sollte man entsprechende Flags bei der Buffererzeugung setzen, so dass der Grafikkartentreiber sich darauf einstellen kann, dass dieser Buffer oft neu befüllt wird. Die DirectX-Doku kann Dir dazu eine Menge erzählen.Noch eine Frage zu den Mashes hab ich: Wie funktioniert das mit dem Vertex- und Indexbuffer? Erstellt man für jedes Mesh einen neuen Buffer oder schmeist man alles in Einen rein? Das ständige Lock und Unlock geht ja extrem auf die Resourcen (so zumindest die DX Warnung, wenn man einen Vertextbuffer mehrmals lockt und unlockt.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
- dot
- Establishment
- Beiträge: 1746
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: Einfache 3D Engine
Und das ist imo genau der falsche Ansatz (take it from someone who tried ;)). Begründung siehe verlinkter Artikel...Raven280438 hat geschrieben:@dot:
Natürlich ist mein Endziel ein Spiel zu programmieren. ;)
Allerdings möchte ich dafür erstmal eine Engine programmieren um in die 3D Programmierung einzusteigen.
Wenn du einfach nur in die 3D Programmierung einsteigen willst, dann brauchst du weder eine Engine noch solltest du gleich ein Spiel schreiben. Fang lieber mit ein paar kleinen Demos an, rotierende Würfel und so...
-
- Establishment
- Beiträge: 140
- Registriert: 03.10.2010, 20:14
Re: Einfache 3D Engine
Hi,
na dann Danke euch beiden für die Hilfe (und Kritik).
Ich werd mir Beides zu Herzen nehmen.
Gruß
na dann Danke euch beiden für die Hilfe (und Kritik).
Ich werd mir Beides zu Herzen nehmen.
Gruß
Re: Einfache 3D Engine
Ich kann mich dot nur anschließen und seine Aussage bekräftigen. Ich habe selber viel Zeit verschwendet Engines zu schreiben, die am Ende doch nicht für meine Spielideen geeignet waren. Schreibe lieber kleine Spielchen angefangen bei nem 3D-Tetris, Breakout oder was auch immer, und arbeite dich langsam vorwärts. Weil kompliziert werden die notwendigen Datenstrukturen (wie das vorhin schon angedeutet wurde) erstens von ganz allein und zweitens wahnsinnig schnell. Quasi kleine Erfolgserlebnisse sammeln statt mit dem berühmt-berüchtigten eigenen MMO anfangen :)
Gruß und viel Erfolg
Gruß und viel Erfolg
Das beste Snake der Welt: www . easysnake . org
Re: Einfache 3D Engine
Man sollte einfach das machen, was einem am meisten Spass macht! Wenn er ne Engine bauen möchte, soll er es probieren.
Und wenn es gleich ein 3D MMORPG werden sollte, noch besser, dann können wir das gemeinsam zocken! :)
Und wenn es gleich ein 3D MMORPG werden sollte, noch besser, dann können wir das gemeinsam zocken! :)
Re: Einfache 3D Engine
Dem kann ich nur zustimmen ;)Zudomon hat geschrieben:Man sollte einfach das machen, was einem am meisten Spass macht! Wenn er ne Engine bauen möchte, soll er es probieren.
Und wenn es gleich ein 3D MMORPG werden sollte, noch besser, dann können wir das gemeinsam zocken! :)
Ich verkaufe diese feinen Lederjacken.