2D Tilemap Rendering

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

vielleicht kann mir jemand weiterhelfen:
Ich plane im Moment den Aufbau meines ersten Spieles. Es geht um das Rendern einer 2D Tilemap (DirectX11)

Soll ich für die gesamte Map einen einzigen VertexBuffer nehmen? Oder für jeden Layer Einen?
Kann ich in jeder Frame die VertexBuffer komplett neu befüllen? (da sich ja ggf. die Texture-Koordinaten ändern können)

Vielleicht kann mir jemand ein paar Tipps geben.


Gruß
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Schrompf »

Render drauflos. Meine Empfehlung: schreibe Dir eine Klasse, die dynamisch Tiles (oder Sprites) entgegennimmt, aus allen Tiles am Ende einen dynamischen VertexBuffer befüllt und den rendert. Das sollte bereits ausreichend schnell sein, um für alles auszureichen, was Du vorhast. Solange Du vermeidest, für jedes Tile einzeln die Textur zu setzen und einen DrawCall abzuschicken, ist alles ok.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

danke für die Antwort.

Neue Frage:
Ich hab Probleme die Projection- und View-Matrix für 2D Rendering zu erstellen. So richtig verstehe ich das Prinzip dahinter nicht.
Irgendwie müsste ich die Projection-Matrix so erstellen, dass Oben-Links "0.0f / 0.0f" ist und Unten-Rechts (z.B.) 2048.0f / 2048.0f.

Und die View-Matrix müsste dass dann je nach Kamera-Position in Bildschirm-Koordinaten umrechnen.

Kann mir da jemand weiterhelfen?


Gruß
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Schrompf »

Warum willst Du eine View und Projection Matrix erstellen? Du brauchst sie doch gar nicht. Schreibe einfach einen Shader, der keine Matrix benutzt. Was Du brauchst, ist eine Konvertierung von:

Code: Alles auswählen

(0,0)     (X,0)

(0,Y)     (X,Y)
zu

Code: Alles auswählen

(-1, 1)  (1, 1)

(-1,-1)  (1,-1)
Mit X und Y als Pixelgröße Deines aktuellen RenderViews. Das ist eine banale Multiplikation und eine Addition. Die kannst Du natürlich auch in eine Matrix gießen, aber Du kannst es auch sein lassen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

da die Map ja größer sein kann aus der Render-View (Scrolling), dachte ich es ist einfacher, wenn es in der "Welt" einen Fixpunkt 0,0 gibt, und je nach Kamera-Position wird der sichtbare Ausschnitt in Bildschirm-Koordinaten umgewandelt.

Wie man merkt hab ich aber keine Ahnung, wie man mit den Matrizen richtig umgeht.
Wie wäre da die beste Herangehensweise?


Gruß
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

kann mir da niemand weiterhelfen?
Wie würden die Profies hier ne 2D Map rendern?


Gruß
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von dot »

Raven280438 hat geschrieben:Wie würden die Profies hier ne 2D Map rendern?
Hängt von vielen Faktoren ab, unter anderem z.B. wie groß die Map ist, ob alle Tiles gleich groß sind, ob es mehrere Layer gibt, ob die Tiles irgendwie sortiert sein müssen, wie dynamisch alles ist... ;)
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

mir gehts im Moment erstmal nur um die Herangehensweise wegen den Matrizen.


Gruß
Benutzeravatar
Chromanoid
Moderator
Beiträge: 4258
Registriert: 16.10.2002, 19:39
Echter Name: Christian Kulenkampff
Wohnort: Lüneburg

Re: 2D Tilemap Rendering

Beitrag von Chromanoid »

Es gibt bestimmt zahlreiche Einführungen im Internet dazu. Vielleicht hilft Dir ja das hier: http://www-lehre.inf.uos.de/~cg/2010/PDF/kap-06.pdf
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

ok danke, werd ich mir angucken.

Aber liege ich mit meiner Annahme
da die Map ja größer sein kann aus der Render-View (Scrolling), dachte ich es ist einfacher, wenn es in der "Welt" einen Fixpunkt 0,0 gibt, und je nach Kamera-Position wird der sichtbare Ausschnitt in Bildschirm-Koordinaten umgewandelt.
richtig (also mit Projection- und View-Matrix), oder gibts da bessere Wege?


Gruß
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Schrompf »

Raven, eine so allgemeine Frage ist schwer zu beantworten. Ich kann Dir gern erzählen, wie ich meine TileMaps rendere, aber das Konzept von Matrizen zu erklären ist mir zu mühsam. Du bist da anscheinend noch Neuling in diesen Themen, daher verweise ich lieber auf Google und die dort zu findenden Tutorials. Eigentlich müsste jedes Tutorial zu 3D-Grafik und auch einige zu 2D-Grafik Matrizen erklären.

Zum Tile Rendering: es kommt sehr darauf an, was Du vorhast. Wenn Du unglaublich große Mengen Tiles zeichnen willst und die alle über mehrere Frames hinweg statisch sind, lohnen sich feste VertexBuffer. Das ist aber eine seltene Ausnahme, behaupte ich mal. Da Du neu in dem Thema bist und das wahrscheinlich alles noch gar nicht abschätzen kannst, erzähle ich mal meinen Standardweg. Betonung auf "mein", da es viele verschiedene Herangehensweisen gibt, die alle ihre Vor- und Nachteile haben. Und Du könntest das alles fertig bekommen, wenn Du eine fertige Lib wie SFML oder SDL benutzen würdest. Wenn Du das aber selber machen möchtest, weil Du daran Spaß hast, dann lies weiter:

Mein Standardweg für 2D-Grafiken basiert auf zwei zentralen Erkenntnissen, die ich Dir auch ans Herz legen möchte:

a) Tiles sind nur 2D-Grafiken. Font Rendering ist auch nur 2D-Grafiken, genauso wie eine GUI zu zeichnen oder sonstwas. Wenn Du einen sauberen Weg für 2D-Grafiken hast, kannst Du in jedem Fall erstmal losrendern und dann für die Spezialfälle Speziallogik schreiben.

b) Du (und nur Du) hast die Wahl, wieviel auf der GPU passieren soll und wieviel auf der CPU. Du kannst in weiten Bereichen frei hin und her schieben, wie Du es magst. Die obige Ansage zu Matrizen ist genauso zu verstehen: Du kannst Matrizen benutzen ODER es im Shader händisch ausrechnen ODER es auch komplett auf der CPU machen. Das ist Deine freie Wahl. Verrenne Dich also nicht allzu sehr in die klassischen 3D-Konzepte mit Projektionsmatrix, Kameramatrix und Modellmatrix.

Also: 2D-Grafiken.

2D-Grafiken zeichnet man allgemein mit 2 Dreiecken, die zusammen ein Rechteck ergeben. Das Zeichnen der Rechtecke würde ich auf jeden Fall der GPU überlassen, aber es gibt selbst dort keine technischen Gründe, die das erzwingen. Du kannst auch gern komplett in Software rendern, wenn Du daran Spaß hast. Es gibt nur heutzutage quasi nix mehr, was man auf der GPU nicht genauso und viel schneller machen könnte. Daher setzte ich im Weiteren mal "GPU" voraus.

Bei 2D-Grafiken im Allgemeinen weißt Du vorab nicht, wieviele Grafiken es werden und mit welchen Parametern sie angezeigt werden sollen (Position, Größe, Rotation, Farbe, usw.). Das alles kann sich jedes Frame ändern. Also bauen wir immer dynamisch unsere Vertexdaten zusammen. Gleichzeitig ist das Rendern am schnellsten, wenn man soviele Dreiecke wie möglich auf einmal zeichnet. Wir sollten also alle zusammengehörigen Grafiken auf einer Textur haben, da wir wären eines DrawCalls keine Textur ändern können. Eine solche Textur, die viele Einzelgrafiken zusammenpfercht, nennt sich Texturatlas. Wir bauen unseren 2D-Grafik-Zeichner also aus folgenden Komponenten:

1) Der Texturatlas
Eine Klasse, die eine Textur mit vielen Einzelgrafiken darauf verwaltet und eine Liste besitzt, wo und wie groß die einzelnen Grafikschnipsel sind. Die Einzelgrafiken zusammenstellen kann ein Texturatlas-Tool aus dem Internet für Dich tun, aber ich kann aus Erfahrung sagen, dass es sehr angenehm ist, wenn die Texturatlas-Klasse das live kann. Bei Splatter sieht der Workflow so aus:

Ist die Definitionen-Datei neuer als der Puffer:
- lade Definitionen-Datei
- füge alle darin gelisteten Grafiken zum Texturatlas hinzu
- speichere den Texturatlas als Binärblob
sonst:
- lade den Texturatlas aus dem Binärblob

Diesen Prozess kann auch ein normales Build-System für Dich abbilden, ich war da mangels Temporärintelligenz etwas arbeitssamer als nötig und habe es in den Startprozess des Spiels eingebaut. Hat den Vorteil, dass mein Grafiker auch damit umgehen konnte.

2) Die RenderQueue
Eine Klasse, die eine Liste von Zeichenaufrufen akkumuliert. Wenn Du irgendwas zeichnen willst, nimmst oder erstellst Du dir eine Instanz davon und füllst Deine Zeichenaufrufe da rein. Ein Zeichenaufruf ist z.B. "Grafik 13, Mittelpunkt der Grafik an Bildschirmpos (765,345), 20° rotiert, mit 0.5f skaliert und rötlicher Färbung". Die Klasse sammelt all diese Aufrufe einfach in einem std::vector.

3) Der Renderer
Eine Klasse, die eine RenderQueue umsetzt. Also auf den Bildschirm bringt. Braucht dazu natürlich die gesammelten Zeichenaufrufe einer RenderQueue und einen Texturatlas, auf den sich die Zeichenaufrufe beziehen. Um seinen Job zu erledigen, braucht der Renderer einen dynamisch befüllbaren VertexBuffer sowie ein Standardset aus Input Declaration (wie auch immer die jetzt unter DX11 heißt), Vertex Shader und Pixel Shader. Ab DX10 würde ich wohl außerdem einen Geometry Shader einsetzen, der das Rechteck live auf der GPU generiert, unter DX9 nehme ich bisher einen minimalen VertexBuffer und IndexBuffer mit einem Dummy-Rechteck drin und nutze Instancing. Das sind aber alles Optimierungsgeschichten, das ist also für die Zukunft. Für den Anfang würde ich Dir folgende Kleinstimplementation empfehlen:

- erstelle in der Klasse einen VertexBuffer, der z.B. 4000 Vertices fassen kann, also 1000 Rechtecke. Erzeuge den mit den passenden Usage Flags, so dass Du ihn schnell mappen und unmappen kannst.
- erstelle einen IndexBuffer mit 6000 Vertices, also 2x drei Indizes pro Rechteck. Der kann statisch sein und vorgefüllt mit allen Indizes.
- erstelle eine Input Assembler Dingens, die erstmal nur einen banalen Vertex mit 2xfloat für Position und 2xfloat für Texturkoordinaten abbildet.
- erstelle einen Vertex Shader, der die als Bildschirmkoordinaten gegebenen Koordinaten in Screen Space Koordinaten umrechnet (siehe Anfang dieses Threads) und die Texturkoords durchreicht
- dazu wird der VS eine Konstante brauchen, wie groß die Auflösung gerade ist
- erstelle einen Pixel Shader, der nur aus der Texturatlas-Textur sampelt und die Farbe zurückgibt.

pro Render-Aufruf:
- ermittle, wieviele Vertizes Du rendern willst. Entweder soviele, wie noch in der Queue sind, oder maximal so viele, wie in die Buffer passen. Im obigen Beispiel also 1000
- mappe den VertexBuffer
- schreibe pro Zeichenaufruf vier Vertizes mit Position in Bildschirmkoordinaten und Texturkoordinaten aus dem Texturatlas
- unmappe den VertexBuffer
- weise Buffer, Input Assembler und Textur zu, setze die VertexShader-Konstante auf aktuelle Bildschirmauflösung
- und rendere

Damit solltest Du schonmal einige zehntausend kleine Einzelgrafiken durch die Gegend fliegen lassen können, ohne unter 100fps zu fallen. Von hier aus kann man jetzt weitermachen und Rotation, Griffpunkt (Mitte oder linke obere Ecke), Farbmodulation, Streckung und Skalierung und wasweißichnoch einbauen. Wenn das einmal läuft, kann man auch zu optimieren anfangen. Z.B. indem man Rotation, Skalierung und alles in den Shader schiebt und im GeometryShader (oder per Instancing) das Rechteck generiert. Dann braucht man pro Zeichenaufruf nur noch einen anstatt vier Vertizes zu schreiben und die moderat teuren Sinus-Berechnungen macht die Graka. Außerdem ersparst Du Dir den IndexBuffer und im GeometryShader-Fall sogar die Instancing-Vorlage.

Wie man mit so allgemeinen 2D-Grafik-Funktionen eine TileMap zeichnet, ist dann was für Teil 2
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Schrompf »

Teil II: die TileMap

Auch hier kann man erstmal ganz doof anfangen und von da aus weiterbauen. Und das würde ich Dir empfehlen, weil Du damit Schritt für Schritt siehst, was es bringt und wo es noch hängt. Bzw. auf heutigen Systemen: wie abartig schnell die heutige Gamer Hardware selbst strunzdummen Code noch ausführen kann.

Also Stufe 1: iteriere über Dein 2D-Array und zeichne jedes Tile. Dein Texturatlas hat alle Tile-Grafiken auf einer Textur gesammelt, der Renderer bringt beliebige Mengen 2D-Grafiken auf den Bildschirm, also los geht's.

Wir beobachten: wir sehen z.B. die linke obere Ecke unserer Map, aber können nicht scrollen. Grmpf.

Also Stufe 2: wir bauen ein Offset ein, also quasi eine kleine Kamera. Wir sagen, dass die Mitte des Bildschirms auf einen bestimmten Punkt der Karte zeigen soll. Also müssen wir alle Zeichenaufrufe um (KameraFokusPunkt minus Bildschirmmitte) verschieben. Den Kamerafokuspunkt schnell mit ein paar Tasten änderbar gemacht und schon können wir scrollen.

(Randempfehlung: diese Offset-Rechnerei würde ich früher oder später in eine kleine Kamera-Klasse auslagern)
(Randempfehlung II: Du kannst diese Offset-Rechnerei auch auf der Grafikkarte im Shader machen, wenn Du sie als Konstante in den Shader reinreichst. Bringt aber nix, behaupte ich.)

Nun ist es ziemliche Verschwendung, alle Tiles zu zeichnen, wenn der Großteil davon eh außerhalb des Bildschirms ist. Aber Kartengrößen von 500 Tiles ins Quadrat dürftest Du das auch deutlich in der Framerate merken.

Also Stufe 3: wir lassen alle Tiles weg, die nicht im Bildschirm sind. Die plumpe Lösung wäre, über jedes Tile drüberzugehen und zu schauen, ob es im Bildschirm ist. Du kennst die Bildschirmauflösung, Du weißt, wo gerade die Kamera steht, und Du kennst die Tile-Größe, also kannst Du vor jedem Tile prüfen, ob es überhaupt den Bildschirm berührt. Und wenn es nicht sichtbar ist, brauchst Du es auch nicht zu zeichnen. Das dürfte schon was bringen.

Aber es ist doch doof, jedes einzelne Tile dafür abfragen zu müssen. Die liegen doch alle regelmäßig nebeneinander. Ich könnte also getrennt nach X und Y einfach einen Zahlenbereich bestimmen, außerhalb von dem definitiv nix sichtbar sein kann.

Also Stufe 4: Wir berechnen anhand der Bildschirmgröße und des aktuellen Kamerafokuspunkts, wo auf der TileMap die linke obere und rechte untere Ecke des Bildschirms liegen. Damit können wir berechnen, von wo bis wo wir überhaupt über unsere TileMap drüber zu iterieren brauchen, weil alles jenseits davon eh unsichtbar ist.

Damit kann die TileMap jetzt so groß werden, wie sie will - wir fassen immer nur den sichtbaren Bereich an und haben damit keine Performance-Probleme selbst bei zehntausenden Tiles in alle Richtungen. Es wär doch aber schön, wenn man ein wenig rauszoomen könnte, um mehr davon auf einmal zu sehen.

Also Stufe 5: Wir bauen einen Faktor ein, den man mit zwei Tasten schnell vergrößern oder verkleinern kann. Damit multiplizieren wir die Koordinaten vor dem Zeichnen. Jetzt müssen wir zwar unsere Bildschirm-Ecken-Berechnung auch mit diesem Faktor bearbeiten und noch ein paar Ecken anderswo anpassen, aber dann können wir zoomen.

Aber wenn wir jetzt rauszoomen, rücken die Tiles zwar näher zusammen, aber werden nicht kleiner und überlappen dabei. Und wenn wir reinzoomen, rücken die Tiles zwar auseinander, aber werden nicht größer und man sieht Lücken dazwischen. Also braucht unser 2D-Renderer von oben eine Skalierungsmöglichkeit.

Den Rest überlasse ich Dir. Spiel damit rum, probiere alles Mögliche aus.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

erstmal vorneweg, SUPER wieviel Zeit du dir nimmst um mir zu helfen, und so einen langen, ausführlichen Text zu schreiben.
Vielen Dank, das hat schon einige (zukünfige) Fragen beantwortet.

Ich hatte vor einigen Jahren schonmal mit DirectX9 angefangen, damals aber komplett ohne Shader.
Im Moment kämpfe ich noch damit, mein erstes Dreieck zu rendern (da ich auch ne kleine Engine drumrum scheibe) ;)
Wenn ich soweit bin, werde ich mich wohl erstmal mit Shadern beschäftigen müssen.

Nochmal Danke für die SEHR ausführliche Antwort.
Mir ist es immer etwas peinlich, dass ich so oft nachfrage, aber ich frag lieber nach, als am Ende zu merken dass irgendwas nicht geht, oder zu langsam ist.

Da mir hier so super geholfen wird, melde ich mich wieder wenn ich Probleme hab ;)


Gruß
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

so da bin ich wieder.
Ich bin im Moment so weit, dass ein farbiges Viereck gerendert wird ;)

Im Moment kämpfe ich mit einem VertexShader, der die Position eines Vertex in der Welt zu einem Punkt auf dem Bildschirm umrechnen soll.

Ich habe mir folgende Herangehensweise überlegt:
Ich übergebe dem Shader die Position der Camera in der Welt (also der Mittelpunkt des Bildschirrms), und die Breite und Höhe des Fensters.
Daraus errechne ich mir den Faktor für Breite und Höhe, wieviel 1.0f in Bildschirm-Koordianten in Welt-Pixeln entspricht.
Daraus kann ich dann errechnen, wie weit das Vertex in der Welt vom Mittelpunkt des Bildschrims entfernt ist.

Leider hab ich keine Ahnung, wie ich das jetzt im Shader umsetzen kann.

Die Input-Position des VertexShaders ist ja vom Typ float4.
Wie kann ich jetzt die X und Y Koordinate der Position mit dem Faktor multiplizieren? Ich hab von Matrizen-Rechnung leider noch garkeine Ahnung.

Hier mein bisheriger VertexShader:

Code: Alles auswählen

cbuffer ShaderInput
{
	float CameraPosX;
	float CameraPosY;
	float ScreenWidth;
	float ScreenHeight;
};

struct VOut
{
	float4 position : SV_POSITION;
	float4 color : COLOR;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
	VOut output;

	//Wieviel Pixel der Welt entsprechen 1.0f auf dem Bildschirm
	float FactorWidth = ScreenWidth / 2;
	float FactorHeight = ScreenHeight / 2;
	
	//Relative Position zum Bildschirm-Mittelpunkt errechnen
	//????
        //output.position.X = (position.x - CameraPosX) / FactorWidth;
        //output.position.Y = (position.y - CameraPosY) / FactorHeight;

 
	output.position = position;
	output.color = color;
 
	return output;
}
Kann mir jemand weiterhelfen?



Gruß
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Schrompf »

Hast Du es denn mal ausprobiert, was Du da hingeschrieben hast? :-) .x und .y müssten klein geschrieben werden, glaube ich, aber abgesehen davon ergibt das sauberen Shadercode. Und natürlich die Tatsache, dass man das auch als Vektor schreiben könnte.

Code: Alles auswählen

output.position.xy = (position.xy - gCameraPos.xy) / gScreenSize.xy;
Und vergiss nicht, dass die finalen Koordinaten der GPU von (-1,-1) bis (+1,+1) gehen. Du müsstest also noch ein "mal zwo minus eins" einbauen. Außerdem ist bei GPU-Bildschirmkoordinaten links unten das (-1,-1) und rechts oben das (1,1), Du musst also vertikal spiegeln. Das steht alles auch in der DirectX-Doku, die ich Dir nur wärmstens ans Herz legen kann.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

ich bins mal wieder.

Im Moment beschäftige ich mich mit Texturierung.
Meine Frage: soll ich die Texture-Koordinaten bei jeder Frame neu berechnen, oder Zwischenspeichern? Zwischenspeichern würde ja weniger Rechenleistung benötigen, aber der Speicherbedarf wird größer.

Und noch eine Frage:
Im Moment habe ich im Renderer ein Array aus Vertices (inkl. Farbe und Texture-Koordinaten etc.). Bei jeder Frame befülle ich das Array neu und am Ende packe ich das komplette Array in den VertexBuffer.

Code: Alles auswählen

D3D11_MAPPED_SUBRESOURCE ms;
this->GetDXContext()->Map(this->DX11VertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
memcpy(ms.pData, &this->pVertexData[0], sizeof(VERTEX) * this->VerticesInBuffer);
this->GetDXContext()->Unmap(this->DX11VertexBuffer, NULL);
Das bedeutet aber auch, dass ich die Vertices doppelt im Speicher habe, oder? Gibt es eine Möglichkeit, den Vertexbuffer Stück für Stück zu befüllen? D.h. am Anfang Mappen, dann Stück für Stück befüllen, und dann Unmappen.


Frohe Weihnachten!


Gruß
Benutzeravatar
Krishty
Establishment
Beiträge: 8240
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Krishty »

Man kann Vertex Buffer Stück für Stück befüllen, ja. Aber
http://zfx.info/viewtopic.php?f=5&t=2797#p35482 hat geschrieben:GPU und CPU laufen asynchron; und während die CPU die Vertices kopiert, kann die GPU den Puffer nicht benutzen. Der Speicher, in den du da kopierst, sieht zwar auch wie ein normaler Zeiger aus, kann aber dank Speichervirtualisierung je nach Treiber was komplett anderes sein – z.B. ein Stück AGP-gekoppelter Speicher, das für Burst Writes (also gradliniges Schreiben großer Datenmengen) optimiert ist. Darum ist man üblicherweise bemüht, das Staging zeitlich so knapp und gradlinig wie möglich zu halten – und memcpy() ist meist hochoptimiert und höchsteffizient.
Die Vertices erst im gemappten Speicher zusammenzubauen wäre deshalb wahrscheinlich kontraproduktiv.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Raven280438
Establishment
Beiträge: 140
Registriert: 03.10.2010, 20:14

Re: 2D Tilemap Rendering

Beitrag von Raven280438 »

Hi,

ok danke. Also lass ich es so wies ist ;)

Wie schauts mit den Texture-Koordinaten aus? Immer neu Berechnen oder zwischenspeichern?
Mangelt es bei Spielen eher an Rechenleistung, oder Speicher?


Gruß
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: 2D Tilemap Rendering

Beitrag von Schrompf »

Probiere es aus :-) Ich könnte dazu heutzutage keine belastbare Aussage mehr treffen, dazu sind mir die CPUs heutzutage viel zu komplex geworden. Im Zweifelsfall würde ich die Variante wählen, jedesmal live zu berechnen, weil ich dadurch ein wenig Verwaltungsaufwand für die zusätzlichem Variablen spare. Und Programmieraufwand ist ja ein ebenso wichtiges Kriterium wie Rechenzeitaufwand.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten