elemente der 3d- grafikprogrammierung. render - pipeline aufgabe eines grafikpakets wie directx: mit...
Post on 05-Apr-2015
104 Views
Preview:
TRANSCRIPT
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:- Tesselieren: komplexe Geometrieelemente in einfache
Geometrieelemente (Grafikprimitive) zerlegen - Um weitere Operationen zu vereinheitlichen- Z.B. Meshes immer aus Dreiecken2.) Tranformation und Beleuchtung- Geometrische Umrechnung der Eingangsdaten wird durchgeführt- Teilschritte:
- World – Transformation- View-Transformation- Perspektivische Transformation
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ärbt5.) 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
• 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
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
• 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.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
• 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
• 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
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
• 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 ->
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
- 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();
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
• 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
• Culling stellt man mit Funktion SetRenderState umdevice->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
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 SetStreamSourceHRESULT 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));
- 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 VertexbufferHRESULT 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);
7.3.3 Beispiele mit Dreiecken und Linien
1. 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
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
• 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
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
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 */
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 Randlinienlv[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;
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
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 aufrufenvoid trianglelist::render(){device->SetRenderState (D3DRS_AMBIENT, 0xffffff);// Beleuchtung: Ambient Licht einschaltendevice->SetRenderState (D3DRS_AMBIENTMATERIALSOURCE,
D3DMCS_COLOR1);// Farbwerte aus diffusen Farbkomponente des Vertex verwendendevice ->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
• 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);
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;};
• 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 (…}};
• 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
• Setup – Funktion: Anfangspositionen einzelner Partikel in Buffer eingetragenvoid 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ürfelpv[i].pos.z = ((float)rand())/RAND_MAX – 0.5f; // um den Ursprung bestimmtD3DXVec3Normalize (&pv[i].pos, &pv[i].pos); // Normalisierung des Punktespv[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 Partikelpv[i].pos = radius * pv[i].pos; // Sphäre auf Anfangsgröße verkleinern}partikelbuffer -> Unlock();}
• 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();}elsesetup ();}
• 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
• 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
top related