Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

05.08.2012, 11:20

Instancing mit verschiedenen Texturen

Hi

ich möchte eine Minecraft ähnliche Szene rendern.
Also:
Einfache Primitive, aber es gibt sehr viele davon.
Die Primitive sind sehr ähnlich, befinden sich halt an unterschiedlichen Positionen - und! - haben auch unterschiedliche Texturen.
Aus einem anderen Thread hab ich schon gelernt, dass dies am besten mit Instancing gemacht werden soll ;)

Meine (weiteren) Fragen:
1. Wie kann ich Instancing mit unterschiedlichen Texturen verwenden?
Geht das mit entsprechend definiertem Shader/Effects oder brauch ich pro Textur (=Primitvtyp) einen eigenen Indexbuffer mit den Instanzinformationen und hab in meiner Renderschleife dann n jener typischen Aufrufe, die zum Instancing gehören?
(n wäre die Anzahl der verschiedenen Texturen.)
2. Wie lös ich die Dynamik der Szene am besten?
Es sollen nämlich Objekte erstellt und auch gelöscht werden können.
Da die Instanzinformation in einem Indexbuffer steht, möcht ich diesen aber nicht immer bei einer der oben erwähnten Aktionen neu erstellen und befüllen.
Oder geht das nur so?

-ueber-

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

05.08.2012, 11:42

Instancing-Informationen in einem Index-Buffer?! Die sollten in einem Vertex-Buffer sein.
Du könntest zusätzliche Instanzinformationen hinzufügen, die die Textur angeben, und dann im Pixel-Shader die korrekte Textur samplen. Am besten wohl mit einem Textur-Array, wobei du dann den Index in den Instanzinformationen speicherst.
Was die "Dynamik" angeht, da bleibt dir wohl nichts übrig als den Buffer zu verändern, sobald ein neues Objekt hinzukommt oder eins gelöscht wird. Du kannst ihn von Anfang an groß genug machen und dann nur den geänderten Teil neu befüllen. Wenn du ein Objekt löschst, ersetzt du es durch das letzte im Buffer und verringerst die Objektanzahl um 1.

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

3

05.08.2012, 11:45

Moin über,

Du müsstest im einfachsten Fall pro Material/Textur die Instanzen sammeln und getrennt rendern. Die kannst Du natürlich alle in einen VertexBuffer packen und per Offset ansprechen, aber ich würde davon abraten, wenn Du die Instanzen nachträglich ändern willst. Es gibt aber auch bessere Wege:

a) Du könntest mit DirectX10-Hardware und Texture Arrays einfach pro Instanz einen Index mitgeben, welche Textur gemeint ist.
oder b) Wir reden von Minecraft-artiger Grafik? Du brauchst also keine Texturwiederholung pro Fläche und die Texturen sind deutlich kleiner als die GPU erlaubt? Dann schreibe doch einfach alle Texturen (am besten 2x2 wiederholt) auf eine große Textur und gib das Offset pro Instanz an.

Die Dynamik der Szene ist, solange die Prozedur nicht komplett auf der GPU läuft, nur über Abreißen und Neubauen der Instanzenbuffer zu lösen. Irgendwann musst Du die Änderungen in die Grafikkarte hochladen, da führt kein Weg vorbei. Aber da Du (für Sichtbestimmung und sowas) eh die Landschaft in irgendwelche größeren Segmente unterteilen musst, musst Du ja nur den InstanzenBuffer des geänderten Segments neubauen. Und ab dann wird es eine reine Abwägungssache, wie groß Du die Segmente machst. Zu klein und Du hast zwar bequeme Änderungen, aber viele viele DrawCalls und Sichttests, zu groß und Du musst zuviel neu hochladen und die Sichttests werden irgendwann unwirksam.

[edit] Selektives Ändern von Daten auf der Grafikkarte wie von David vorgeschlagen halte ich für eine schlechte Idee, da die GPU separat von der CPU arbeitet und üblicherweise ein bisschen dem Geschehen hinterherhinkt. Folgender Ablauf:

a) Löschen und Neuerstellen
- Die GPU rendert grad Deine Instanzen
- Du löschst den InstanzenBuffer und erstellst ihn neu
- der Treiber merkt das üblicherweise, gibt Dir einen neuen Buffer
- die GPU kann währenddessen noch zu Ende rendern
- im nächsten Frame hast Du Deine Änderungen

b) Selektiv updaten
- die GPU rendert grad Deine Instanzen
- Du sagst DirectX, dass Du was am Buffer ändern willst
- Der Aufruf hängt, bis die GPU mit dem Rendern fertig ist
- dann kriegst Du Zugriff

Das löst vor allem bei GPU-lastigen Programmen merkliche Hänger aus... das hab ich schon erlebt, und ich rate davon ab. Auch wenn heutzutage zumindest die Zocker-Grafikkarten solche Monster sind, dass man sie nur noch als erfahrener GPUler oder als Idiot wirklich auslasten kann. Die GPU hängt nunmal immer etwas hinterher, rein prinzipiell und egal wie schnell sie ist.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

Werbeanzeige