1 / 34

Elemente der 3D-Grafikprogrammierung

Elemente der 3D-Grafikprogrammierung. Render - Pipeline. Aufgabe eines Grafikpakets wie DirectX: mit Grafikkarte eingehende Grafikdaten, Primitive, in Pixel auf dem Bildschirm transformieren Prozess aus mehreren Verarbeitungsschritten: Fixed Function Pipeline: 1.) Vorverarbeitung:

remedy
Download Presentation

Elemente der 3D-Grafikprogrammierung

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Elemente der 3D-Grafikprogrammierung

  2. Render - Pipeline • Aufgabe eines Grafikpakets wie DirectX: mit Grafikkarte eingehende Grafikdaten, Primitive, in Pixel auf dem Bildschirm transformieren • Prozess aus mehreren Verarbeitungsschritten: • Fixed Function Pipeline: 1.) Vorverarbeitung: • Tesselieren: komplexe Geometrieelemente in einfache Geometrieelemente (Grafikprimitive) zerlegen • Um weitere Operationen zu vereinheitlichen • Z.B. Meshes immer aus Dreiecken 2.) Tranformation und Beleuchtung • Geometrische Umrechnung der Eingangsdaten wird durchgeführt • Teilschritte: • World – Transformation • View-Transformation • Perspektivische Transformation

  3. 3.) Clipping: Abschneiden von Teilen, die außerhalb des Blickfeldes liegen • Backface Culling: Entfernen von Rückseiten • Beide Prozesse automatisch, aber Programmierer kann durch Setzen von Render-States eingreifen -> Culling abschalten: auch Rückseiten der Objekte erzeugt 4.) Texturierung • Texturen bzw Bilder werden auf Grafikprimitive aufgebracht • entsprechend Lichtverhältnissen eingefärbt 5.) Ergebnisse zusammenführen • Farbwerte der Pixel für Bildschirmausgabe berechnen • Anhand Tiefen-Information (Z-Buffer) wird entschieden, welche Pixel im Vordergrund liegen • Übereinander liegende Pixel werden verschnitten

  4. Fixed Function Pipeline: geeignet für feste Strukturen • Organische Strukturen wie Gesichter, Pflanzen, Wasser mit Verformungen oder Farbenspiel -> Berechnung aller geometrischen und farblichen Übergänge im Anwendungsprogramm nötig, dann Übergabe an Grafikkarte -> dazu „programmierbare“ Render-Pipeline: • Geometrische und farbliche Transformationen nah an der Hardware durchgeführt • Vertexshader: zur geometrischen Transformation • Pixelshader: zur Texturierung • Shader: kleine Programme, die bei Bedarf in Grafikkarte geladen werden um Vertex- oder Pixelberechnungen durchzuführen • Vorrangig dann, wenn spezielle geometrische pder farbliche Effekte erzielt werden sollen

  5. 7.2 Vertices und Vertexbuffer • Interne Darstellung eines 3D-Modells: Datenstruktur, die performant gerendert werden kann • maximale Geschwindigkeit in Render – Pipeline: am besten Arrays mit Aneinanderreihung von Geometriedaten, die als Ganzes in Grafikkarte geladen und mit einfachen Algorithmen verarbeitet werden können • Verzicht auf Kopien -> es darf nur einen Originaldatensatz geben, auf dem dann sowohl Anwendungsprogramm als auch Grafiksystem arbeiten kann • In DirectX: Vertexbuffer sind auf Verwendung an Schnittstelle zwischen Grafiksystem und Anwendungsprogramm hin optimiert

  6. Vertexbuffer: • reservierter Speicherbereich • Informationen über Knoten (Vertices) eines 3D Modells sind hier abgelegt • Programm kann mehrere Vertexbuffer anlegen und unabhängig voneinander verwenden • in Vertexbuffer steht Aneinanderreihung von Vertices • Vertices: • Eckpunkte oder Knoten eines dreidimensionalen Mesh • Hat Positionsdaten und ggf. weitere Daten über den Knoten wie Farbwerte, Texturkoordinaten • Möglichst performant: schlichte, starre Struktur für Vertex -> einfachste Möglichkeit: immer gleiche Struktur, kann auch enorme Speichervergeudung bedeuten • Daher flexibles Vertex - Format

  7. 7.2.1 Das Flexible Vertex-Format • Flexibles Vertex-Format (FVF): zur Speicherung von Vertices in Vertexbuffer verwendetes Datenformat wird festgelegt • Für jedes Attribut bestimmter Datentyp • Position des Vertex durch Vektor D3DXVECTOR3 beschrieben, • Farbe durch RGBA-Wert D3DCOLOR • Zusätzlich ist verbindliche Reihenfolge der Attribute festgelegt -> Gesamtstruktur mit allen Feldern ist festgelegt, nicht verwendete Felder werden gelöscht

  8. Vertexformat mit Positionsangabe, Normale, diffusem Farbwert: # define MEINVERTEXFORMAT (D3DFVF_XYZ I D3DFVF_NORMAL I D3DFVF_DIFFUSE) struct meinvertex { D3DXVECTOR3 pos; D3DXVECTOR3 normale; D3DCOLOR color; }; • Symbolische Konstante MEINVERTEXFORMAT verwendet man später zur Reservierung von Vertexbuffer • Datenstruktur meinvertex verwendet als Overlay, wenn man von Vertexbuffer schreiben oder lesen will • Deklaration des Vertexformats -> dieses wird später mit Funktion SetFVF dem Device bekannt gegeben • Bei Deklaration von MEINVERTEXFORMAT kommt es nicht auf die Reihenfolge einzelner Flags an • die Reihenfolge der Felder in der Datenstruktur meinvertex muss sich jedoch streng an Reihenfolge der Attribute in der Tabelle orientieren -> bei abweichender Reihenfolge erhält man später falsche Werte durch unpassendes Overlay

  9. Umfassendere Methode zur Definition von Vertexformaten: • Array mit Feldbeschreibungen anlegen D3DVERTEXELEMENT9 • Diesen an Funktion CreateVertexDeclaration übergeben um Vertexdeklaration zu erzeugen • SetVertexDeclaration setzt Deklaration im Device -> Feldbeschreibungen D3DVERTEXELEMENT9 entsprechen in etwa symbolischen Konstanten -> Aufruf von CreateVertexDeclaration entspricht Montage der symbolischen Konstanten durch Oder – Verbindung -> SetVertexDeclaration entspricht Funktion SetFVF -> Vertexdeklaration verwendet man im Zusammenhang mit Vertex- und Pixelshadern, wenn man selbst definierte Formate in der Renderpipeline verwenden will

  10. 7.2.2 Verwendung von Vertexbuffern • Vertexbuffern anlegen für ausgewähltes Vertexformat: Position, Normale, Farbe wird für Vertices benötigt • Vertexbuffer bereitstellen über Memberfunktion CreateVertexBuffer aus Interface des DirectX-Device (IDirect3DDevice9) HRESULT CreateVertexBuffer (UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9 **ppVertexBuffer, HANDLE pHandle) -> Länge des Buffers in Bytes, Verwendungsart, flexibles Vertexformat, Memorypool, aus dem Speicher bereitgestellt wird, Pointer für erzeugten Buffer, reservierter Parameter, muss NULL sein • Als Länge übergibt man Anzahl gewünschter Vertices x Größe der Datenstruktur für einen Vertex, etwa sizeof(meinvertex) • FVF-Parameter sollte zu Vertexstruktur passende Bitmaske, etwa MEINVERTEXFORMAT enthalten • im Parameter ppVertexBuffer erhalten wir Funktionsergebnis, d.h. Vertexbuffer

  11. Konkretes Beispiel für Anforderung eines Buffers für 1000 Vertices LPDIRECT3DVERTEXBUFFER9 vertexbuffer; device->CreateVertexBuffer (1000*sizeof(meinvertex), 0, MEINVERTEXFORMAT, D3DPOOL_MANAGED, &vertexbuffer, NULL); • Device als Zeiger auf zuvor initialisiertes DirectX-Device • Zugriff auf Vertexbuffer über Interface (LPDIRECT3DVERTEXBUFFER9) • Buffer kann in anderem Adressraum als dem unseres Prozesses liegen und damit konkurrierend von anderen Prozessen verwendet werden • Daher mit Funktion Lock für exklusiven Zugriff ganz oder teilweise sperren ->

  12. HRESULT Lock (UINT OffsetToLock, UINT SizeToLock, VOID **ppbData, DWORD Flags) • Offset, ab dem gesperrt wird; Anzahl Bytes, die gesperrt werden; unspezifizierter Zeiger, der nach Aufruf auf den Buffer zeigt; Flags, die Art des gewünschten Locks bestimmen • Bei erfolgreichem Aufruf erhalten wir in ppbData einen Zeiger auf reservierten Vertexbuffer • konkret: meinvertex *pv; vertexbuffer->Lock(0, 0, (void**)&pv, 0); • Wenn SizeToLock auf 0, wird der gesamte Vertexbuffer gesperrt • Nach Funktionsaufruf finden wir in pv einen Zeiger auf Vertexbuffer

  13. Struktur meinvertex dient dann als Overlay zum Lesen/Schreiben in Vertexbuffer for (int i=0; i<1000; i++) { pv[i].pos = D3DXVECTOR3 (1, 1, 1); pv[i].normale = D3DXVECTOR3 (0, 1, 0); pv[i].color = D3DCOLOR_ARGB (255, 255, 255, 0); } • Nach Zugriff Freigabe des Vertexbuffer für andere Prozesse über Funktion Unlock: HRESULT Unlock (VOID) • Freigabe über Aufruf von Release – Funktion: vertexbuffer -> Release();

  14. 7.3 Grafikprimitive7.3.1 Grafikprimitive in DirectX • Grafikprimitive: einfache geometrische Struktur, aus der komplexere Strukturen aufgebaut werden können • DirectX kennt Punkte, Linien, Dreiecke als Primitive -> alle räumlichen Modelle werden in Dreiecke aufgelöst >>Triangulierung<< • Vertexbuffer kann Punktliste, Linienliste, Linienzug, Dreiecksliste, Dreiecksstreifen oder Dreiecksfächer enthalten

  15. Punktliste: D3DPT_POINTLIST • Vertexbuffer enthält einzelne Punkte • Linienliste: D3DPT_LINELIST • Zwei aufeinanderfolgende Vertices werden als Anfangs- bzw Endpunkt einer Linie aufgefasst • Anzahl der Vertices muss größer als 1 und gerade sein • Linienzüge: D3DPT_LINESTRIP • Können ebenfalls im Vertexbuffer modelliert werden • Punkte, Linien, Linienzüge eher selten, wichtiger sind Dreiecke -> flexibelste Form dazu Dreiecksliste D3DPT_TRIANGLELIST • Je drei aufeinanderfolgende Vertices bilden Dreieck • Dreiecke haben Vorder- und Rückseite -> nur Vorderseite wird gerendert • Vorderseite: Windungsrichtung der im Vertexbuffer aufeinanderfolgenden Eckpunkte verläuft im Uhrzeigersinn • Ausblenden der Rückseite: Backface - Culling

  16. Culling stellt man mit Funktion SetRenderState um device->SetRenderState ( D3DRS_CULLMODE, D3DCULLL_CCW); • Im obigen Beispiel wird Culling so eingestellt, dass Rückseiten, deren Windungsrichtung gegen Uhrzeigersinn (CCW) verläuft, nicht dargestellt werden • Anzahl zur Beschreibung geometrischer Strukturen verwendete Vertices verringern: • Dreiecksstreifen (D3DPT_TRIANGLESTRIP) • Erste drei Vertices bilden Dreick, jeder weitere Vertex bildet mit seinen zwei Vorgängern das nächste Dreieck • Wenn Backface-Culling aktiviert: erstes Dreieck im eingestellten Cullingmode gerendert, bei jedem weiteren Dreieck wird Wichtungsrichtung umgekehrt • Dreiecksfächer (D3DPT_TRIANGLEFAN): drei erste Vertices ein Dreieck, jeder weitere Vertex mit Vorgänger und erstem Vertex • Culling für alle Dreiecke gleich

  17. 7.3.2 Rendern von Primitiven • Vertex-Format festlegen -> Vertexbuffer allokieren -> Vertexbuffer mit Primitiven füllen -> rendern • Vertexbuffer als Eingabequelle der Render-Pipeline unseres Devices festlegen: mit Funktion SetStreamSource HRESULT SetStreamSource (UINT StreamNumber, IDirect3DVertexBuffer9 *pStreamData, UINT OffsetInBytes, UINT Stride) • Nummer des Streams, Vertexbuffer als Quelle, Offset zum Startpunkt im Vertexbuffer, Größe des Datensatzes für einen Vertex in Bytes • StreamNumber ist logische Nummer -> mehrere Vertexbuffer als Streamsource festlegen, sofern man jedes Mal eine andere Nummer wählt • Beispiel: device->SetStreamSource (0, vertexbuffer, 0, sizeof(meinvertex));

  18. Device mitteilen, welches Vertexformat man im Vertexbuffer verwendet: HRESULT SetFVF (DWORD FVF) -> flexibles Vertex – Format • Als Parameter definiertes Vertexformat übergeben • Beispiel: device-> SetFVF(MEINVERTEXFORMAT); • Funktion DrawPrimitive rendert Vertexbuffer HRESULT DrawPrimitive (D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) • Art der Primitive, Startindex im Vertexbuffer, Anzahl der zu rendernden Primitiven • idR kompletten Vertexbuffer rendern und Startindex auf 0 setzen, aber auch andere Startpunkte sind möglich • Beispiel: Ab dem 10ten Vertex im Buffer 100 Dreiecke rendern: device->DrawPrimitive (D3DPT_TRIANGLELIST, 10, 100);

  19. 7.3.3 Beispiele mit Dreiecken und Linien • Schritt: Festlegen des Vertexformats • Für jeden Vertex Position und Farbwert im Vertexbuffer speichern # define MEINVERTEXFORMAT (D3DFVF_XYZ I D3DFVF_DIFFUSE) struct meinvertex { D3DXVECTOR3 pos; D3DCOLOR color; }; • Liste von Dreiecken mit Umrandung erstellen • Dazu Dreiecksliste und Linienliste rendern • Voraussetzung: Device (LPDIRECT3DDEVICE9) wurde erfolgreich initialisiert • Funktionalität zum Erstellen und rendern konzipieren wir als eine in sich geschlossene Klasse (trianglelist), in die von außen nur ein Zeiger auf Device eingeht

  20. class trianglelist { private: LPDIRECT3DDEVICE9 device; LPDIRECT3DVERTEXBUFFER9 dreieckbuffer; LPDIRECT3DVERTEXBUFFER9 linienbuffer; public: trianglelist(); ~trianglelist(); void create(LPDIRECT3DDEVICE9 dev); void setup(); void render(); }; • Zwei Vertexbuffer: der erste (dreieckbuffer) soll Eckpunkte der Dreiecke, der zweite (linienbuffer) Eckpunkte der Umrandung aufnehmen • Fehlende Arbeitsschritte werden in öffentlichen Methoden create, setup, render abgehandelt

  21. Konstruktor und Destruktor der Klasse: trianglelist::trianglelist() { dreieckbuffer = 0; linienbuffer = 0; } trianglelist::~trianglelist() { if (dreieckbuffer) dreieckbuffer -> Release(); if (linienbuffer) linienbuffer-> Release(); } • Konstruktor initialisiert Bufferzeiger • Destruktor gibt Buffer frei

  22. 2. Schritt: Allokieren des Vertexbuffers • Zwei Vertexbuffer: erste soll 2 Dreiecke = 6 Vertices aufnehmen, zweite soll 6 Randlinien = 12 Vertices aufnehmen • Daraus ergibt sich erforderlicher Speicherplatz void trianglelist::create (LPDIRECT3DDEVICE9 dev) { device = dev; device -> CreateVertexBuffer (6*sizeof(meinvertex),0, MEINVERTEXFORMAT, D3DPOOL_MANAGED, &dreieckbuffer, NULL); device->CreateVertexBuffer (12*sizeof(meinvertex),0, MEINVERTEXFORMAT, D3DPOOL_MANAGED, &linienbuffer, NULL); } - System legt beide Buffer an, kein direkter Zugriff -> bei Zugriff auf Inhalt zuvor Funktion Lock aufrufen

  23. 3. Schritt: Befüllen des Vertexbuffers • Zunächst beide Vertexbuffer für Zugriff durch unser Programm reservieren void trianglelist::setup() { meinvertex *dv, *lv; int i; dreieckbuffer -> Lock (0, 0, (void**)&dv, 0); linienbuffer ->Lock(0,0, (void**)&lv, 0); /* Zeiger auf jeweilige Bufferinhalte werden in Variablen dv und lv übertragen */ dv[o].pos = D3DXVECTOR3 (0, 0, 0); dv[1].pos = D3DXVECTOR3 (2, 1, 0); dv[2].pos = D3DXVECTOR3 (2, 0, 0); // … bis dv[5] /* Koordinatenwerte für sechs Eckpunkte der beiden Dreiecke eintragen dv[0] bis dv[5] in Dreiecks- bzw Linienpuffer */

  24. dv[0].color = D3DCOLOR_ARGB (255, 80, 80, 80); dv[1].color = D3DCOLOR_ARGB (255, 160, 160, 160); // .. Bis dv[5] /* für Eckpunkte der Dreiecke unterschiedliche Farbwerte */ lv[0].pos = dv[0].pos; // 12 Eckpunkte der 6 Randlinien lv[1].pos = dv[1].pos; lv[2].pos = dv[1].pos; lv[3].pos = dv[2].pos; lv[4].pos = dv[2].pos; lv[5].pos = dv[0].pos; lv[6].pos = dv[3].pos; lv[7].pos = dv[4].pos; lv[8].pos = dv[4].pos; lv[9].pos = dv[5].pos; lv[10].pos = dv[5].pos; lv[11].pos = dv[3].pos;

  25. for (i = 0; i<12; i++) lv[i].color=D3DCOLOR_ARGB(255, 0, 0, 0); // Eckpunkte der Randlinien schwarz dreieckbuffer->Unlock(); linienbuffer->Unlock(); } // Vertexbuffer freigeben - Beide Buffer sind jetzt bereit zum rendern

  26. 4. Schritt: Rendern der Primitiven im Vertexbuffer • Rendern besteht aus wenigen Funktionsaufrufen • Zunächst mit Funktion SetFVF richtiges Vertexformat setzen • Danach für jeden Buffer Funktionen SetStreamSource und DrawPrimitive aufrufen void trianglelist::render() { device->SetRenderState (D3DRS_AMBIENT, 0xffffff); // Beleuchtung: Ambient Licht einschalten device->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); // Farbwerte aus diffusen Farbkomponente des Vertex verwenden device ->SetFVF (MEINVERTEXFORMAT); device->SetStreamSource (0, dreieckbuffer, 0 sizeof(meinvertex)); device->DrawPrimitive (D3DPT_TRIANGLELIST, 0, 2); devide->SetStreamSource(0, linienbuffer, 0 sizeof(meinvertex)); device->DrawPrimitive(D3DPT_LINELIST, 0, 6); } • Aufruf der Methoden create und setup sowie regelmäßiges Rendern ergibt gewünschtes Bild

  27. Unterschiedliche Farbtöne an den Ecken der Dreiecke führen zu Farbverläufen • Ecken dv[2] und dv[3] haben gleiche Position, unterscheiden sich aber in Farbe -> da Vertices zu unterschiedlichen Dreiecken gehören, hätten wir auf keines von beiden verzichten können • Wenn alle Dreiecke in der gleichen Farbe und ohne Farbverläufe dargestellt werden sollen, wäre Farbinfo für jeden Vertex Speicherplatzvergeudung • Stattdessen Material in gewünschter Farbe anlegen: D3DMATERIAL9 material; ZeroMemory (&material, sizeof (material)); Material.Ambient = D3DXCOLOR (255, 255, 0, 0); • Material in render-Funktion auswählen und durch SetRenderState festlegen, dass Material verwendet werden soll: device->SetMaterial (&material); device->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL);

  28. 7.3.4 Beispiel mit Punktlisten (Partikelsysteme) • Dreiecke oder Linien als am häufigsten genutzte Primitive • Punktlisten zur Realisation von Partikelsystemen = 3-dimensionale Punktwolken um etwa Rauch oder Schnee zu implementieren • verwenden gleiches Vertexformat wie zuvor define MEINVERTEXFORMAT (D3DFVF_XYZ I D3DFVF_DIFFUSE) struct meinvertex { D3DXVECTOR3 pos; D3DCOLOR color; };

  29. Jeder Punkt /Partikel hat eigene Position, kann eigenständig bewegt werden, hat eigene Farbe • Beispiel: Kugeloberfläche als Wolke aus einzelnen Punkten zusammensetzen -> größer werden lassen - > zerstäuben class partikelsystem { private: LPDIRECT3DDEVICE9 device; LPDIRECT3DVERTEXBUFFER9 partikelbuffer; int anzahl; float radius; public: partikelsystem (); ~partikelsystem(); void create( LPDIRECT3DDEVICE9 dev, int anz); void setup(); void blowup(); void render (); void lookatme (…} };

  30. Create – Methode: void partikelsystem::create(LPDIRECT3DDEVICE9 dev, int anz) { device = dev; anzahl = anz; device ->CreateVertexBuffer (anzahl*sizeof(meinvertex), 0, MEINVERTEXFORMAT, D3DPOOL_MANAGED, &partikelbuffer, NULL); } • Anwender kann wählen, wie viele Partikel er haben will ->entsprechend wird Vertexbuffer bereit gestellt

  31. Setup – Funktion: Anfangspositionen einzelner Partikel in Buffer eingetragen void partikelsystem::setup() { int i; meinvertex *pv; srand (123); radius = 0.1f; partikelbuffer->Lock (0, 0, (void**)&pv, 0); for (i=0;i < anzahl; i++) { pv[i].pos.x = ((float)rand())/RAND_MAX – 0.5f; // für jedes Partikel durch Zufalls- pv[i].pos.y = ((float)rand())/RAND_MAX – 0.5f; // Zufallskoordinaten ein // Punkt in Würfel pv[i].pos.z = ((float)rand())/RAND_MAX – 0.5f; // um den Ursprung bestimmt D3DXVec3Normalize (&pv[i].pos, &pv[i].pos); // Normalisierung des Punktes pv[i].color = D3DCOLOR_ARGB (255, (int) (128*(pv[i].pos.x +1)), (int) (128*(pv[i].pos.y +1)), (int) (128*(pv[i].pos.z +1))); // Auswahl eines Farbwertes für Partikel pv[i].pos = radius * pv[i].pos; // Sphäre auf Anfangsgröße verkleinern } partikelbuffer -> Unlock(); }

  32. Funktion blowup: Aufblasen der Sphäre, bei jedem Aufruf um 10% bis Maximalwert des Radius 10 • Radius 10 erreicht -> Funktion setup setzt Sphäre in Ausgangszustand void partikelsystem::blowup() { int i; meinvertex *pv; radius *= 1.1f; if (radius <10) { partikelbuffer ->Lock (0, 0, (void**)&pv, 0); for (i = 0; i < anzahl; i++) pv[i].pos = 1.1f * pv[i].pos; partikelbuffer->Unlock(); } else setup (); }

  33. Render – Funktion nimmt Beleuchtungseinstellungen vor und bringt Vertexbuffer zur Darstellung void partikelsystem::render () { device->SetRenderState (D3DRS_AMBIENT, 0xffffff); device->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); device->SetFVF (MEINVERTEXFORMAT); device ->SetStreamSource (0, partikelbuffer, 0, sizeof (meinvertex)); device -> DrawPrimitive (D3DPT_POINTLIST, 0, anzahl); } • Effekt des Zerbröselns: die dem Auge näher liegenden Partikel größer und weiter entfernt liegende Partikel kleiner -> Pointscaling D3DRS_POINTSCALEENABLE aktivieren

  34. Skalierung für Partikel einschalten und Konstanten A, B und C setzen: inline DWORD FtoDW (FLOAT f) { return *((DWORD*) &f);} void partikelsystem::render () { device ->SetRenderState (D3DRS_POINTSCALEENABLE, TRUE); device ->SetRenderState (D3DRS_POINTSIZE, FtoDW(0.1f)); device->SetRenderState (D3DRS_POINTSCALE_A, FtoDW (0.0f)); device->SetRenderState (D3DRS_POINTSCALE_B, FtoDW (0.0f)); device ->SetRenderState (D3DRS_POINTSCALE_C, FtoDW (1.00f)); device ->SetRenderState (D3DRS_AMBIENT, 0xffffff); device ->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1); device ->SetFVF (MEINVERTEXFORMAT); device ->SetStreamSource (0, partikelbuffer, 0, sizeof (meinvertex)); device -> DrawPrimitive (D3DPT_POINTLIST, 0, anzahl); } • Beim Setzen der Konstanten - Hilfsfunktion FtoDW: Funktion SetRenderState akzeptiert nur DWORD, aber eine Gleitkommazahl übergeben -> kopiert float in Speicherbereich, der für DWORD vorgesehen ist

More Related