AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Direct3D - Kapselung der Routinen
Thema durchsuchen
Ansicht
Themen-Optionen

Direct3D - Kapselung der Routinen

Ein Thema von Vitus · begonnen am 16. Feb 2004 · letzter Beitrag vom 21. Feb 2004
Antwort Antwort
Vitus

Registriert seit: 24. Apr 2003
Ort: Auckland, Neuseeland
38 Beiträge
 
Delphi XE2 Professional
 
#1

Direct3D - Kapselung der Routinen

  Alt 16. Feb 2004, 12:32
Hallo liebe Delphi Tüftler,

seit einigen Tagen beschäftige ich mich mit der DirectX Programmierung unter Delphi. Ich nutze dazu die übersetzten Header Dateien von ATD.

Ich sehe mich inzwischen in der Lage D3D zu initialisieren, eine Oberfläche zu erzeugen, Einfluss auf Auflösung, Graphic Adapter und D3DMode zu nehmen, ich kann Geometrien erzeugen und diese im Raum verschieben...

Meine Frage ist nun eine ganz grundsätzliche: Wie kapsel ich die einzelnen Routinen?! Also, an welcher Stelle stehen die einzelnen Prozeduren und Funktionen - und vorallem: wie verquicke ich diese mit meinem D3DInterface Objekt?

Bei den Beispielen die ich gefunden habe wird ja irgendwie immer nur mit einer unit Datei gearbeitet und die Methodenaufrufe erfolgen stets sehr statisch - in der Praxis bringt mir das also recht wenig...


Ich wäre froh wenn mir jemand meine Frage beantworten kann

Gruß
Vitus
  Mit Zitat antworten Zitat
Vitus

Registriert seit: 24. Apr 2003
Ort: Auckland, Neuseeland
38 Beiträge
 
Delphi XE2 Professional
 
#2

Re: Direct3D - Kapselung der Routinen

  Alt 17. Feb 2004, 19:20
Nachdem mir bei meinem Problem bisher noch niemand helfen konnte hab ich mich mal alleine auf den steinigen Pfad begeben und angefangen ein paar Klassen zu schreiben. Und siehe da: ich stehe vor weiteren Problemen!

Ich habe jetzt eine Klasse Tlts2DObject mit folgender Deklaration:
Delphi-Quellcode:
type
Tlts2DObject = class(TObject)
  private
    D3DVertex: array [0..5] of TMyVertex;
    D3DTexture: IDIRECT3DTEXTURE9;
    DebugSchritt: Integer;
  public
    Left: Integer;
    Top: Integer;
    Width: Integer;
    Height: Integer;
    Layer: Integer;
    Color: dword;
    Angle: Real;
    Alpha: Integer;
    Graphic: String;
    procedure render(pD3DVertexBuffer: pIDirect3DVertexBuffer9;
                                pD3DDevice: pIDirect3DDevice9);
    procedure updateGeom();
    procedure DebugMsg(Text: String);
end;
Dabei sind pIDirect3DVertexBuffer9 und pIDirect3DDevice9 folgendermassen definiert:

Delphi-Quellcode:
type pIDirect3DDevice9 = ^IDirect3DDevice9;

type pIDirect3DVertexBuffer9 = ^IDirect3DVertexBuffer9;
Die Render Methode (der Übeltäter und Nagel zu meinem Sarg) sieht folgendermassen aus:
Delphi-Quellcode:
procedure Tlts2DObject.render(pD3DVertexBuffer: IDirect3DVertexBuffer9;
                                pD3DDevice: IDirect3DDevice9);
var
  vbVertices : pByte;
begin
   UpdateGeom(); //Anmerkung: hier wird die Geometrie des Objekts errechnet

 pD3DDevice^.SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1); //hier crash => Zugriff auf das Device per Pointer nicht möglich
  pD3DDevice^.SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_CONSTANT, D3DTEXF_LINEAR);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_CONSTANT, D3DTEXF_LINEAR);

  D3DXCreateTextureFromFile(pD3DDevice^,pchar(Graphic),D3DTexture);

   if Alpha <> 255 then
      pD3DDevice^.SetRenderState( D3DRS_ALPHABLENDENABLE, 1 )
   else
      pD3DDevice^.SetRenderState( D3DRS_ALPHABLENDENABLE, 0 );

  pD3DDevice^.CreateVertexBuffer (sizeof(TMyVertex), D3DUSAGE_WRITEONLY,
                            D3D9T_CUSTOMVERTEX, D3DPOOL_MANAGED,
                            pD3DVertexBuffer^, nil);

   pD3DVertexBuffer^.Lock(0,0,pointer(vbVertices),D3DLOCK_NOOVERWRITE);
  Move(D3DVertex,vbVertices^,SizeOf(TltsSprite));
  pD3DVertexBuffer^.Unlock;

   pD3DDevice^.SetTexture( 0, D3DTexture );

  pD3DDevice^.SetFVF(D3D9T_CUSTOMVERTEX);

  pD3DDevice^.SetStreamSource(0,pD3DVertexBuffer^,0,sizeof(TMyVertex));

   pD3DDevice^.DrawPrimitive( D3DPT_TRIANGLELIST,0,2 );

end;
Ich lege nun von meinem Hauptprogramm aus ein neues Objekt vom Typ Tlts2DObject an:

Delphi-Quellcode:
  newWindowObject := Tlts2DObject.Create();
  newWindowObject.Width := frmMain.getResolution.Width;
  newWindowObject.Height := frmMain.getResolution.Height;
  newWindowObject.Left := 0;
  newWindowObject.Top := 0;
  newWindowObject.Layer := 1;
  newWindowObject.Color := $8000FF;
  newWindowObject.Angle := 0;
  newWindowObject.Alpha := 130;
  newWindowObject.Graphic := 'media\menumain.bmp';
Desweiteren initialisiere ich in meinem Hauptprogramm das Direct3DDevice mit allem drum und dran.

In meinem Hauptprogramm wird ausserdem die Szene begonnen und beendet (Damit meine ich BeginScene und EndScene). Dazwischen jedoch soll die render Methode meines neuen Objekts newWindowObject aufgerufen werden und genau da liegt das Problem!

Delphi-Quellcode:
  if assigned(D3DDevice) then
  begin
    D3DDevice.Clear(0,nil,D3DCLEAR_TARGET,D3DCOLOR_XRGB(100,100,100),1,0);

    if SUCCEEDED(D3DDevice.BeginScene) then
    begin
    //VertexListe erweitern
      SetLength(vblist, length(vblist)+1);
      newWindowObject.render(Pointer(vblist[0]),Pointer(D3DDevice));
      D3DDevice.EndScene;
    end;

   // Zeige Resultate auf dem Bildschirm
    D3DDevice.Present(nil,nil,0,nil);
  end;
end;
Beim Sprung in die render Methode des Objekts kommt eine Exception sobald ich das D3DDevice auch nur anfasse - die Zeile habe ich oben markiert.


Ich habe bisher noch nie wirklich mit Zeigern unter Delphi gearbeitet, ich kann mir vorstellen dass einem versierten Pointer-Nutzer der Fehler sofort auffällt - ich für meinen Teil bin wirklich ratlos.


jaaaaa! Gebt es mir

Lieber Gruß
Vitus
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#3

Re: Direct3D - Kapselung der Routinen

  Alt 19. Feb 2004, 14:44
Welchen Typ hat D3DDevice in deinem Hauptprogramm?
Warum castest du D3DDevice in einen Pointer, bevor du es der Render-Methode übergibst?

Ein D3DDevice kann man doch nur als Zeiger (oder als Zeiger auf einen Zeiger) haben, das liegt ja in der Natur von COM. Möglicherweise macht Delphi hier etwas anders als ich es gewohnt bin
Vielleicht anstelle des Casts einfach mal den Adressoperator benutzen (also @D3DDevice an die Render-Methode übergeben)?
Überprüfe doch einfach mal im Debugger, ob der richtige Zeiger in der Render-Methode angekommen ist, wenn nein, ist hier tatsächlich der Fehler zu suchen. Anders gefragt, muss man COM-Objekte in Delphi eigentlich überhaupt explizit als Zeiger übergeben?
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
Vitus

Registriert seit: 24. Apr 2003
Ort: Auckland, Neuseeland
38 Beiträge
 
Delphi XE2 Professional
 
#4

Re: Direct3D - Kapselung der Routinen

  Alt 19. Feb 2004, 15:53
Danke für die Antwort, ich hatte schon vermutet dass mich hier keiner mag und deshalb keiner antwortet *fg*


Inzwischen bin ich nach vieeeeeeeeeeeeeeelen Testläufen endlich mal zu einem Ergebnis gekommen - das Programm ist nun auch etwas anders strukturiert. Damit das hier mal up-to-date ist mal den Code für die neue Tlts2DObject Klasse.


Erstmal die Definitionen:
Delphi-Quellcode:
type

pIDIRECT3D9 = ^IDIRECT3D9;

pIDirect3DDevice9 = ^IDirect3DDevice9;

pIDirect3DVertexBuffer9 = ^IDirect3DVertexBuffer9;

pIDIRECT3DTEXTURE9 = ^IDIRECT3DTEXTURE9;

////////////////////////////////////////////////////////////////////////////////
// Vertexstruktur //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

TMyVertex = Record
  x,y,z : single; // Position des Vertex
  color : dword; // Farbe des Vertex
  tu,tv : single; // Die Koordinaten der Textur
end;

TltsSprite = array [0..5] of TMyVertex;

////////////////////////////////////////////////////////////////////////////////
// 2D Objekt: Grundgerüst für Dialogelemente uä. ///////////////////////////////
////////////////////////////////////////////////////////////////////////////////

Tlts2DObject = class(TObject)
  private
    D3DVertexBuffer: IDirect3DVertexBuffer9;
    D3DTexture: IDIRECT3DTEXTURE9;
    D3DVertex: TltsSprite;
  public
    Left: Real;
    Top: Real;
    Width: Real;
    Height: Real;

    Layer: Integer;

    Angle: Real;

    tuleft: Real;
    turight: Real;
    tvtop: Real;
    tvbottom: Real;

    Color: dword;
    Alpha: Integer;

    Graphic: String;

    constructor Create();
    procedure init(pD3DDevice: pIDirect3DDevice9);
    procedure render(pD3DDevice: pIDirect3DDevice9);
    procedure updateGeom(); virtual;
    procedure updateTexPos(tuleft,turight,tvtop,tvbottom: Real);
    function getVertexBuffer(): pIDirect3DVertexBuffer9;
    function getTexture(): pIDIRECT3DTEXTURE9;
end;
Implementation:
Delphi-Quellcode:
implementation

////////////////////////////////////////////////////////////////////////////////
// Routinen Tlts2DObject ///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

constructor Tlts2DObject.Create();
begin
  inherited Create();
  tuleft := 0;
  turight := 1;
  tvtop := 0;
  tvbottom := 1;
end;

function Tlts2DObject.getTexture(): pIDIRECT3DTEXTURE9;
begin
  result := @D3DTexture;
end;

function Tlts2DObject.getVertexBuffer(): pIDirect3DVertexBuffer9;
begin
  result := @D3DVertexBuffer;
end;

procedure Tlts2DObject.init(pD3DDevice: pIDirect3DDevice9);
var
  vbVertices : pByte;
begin

  updateGeom();
  updateTexPos(tuleft,turight,tvtop,tvbottom);

  pD3DDevice^.CreateVertexBuffer (sizeof(TltsSprite), D3DUSAGE_WRITEONLY,
                            D3D9T_CUSTOMVERTEX, D3DPOOL_MANAGED,
                            D3DVertexBuffer, nil);

  D3DVertexBuffer.Lock(0,0,pointer(vbVertices),0);
  Move(D3DVertex,vbVertices^,SizeOf(TltsSprite));
  D3DVertexBuffer.Unlock;

  pD3DDevice^.SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW); //alle Seiten anzeigen
  pD3DDevice^.SetRenderState(D3DRS_LIGHTING,0);
  pD3DDevice^.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); //Z Buffer abgeschaltet

  pD3DDevice^.SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_CONSTANT, D3DTEXF_LINEAR);
  pD3DDevice^.SetTextureStageState(0,D3DTSS_CONSTANT, D3DTEXF_LINEAR);

  D3DXCreateTextureFromFile(pD3DDevice^,pchar(Graphic),D3DTexture);
end;

procedure Tlts2DObject.render(pD3DDevice: pIDirect3DDevice9);
begin
  pD3DDevice^.SetTexture( 0, D3DTexture );
  pD3DDevice^.SetStreamSource(0,D3DVertexBuffer,0,sizeof(TMyVertex));
  pD3DDevice^.DrawPrimitive( D3DPT_TRIANGLELIST,0,2 );
end;

procedure Tlts2DObject.updateTexPos(tuleft,turight,tvtop,tvbottom: Real);
var
  i: Integer;
begin
  for i := 0 to 5 do
  begin
    if i = 0 then
    begin
      D3DVertex[i].tu := tuleft;
      D3DVertex[i].tv := tvbottom;
    end;
    if i = 1 then
    begin
      D3DVertex[i].tu := tuleft;
      D3DVertex[i].tv := tvtop;
    end;
    if i = 2 then
    begin
      D3DVertex[i].tu := turight;
      D3DVertex[i].tv := tvtop;
    end;
    if i = 3 then
    begin
      D3DVertex[i].tu := turight;
      D3DVertex[i].tv := tvtop;
    end;
    if i = 4 then
    begin
      D3DVertex[i].tu := turight;
      D3DVertex[i].tv := tvbottom;
    end;
    if i = 5 then
    begin
      D3DVertex[i].tu := tuleft;
      D3DVertex[i].tv := tvbottom;
    end;
  end;
end;

procedure Tlts2DObject.updateGeom();
var
  x,y: Real;
  i: Integer;
begin

   for i:=0 to 5 do
  begin
    if i = 0 then
    begin
      x := left;
         y := top;
    end
    else if i = 1 then
    begin
        x := left;
        y := top+height;
    end
    else if i = 2 then
    begin
         x := left+width;
         y := top+height;
    end
    else if i = 3 then
    begin
         x := left+width;
         y := top+height;
    end
    else if i = 4 then
    begin
         x := left+width;
         y := top;
    end
    else
    begin
        x := left;
        y := top;
    end;

      D3DVertex[i].x := x;
      D3DVertex[i].y := y;
    D3DVertex[i].z := (layer*(-1))/100;
      D3DVertex[i].color := Color;
  end;
end;
Nach der Initialisierung des D3DDevice (um die Frage zu beantworten: D3DDevice ist nat. vom Typ IDirect3DDevice9) wird das neue 2D Objekt so initialisiert:

Delphi-Quellcode:
var
  D2DObjekt: Tlts2DObject;
begin
  D2DObjekt:= Tlts2DObject.Create();
  D2DObjekt.Width := 4;
  D2DObjekt.Height := 3;
  D2DObjekt.Left := -2;
  D2DObjekt.Top := -1.5;
  D2DObjekt.Layer := 1;
  D2DObjekt.Color := $457890;
  D2DObjekt.Angle := 0;
  D2DObjekt.Alpha := 130;
  D2DObjekt.Graphic := 'pfadzumbild.bmp';

  if assigned(D3DDevice) then
  begin
    D3DObjekt.init(pD3DDevice);
  end;
und in der Render Funktion so gerendert:

Delphi-Quellcode:
  D3DDevice.Clear(0,nil,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1,0);

  if SUCCEEDED(D3DDevice.BeginScene) then
  begin

    D3DDevice.SetFVF(D3D9T_CUSTOMVERTEX);

    D3DObjekt.render(pD3DDevice);

    D3DDevice.EndScene;
  end;

 // Zeige Resultate auf dem Bildschirm
  D3DDevice.Present(nil,nil,0,nil);
Das funktioniert so eigentlich ganz gut auch wenn noch viel zu tun ist - bei der initialisierung des Objekts bin ich mir ziemlich unsicher aber die ganzen zusätzlichen Features Problembeseitigungen werden als nächstes "herausgetüftelt"
Eine Frage die sich mir zum Beispiel stellt ist die ob es wirklich sinnvoll ist die Position des 2D Objekts ausschliesslich über die Koordinaten der Dreiecke festzulegen, oder ob es nicht sinnvoller wäre das ganze über transformationen zu realisieren...

Um auf mein ursprüngliches Problem zurückzukommen:
Ich übergebe in der Render Methode (Jetzt heisst die nat. "init" Methode) eigentlich nur deshalb einen Zeiger weil ich Angst hatte dass die Methode sonst versucht ein ganz neues Objekt als eine Kopie des übergebenen anzulegen anstatt auf das vorhandene zuzugreifen. Das würde bedeuten dass dieses neue angelegte D3DDevice im Grunde nur in diesem einen Objekt existent wäre - damit kann man also nix anfangen

Dein Tip mit dem @ war gut - wie schon gesagt: ich habe mich bisher noch NULL (<- achtung: Wortspiel ) mit Zeigern beschäftigt deshalb wußte ich nicht wie man überhaupt den Zeiger auf ein Objekt rausfinden kann - das @ tuts *gg*






Soviel also zu meiner vörläufigen Lösung des Problems...

Was mich wirklich interessieren würde: Macht das was ich da getippselt habe Sinn oder geht das alles viel einfacher!?
Ausserdem: wenn ich mich in meinem Spiel für eine 3D "Engine" (*hüstel*) entscheide, muss dann wirklich ALLES 3D sein - oder ist es technisch auch möglich zB. Hauptmenü und das Interface als einfache 2D Grafiken zu zeichnen, ohne einen solchen Aufwand, wie da oben ersichtlich, zu treiben?

Danke für die nun folgenden, zahlreichen (!) Antworten

Gruß
Vitus
Gott segne diese Heiden! [Homer J. Simpson]
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#5

Re: Direct3D - Kapselung der Routinen

  Alt 19. Feb 2004, 19:12
Zitat:
D3DDevice ist nat. vom Typ IDirect3DDevice9
Ja, das sagst du, dass das natürlich ist. In jeder C++-Anwendung ist IDirect3DDevice9 abstrakt und kann daher nicht instanziiert werden, folglich kann es innerhalb einer Anwendung nur Zeiger auf Objekte dieses Typs geben!
Ich programmiere D3D etc. nur mit C++, daher. Das sind halt so Delphi-Vereinfachungen, mit denen ich mich nicht hundertpro auskenne. Wenn man sowieso nur einen Zeiger auf so'n Objekt hat, ist es halt auch kein Ding, den zu übergeben ;c)

Zitat:
Eine Frage die sich mir zum Beispiel stellt ist die ob es wirklich sinnvoll ist die Position des 2D Objekts ausschliesslich über die Koordinaten der Dreiecke festzulegen, oder ob es nicht sinnvoller wäre das ganze über transformationen zu realisieren...
Richtig. Transformationen sind sinnvoller und einfacher, um gar nicht erst vom Geschwindigkeitsvorteil zu sprechen. Wenn du auf die Vertices nie zugreifen musst, kann auch kein Vertexzugriff das ganze verlangsamen ;c)

Zitat:
[...]weil ich Angst hatte dass die Methode sonst versucht ein ganz neues Objekt als eine Kopie des übergebenen anzulegen anstatt auf das vorhandene zuzugreifen.
Die Angst kenne ich - aber übergibt Delphi nicht ohnehin alle Klassentypen (also von Object abgeleitete) als Referenz? Das ist auch in C++ etwas anders...

Zitat:
ich habe mich bisher noch NULL (<- achtung: Wortspiel ) mit Zeigern beschäftigt
Man beachte insbesondere in diesem Zusammenhang meine Signatur

Zitat:
oder ist es technisch auch möglich zB. Hauptmenü und das Interface als einfache 2D Grafiken zu zeichnen
NEIN. Nicht in Direct3D ab Version 8. Oder sagen wir, es ist nicht vorgesehen. Wozu auch, denn die 3D-Hardware macht sowas (insbesondere skaliert, verdreht, transparent etc.) wesentlich schneller als jede 2D-Einheit. Und was den Aufwand angeht, nun, einmal einen Spriterenderer geschrieben, der funktioniert, dann ist die Benutzung desselben ja trivial.

Was ich dir empfehlen würde, ist, dass nicht jedes Objekt seinen eigenen Vertexbuffer haben sollte, sondern wie gesagt, ein Spriterenderer hat einen Vertexbuffer, in dem nur ein Rechteck drin steht, und die Positionierung, Texturierung, Skalierung und Drehung erreichst du mit Transformationen. Dasselbe gilt für die Texturen, die solltest du zentral verwalten, denn in einer Textur sind gewöhnlich mehrere Sprites (auch 128MB Texturspeicher sind GANZ SCHNELL voll (c; ).

Oh, und SetRenderState etc. nur zur Initialisierung aufzurufen ist nicht korrekt. Das merkst du ganz schnell, wenn du ein anderes Objekt rendern willst, das andere Renderstates benötigt... Auch hier kann ein Spriterenderer Abhilfe schaffen, indem du ihm zum Beispiel eine Begin- und End-Methode gibst, in der für alle Sprites diese Einstellungen vorgenommen werden können. So sparst du dir auch die SetStreamSource-Aufrufe, denn das muss für den Spriterenderer ja auch nur einmal pro Frame gemacht werden.

Wenn ich nicht irre, muss die Hardware die Transformationen SO ODER SO bei jedem Dreieck durchführen, so dass lediglich die CPU die Matrizen vorher berechnen muss - und die kann man dann zum Beispiel puffern, zum Beispiel für jedes Objekt. Auch macht es Sinn, zu testen, ob die Textur überhaupt gesetzt werden muss (weil sie evtl. noch gesetzt ist), oder alle Aufrufe für eine Textur zwischenzuspeichern etc.

Naja, und dann macht es vielleicht auch noch Sinn, sämtliche Renderstates etc. vor dem Spriterendern in einem Stateblock zu speichern, damit das wiederhergestellt werden kann - aber das ist nicht unbedingt notwendig ;c)
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
Vitus

Registriert seit: 24. Apr 2003
Ort: Auckland, Neuseeland
38 Beiträge
 
Delphi XE2 Professional
 
#6

Re: Direct3D - Kapselung der Routinen

  Alt 20. Feb 2004, 23:44
Hallo OregonGhost,

danke für Dein Posting, ich werde das jetzt erstmal alles austesten

Was mich bei dieser Art der Spritedarstellung etwas irritiert ist das ständige neu-errechnen und neuzeichnen der Dreiecke. Uuuuuuuund: wenn ich mir so die ganzen 3D Spiele auf dem Markt anschaue dann sehen die Menügrafiken irgendwie immer extrem 2D aus.

Grüße
Vitus
Gott segne diese Heiden! [Homer J. Simpson]
  Mit Zitat antworten Zitat
OregonGhost

Registriert seit: 8. Jun 2002
Ort: Lübeck
1.216 Beiträge
 
Delphi 3 Professional
 
#7

Re: Direct3D - Kapselung der Routinen

  Alt 21. Feb 2004, 13:58
Nun, ein in 3D korrekt gerendertes Sprite sieht genauso aus wie ein 2D-Sprite!
Der Unterschied ist, dass zum einen die Geschwindigkeit viel höher ist, und du zum anderen mit vergleichsweise geringen Performance-Einbußen das Sprite drehen, skalieren oder auch alphablenden kannst. Und die CPU hat eidieweil für andere Dinge Zeit.

Und die Dreiecke musst du ja eben nicht neu errechnen. Das übernimmt ja die Grafikkarte für dich, wenn du ihr die nötigen Transformationsmatrizen gibst. Die Errechnung der Matrizen ist wiederum relativ trivial, zumal du sie ja zwischenspeichern kannst. Der Witz ist, dass es eine enorme "Performance-Strafe" gibt, wenn du andauernd auf die Vertexbuffer zugreifst, denn deren Daten liegen ja im Grafikkartenspeicher und die gibt den nur ungern her (muss gesperrt werden etc.), und das mit den Matrizen geht halt einfach schneller, selbst wenn du sie immer neu errechnest.

Hier noch ein paar Tipps aus dem SDK (Performance Optimization: General Performance Tips)
Zitat von Microsoft:
Minimize vertex buffer switches.
Use static vertex buffers where possible.
Use one large static vertex buffer per flexible vertex format (FVF) for static objects, rather than one per object.
Insbesondere die ersten beiden treffen hier zu. Der dritte trifft dann zu, wenn du trotzdem lieber die Dreieckdaten verändern willst, als Transformationsmatrizen zu verwenden.
Ach ja, und zum Theme Matrizen, wie ich bereits erwähnte:
Zitat von Microsoft:
Direct3D uses the world and view matrices that you set to configure several internal data structures. Each time you set a new world or view matrix, the system recalculates the associated internal structures. Setting these matrices frequently—for example, thousands of times per frame—is computationally time-consuming. You can minimize the number of required calculations by concatenating your world and view matrices into a world-view matrix that you set as the world matrix, and then setting the view matrix to the identity. Keep cached copies of individual world and view matrices so that you can modify, concatenate, and reset the world matrix as needed. For clarity in this documentation, Direct3D samples rarely employ this optimization.
Im selben Dokument stehen auch noch eine Reihe weiterer Performance-Tipps, einfach mal reinschauen.
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:11 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz