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

01.11.2012, 15:03

Direct3D mit .NET-Forms

Hallo,

ich versuche seit einiger Zeit, einen Level-Editor mit Direct3D 9 und dem .NET-Framework in c++ zu programmieren, da die Zeichenmethoden der Steuerelemente trotz Pufferung zu langsam sind.

Dafür habe ich mich an folgendes Tutorial gahalten:http://www.codeproject.com/Articles/4212…ith-NET-Forms-C

Leider sind die Gezeichneten Primitiven nicht zu sehen!

In Konstruktor meiner View-Klasse(MVC) habe ich diesen Code:
"form" steht dabei für eine clr-Fensterklasse.
Außerdem ist das deklariert:
IDirect3DDevice9* d3ddev;
LPDIRECT3D9 d3d;
HWND hDX9;

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// DX-Fensterhandle erstellen          
HINSTANCE hInstance = (HINSTANCE)System::Runtime::InteropServices::Marshal::GetHINSTANCE(form->GetType()->Module).ToPointer();          
WNDCLASSEX wc;          
ZeroMemory(&wc, sizeof(WNDCLASSEX));
            
wc.cbSize = sizeof(WNDCLASSEX);         
wc.style = CS_HREDRAW | CS_VREDRAW;         
wc.lpfnWndProc = &WindowProc;           
wc.hInstance = hInstance;           
wc.hbrBackground = NULL;            
wc.lpszClassName = L"WindowClass";
            
RegisterClassEx(&wc);
            
Control^ panel = form->GetDrawingOutputInterface(); // Das Steuerelement, in das gezeichnet werden soll         
hDX9 = CreateWindowEx(  NULL,                                   
                         L"WindowClass",                                                                                                            
                         NULL,
                         WS_CHILD,                                  
                         panel->ClientRectangle.X,                                  
                         panel->ClientRectangle.Y,                                  
                         panel->Width,                                  
                         panel->Height,                                 
                         (HWND)(void*)panel->Handle.ToPointer(),
             NULL,
             hInstance, 
             NULL);    
  
ShowWindow(hDX9, SW_SHOW); 
            
initD3D(hDX9);



C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void initD3D(HWND hHandle)
{
  d3d = Direct3DCreate9(D3D_SDK_VERSION); // create the Direct3D interface
  D3DPRESENT_PARAMETERS d3dpp;             // create a struct to hold various device information                
  ZeroMemory(&d3dpp, sizeof(d3dpp));           // clear out the struct for use 
  d3dpp.Windowed = true;                
  d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;         
  d3dpp.hDeviceWindow = hHandle;

                
  pin_ptr<IDirect3DDevice9*> p = &d3ddev;               
  IDirect3DDevice9** pinnedPtr = p;
                
  d3d->CreateDevice(     D3DADAPTER_DEFAULT,                                    
                        D3DDEVTYPE_HAL,                                 
                        hHandle,                                    
                        D3DCREATE_SOFTWARE_VERTEXPROCESSING,                                    
                        &d3dpp,                                 
                        pinnedPtr);
                
  d3ddev->SetRenderState(D3DRS_LIGHTING, FALSE);        
  d3ddev->SetRenderState(D3DRS_COLORVERTEX, TRUE);        
  d3ddev->SetRenderState(D3DRS_ZENABLE, FALSE);        
  d3ddev->SetRenderState(D3DRS_DITHERENABLE, TRUE);        
  d3ddev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
        
  D3DXMATRIX matrix;                
  D3DXMatrixIdentity(&matrix);        
  d3ddev->SetTransform( D3DTS_VIEW, &matrix);        
  d3ddev->SetTransform( D3DTS_PROJECTION, &matrix);        
  d3ddev->SetTransform( D3DTS_WORLD, &matrix);
}

Zur Abweichung vom Tutorial mit pin_ptr siehe:
http://msdn.microsoft.com/en-us/library/…h(v=vs.80).aspx

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
struct COLVertex 
{
    float x, y, z;
    D3DCOLOR c;
    COLVertex()
    {
    }
    COLVertex(const float fx, const float fy, D3DCOLOR col) : x(fx), y(fy), z(0.0f), c(col)
    {
    }
    static const DWORD  dwFVF;
};
const DWORD COLVertex::dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;

In einer Paint-Methode, die für das Steuerelement registriert ist soll nun etwas gezeichnet werden (2D):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(100, 40, 100), 1.0f, 0);
d3ddev->BeginScene();
COLVertex* a = new COLVertex[4];
a[0] = COLVertex(-100,-100,D3DCOLOR_XRGB(255,255,255));
a[1] = COLVertex(-100, 100,D3DCOLOR_XRGB(255,255,255));
a[2] = COLVertex( 100, 100,D3DCOLOR_XRGB(255,255,255));
a[3] = COLVertex( 100,-100,D3DCOLOR_XRGB(255,255,255));
d3ddev->SetFVF(COLVertex::dwFVF);
d3ddev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, a, 0);
delete[] a;
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);


Das Problem: Vom Quadrat ist nichts zu sehen. Der Puffer wird zwar mit lila geleert, aber sonst passiert nichts.
Außerdem sagt mir der VS 2010 Debugger, d3ddev sei ein nicht definierter Wert, obwohl CreateDevice nicht fehlschlägt.

Kennt sich Jemand mit verwaltetem Code aus, oder hat sogar etwas ähnliches schon mal gemacht?
Oder weiß Jemand, wie es anders gehen könnte?

Schon mal vielen Dank

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

01.11.2012, 15:09

Ich geh schon mal in Deckung wegen den C++/CLI Angriffen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Counterfeit

Frischling

Beiträge: 32

Beruf: Softwareentwickler

  • Private Nachricht senden

3

01.11.2012, 15:40

"In einer Paint-Methode, die für das Steuerelement registriert ist"

Wird diese Paint-Methode auch immer aufgerufen oder nur einmal? Zum testen könntest du dir einen Timer erstellen, der die Paint-Methode aufruft.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

01.11.2012, 15:58

Ein paar Fragen in absteigender Wichtigkeit: Wieso C++/CLI? Wieso .NET, wenn es C++ sein soll, bzw. wieso C++ wenn es .NET sein soll? Wieso erzeugst du selbst ein Fenster, wenn du einfach das HWND des Control benutzen könntest? Wieso erzeugst du in jedem Frame ein neues Vertex Array? Wieso D3DCREATE_SOFTWARE_VERTEXPROCESSING? Wieso diese riesigen Vertexkoordinaten? Wieso D3DRS_DITHERENABLE?

Gib deinen Vertices mal ein z zwischen 0 und 1, möglicherweise werden deine Dreiecke einfach geclipped...

5

01.11.2012, 16:40

Erstmal danke für eure raschen Antworten.

Die Paint-Methode wird manuell im Code, und wenn das Steuerelement verdeckt und wieder aufgedeckt wird aufgerufen.
Das Gesamte Programm ist schon in C++/CLI fertig. Und weil es ziemlich groß ist, werde ich nicht alles neu schreiben, zumal ich dort ausgiebigen Gebrauch der NET-Klassen mache.
Wenn es möglich wäre den Teil, der sich um das Zeichnen kümmert in eine Andere Sprache auszulagern, könnte ich mich notfalls auch mit C# und XNA anfreunden.
Nur dachte ich, wieso so kompliziert, wenn ich D3D direkt in das CLI-Programm integrieren könnte. (Was scheinbar auch nicht so einfach ist)

@dot
Wenn ich mir das Handle so hole, ist das Ergebniss das selbe, nur dass das lila noch bei jedem Paint flackert. (Unabhängig davon, ob ich die Primitiven zeichne, oder nicht)

C-/C++-Quelltext

1
hDX9 = (HWND)panel->Handle.ToPointer();

Das Array dient nur zum unkomplizierten Testen der Zeichenfunktion.
D3DCREATE_SOFTWARE_VERTEXPROCESSING oder Hardware ist doch hierfür nicht wichtig oder? Übrigens ergeben sich bei mir dadurch sowieso keine Performancevorteile.
Das Quadrat ist nur so riesig, damit man es nicht übersieht...

Ich habe deinen Vorschlag mit den X-Koordinaten mal ausprobiert. Leider ohne Erfolg. In dem Spiel, für das der Editor ist, mache ich es auch so und es funktioniert.

Allerdings verwendet das Spiel auch einen Shader. Könnte es daran liegen, dass es da klappt und hier nicht?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

01.11.2012, 17:24

Das Gesamte Programm ist schon in C++/CLI fertig. Und weil es ziemlich groß ist, werde ich nicht alles neu schreiben, zumal ich dort ausgiebigen Gebrauch der NET-Klassen mache.

Verständlich, für die Zukunft würde ich allerdings raten, C++/CLI nicht mehr zu Schreiben von WinForms Anwendungen zu verwenden. Grund siehe z.B. hier oder hier. Wenn du C++ lernen/verwenden willst, dann lern/verwend C++. C++/CLI ist nicht C++. Wenn du Windows Forms Anwendungen schreiben willst, nimm eine dafür geeignete Sprache wie z.B. C#. C++/CLI ist weder dafür gedacht, noch gut dafür geeignet...

Wenn ich mir das Handle so hole, ist das Ergebniss das selbe, nur dass das lila noch bei jedem Paint flackert. (Unabhängig davon, ob ich die Primitiven zeichne, oder nicht)

Gib dem Control eine leere OnPaintBackground Methode. ;)

C-/C++-Quelltext

1
hDX9 = (HWND)panel->Handle.ToPointer();

Das Array dient nur zum unkomplizierten Testen der Zeichenfunktion.

Trotzdem könnte es einfach ein statisches Array sein, anstatt in jedem Frame einen neuen Speicherblock zu allokieren und Werte hineinzukopieren... ;)

D3DCREATE_SOFTWARE_VERTEXPROCESSING oder Hardware ist doch hierfür nicht wichtig oder? Übrigens ergeben sich bei mir dadurch sowieso keine Performancevorteile.

Naja, Software Vertexprocessing ist eigentlich nur auf irgendwelchen Intel Chips notwendig, wenn du eine richtige Grafikkarte hast, dann gibt es keinen Grund, nicht Hardware Vertexprocessing zu verwenden...

Ich habe deinen Vorschlag mit den X-Koordinaten mal ausprobiert. Leider ohne Erfolg. In dem Spiel, für das der Editor ist, mache ich es auch so und es funktioniert.

Allerdings verwendet das Spiel auch einen Shader. Könnte es daran liegen, dass es da klappt und hier nicht?

Hm, sagt die Direct3D Debug Runtime was?

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »dot« (01.11.2012, 17:34)


7

04.11.2012, 19:18

Im Prinzip kann ich deine Argumente ja verstehen. Allerdings verwende ich C++/CLI doch genau dafür, um managed mit unmanaged zu kombinieren.

Die Direct3D Debug Runtime gibt keine Fehler aus, wenn ich D3DCREATE_HARDWARE_VERTEXPROCESSING verwende. (Bei Software aber schon)
Wenn ich eine neue Klasse von einem Steuerelement erben lasse, OnPaintBackground dann mit einer leeren Methode überschreibe und diese Klasse dann zum Zeichnen verwende, ist das Flackern weg. Vielen Dank.

Nur hilft mir das nicht bei meinem Problem weiter! Ich glaube ich werde den Kern des Programms in dlls kompilieren (ganz systemeigen) und die Benutzeroberfläche dann neu in C# schreiben.

Falls es einen unkomplizierteren Weg gibt: Ich bin offen für Neuerungen

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

04.11.2012, 19:49

Im Prinzip kann ich deine Argumente ja verstehen. Allerdings verwende ich C++/CLI doch genau dafür, um managed mit unmanaged zu kombinieren.

Naja, ich ging halt davon aus, dass du deine komplette Software inkl. GUI und was weiß ich was noch in C++/CLI gecodet hast!? Wenn du nur den Rendering Teil in C++/CLI schreibst und diesen dann z.B. von deiner C# GUI aus verwendest, dann hast du C++/CLI imo richtig eingesetzt. So wie ich das verstanden hab, ist das bei dir aber nicht der Fall!?

Die Direct3D Debug Runtime gibt keine Fehler aus, wenn ich D3DCREATE_HARDWARE_VERTEXPROCESSING verwende. (Bei Software aber schon)

Welche Fehler?

Nur hilft mir das nicht bei meinem Problem weiter! Ich glaube ich werde den Kern des Programms in dlls kompilieren (ganz systemeigen) und die Benutzeroberfläche dann neu in C# schreiben.

Naja, wenn das Programm jetzt schon komplett in C++/CLI geschrieben ist, dann belass es einfach dabei. Jetzt alles umzuschreiben, ist wohl auch nicht unbedingt sinnvoll. Ich würde nur für die Zukunft davon abraten... ;)

Falls es einen unkomplizierteren Weg gibt: Ich bin offen für Neuerungen

Naja, du könntest z.B. einfach fertige .NET Bindings wie SlimDX oder SharpDX verwenden. Das macht aber vor allem Sinn, wenn man eben z.B. C# verwendet. Da du sowieso schon mit C++/CLI unterwegs bist, wirst du nicht besonders viel davon haben...

9

04.11.2012, 23:11

Zitat

Naja, ich ging halt davon aus, dass du deine komplette Software inkl. GUI und was weiß ich was noch in C++/CLI gecodet hast!? Wenn du nur den Rendering Teil in C++/CLI schreibst und diesen dann z.B. von deiner C# GUI aus verwendest, dann hast du C++/CLI imo richtig eingesetzt. So wie ich das verstanden hab, ist das bei dir aber nicht der Fall!?

Ähm, ich habe es genau andersrum gemacht. Der Code ist eigentlich unmanaged. Nur die GUI, also die Schnittstelle zum Benutzer ist CLI. Diese wollte ich jetzt mit mit Direct3D "aufrüsten". Meine Idee war, dass ich nur die GUI in C# neu schreibe, da ich dort XNA als DX-Ersatz verwenden kann. Den Rest könnte ich dann in Bibliotheken packen, die aus C# angesprochen werden.

Die Direct3D Debug Runtime sagt folgendes:
Direct3D9: (INFO) :Using P4 PSGP
Direct3D9: (INFO) :Using FF to VS converter in software vertex processing
Direct3D9: (ERROR) :ASSERTION FAILED! File s:\gfx_aug09\windows\directx\dxg\inactive\d3d9\d3d\fw\lhbatchfilter.cpp Line 3466: pArgs->Flags.Discard

Daraus werde ich aber nicht schlau, zumal es nichts mir dem SwapEffect Discard zu tun haben scheint, und eben nur bei D3DCREATE_SOFTWARE_VERTEXPROCESSING auftritt.

Zitat

Naja, du könntest z.B. einfach fertige .NET Bindings wie SlimDX oder SharpDX verwenden. Das macht aber vor allem Sinn, wenn man eben z.B. C# verwendet. Da du sowieso schon mit C++/CLI unterwegs bist, wirst du nicht besonders viel davon haben...

Ich werde mich mal etwas einlesen und schauen, ob das eine Alternative zu XNA darstellt.

Werbeanzeige