Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Apr 25, 2024 04:33

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Di Jun 10, 2014 20:59 
Offline
DGL Member

Registriert: Di Jun 10, 2014 06:59
Beiträge: 17
Programmiersprache: Delphi XE6
Hallo zusammen,

bin hier neu und beschäftige mich erst seit ein paar Tagen mit OpenGL. Grundsätzlich funktioniert alles wie ich mir es vorstelle (wenn auch manchmal etwas umständlich). Da ich OpenGL zur Visualisierung von Berechnungsergebnissen einsetze spielen für mich so Dinge wie Beleuchtung, Texturen etc. eine untergeordnete bis gar keine Rolle. Macht alles sehr viel einfacher :-). Ach ja: Ich nutze Delphi XE6 auf einer Win7 64 und einer Win 8 64 Maschine.

Zu meinem Problem(chen):

Ich habe eine Komponente auf Basis von TCustomControl erstellt. Die Initialisierung des DC/RC mache ich in CreateWnd bzw. die Freigabe der Handles in DestroyWnd bzw. am Schluss dann in "Destroy". Den DC kann ich in Destroy aber nicht mit ReleaseDC freigeben, da wohl der Handle der Komponente bereits nicht mehr gültig ist. Gibt Fehler... Die Ausgabe findet klassisch in "Paint" statt. Die Initialisierung von OpenGL (InitOpenGL) mache ich in der "initialization"-Sektion der Unit. Funktioniert soweit alles super und stabil. Leider kann ich die Komponente nur einmal auf einem Formular verwenden. Ein zweites mal wird da nichts ausgegeben (schwarz). Ist das eine Restriktion von OpenGL? Ich hätte halt gerne zwei unabhängige Grafiken - auf Basis der gleichen Komponente - nebeneinander gehabt...

Wäre klasse, wenn mir da jemand einen Tipp geben könnte.

Vielen Dank im Voraus

Alex


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jun 10, 2014 22:37 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Mehrere Kontexte sollten auf jeden Fall möglich sein.
Leider kann ich dir im Speziellen wenig weiterhelfen, weil ich bisher immer auf etwas fertiges gesetzt habe, das diesen Schritt für meine Bedürfnisse übernimmt (GLFW3). Kannst du vielleicht mal ein bisschen auf das Problem reduzierten Code bereitstellen?

Ausßerdem ist dir hoffentlich schon bewusst, dass du natürlich beide Grafikbereiche rendern musst und dazwischen mit "wglMakeCurrent"(Windows) oder "glXMakeCurrent"(X also Linux, *BSD, ...) wechseln musst? Der aktuelle Kontext ist übrigens Thread lokal.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 11, 2014 07:44 
Offline
DGL Member

Registriert: Di Jun 10, 2014 06:59
Beiträge: 17
Programmiersprache: Delphi XE6
Hallo OpenglerF,

vielen Dank für Deine Antwort. Das mit wglMakeCurrent kannte ich noch nicht.

ES FUNKTIONIERT!

Nichts desto trotz hier mal ein paar Code-Fragmente, die ich auf das Wesentliche verkürzt habe:

Die komplette Definition der Komponente sieht momentan so aus:
Code:
  1.  
  2. type
  3.   // Projekt Canvas OpenGL
  4.   TfemCustomOpenGLCanvas = class(TCustomControl)
  5.   private
  6.     // Device Context
  7.     FDC: HWND;
  8.     // Rendering Context
  9.     FRC: HGLRC;
  10.     // Schriftspeicher
  11.     FFontLists: Cardinal;
  12.     // OpenGL bereit
  13.     FOpenGLReady: Boolean;
  14.     // Sichtfeld Winkel
  15.     FFieldOfViewAngle: Double;
  16.     // Clipping
  17.     FClippingNear, FClippingFar: Double;
  18.     // Kameraverschiebung
  19.     FMoveX, FMoveY, FMoveZ: Single;
  20.     // Objektdrehung
  21.     FRotateX, FRotateY, FRotateZ: Single;
  22.     // Schrift setzen
  23.     procedure SetFontList;
  24.     // Sichtfeld Winkel
  25.     procedure SetFieldOfViewAngle(const Value: Double);
  26.     function GetFieldOfViewAngleStored: Boolean;
  27.     // Clipping
  28.     procedure SetClipping(Index: Integer; const Value: Double);
  29.     function GetClippingStored(Index: Integer): Boolean;
  30.     // Kameraverschiebung
  31.     procedure SetMove(Index: Integer; const Value: Single);
  32.     function GetMoveStored(Index: Integer): Boolean;
  33.     // Objektdrehung
  34.     procedure SetRotate(Index: Integer; const Value: Single);
  35.     function GetRotateStored(Index: Integer): Boolean;
  36.   protected
  37.     procedure CreateWnd; override;
  38.     procedure DestroyWnd; override;
  39.     procedure WMSize(var Msg: TWMSize); message WM_SIZE;
  40.     procedure WMEraseBkgnd(var Msg: TWmEraseBkgnd); message WM_ERASEBKGND;
  41.     procedure CMFontChanged(var Msg: TMessage); message CM_FONTCHANGED;
  42.     procedure Paint; override;
  43.     // Text an Position X, Y ausgeben (Bildschirmkoordinaten)
  44.     procedure ShowTextAt(X, Y: Integer; const S: string);
  45.     // Sichtfeld Winkel
  46.     property FieldOfViewAngle: Double read FFieldOfViewAngle write SetFieldOfViewAngle stored GetFieldOfViewAngleStored;
  47.     // Clipping
  48.     property ClippingNear: Double index 1 read FClippingNear write SetClipping stored GetClippingStored;
  49.     property ClippingFar: Double index 2 read FClippingFar write SetClipping stored GetClippingStored;
  50.     // Kameraverschiebung
  51.     property MoveX: Single index 1 read FMoveX write SetMove stored GetMoveStored;
  52.     property MoveY: Single index 2 read FMoveY write SetMove stored GetMoveStored;
  53.     property MoveZ: Single index 3 read FMoveZ write SetMove stored GetMoveStored;
  54.     // Objektdrehung
  55.     property RotateX: Single index 1 read FRotateX write SetRotate stored GetRotateStored;
  56.     property RotateY: Single index 2 read FRotateY write SetRotate stored GetRotateStored;
  57.     property RotateZ: Single index 3 read FRotateZ write SetRotate stored GetRotateStored;
  58.   public
  59.     // Initialisierung
  60.     constructor Create(AOwner: TComponent); override;
  61.     // Freigabe
  62.     destructor Destroy; override;
  63.   published
  64.   end;
  65.  


Hier wird der Geräte- und der Renderkontext erstellt:
Code:
  1.  
  2. procedure TfemCustomOpenGLCanvas.CreateWnd;
  3. // Fenster erstellen
  4. begin
  5.   inherited;
  6.   // Gerätekontext
  7.   FDC := GetDC(Handle);
  8.   // Renderkontext
  9.   FRC := CreateRenderingContext(FDC, [opDoubleBuffered], 32, 24, 0, 0, 0, 0);
  10.   ActivateRenderingContext(FDC, FRC);
  11.   // Schrift setzen
  12.   SetFontList;
  13.   // OpenGL ist bereit
  14.   FOpenGLReady := True;
  15. end;
  16.  


Falls der Context sich zwischendurch ändert:
Code:
  1.  
  2. procedure TfemCustomOpenGLCanvas.DestroyWnd;
  3. // Fenster freigeben
  4. begin
  5.   DeactivateRenderingContext;
  6.   DestroyRenderingContext(FRC);
  7.   ReleaseDC(Handle, FDC);
  8.   inherited;
  9. end;
  10.  


Größenänderung:
Code:
  1.  
  2. procedure TfemCustomOpenGLCanvas.WMSize(var Msg: TWMSize);
  3. // Panelgröße wurde geändert
  4. begin
  5.   inherited;
  6.   if FOpenGLReady then
  7.     glViewport(0, 0, Msg.Width, Msg.Height);
  8. end;
  9.  


Die eigentliche Zeichenroutine (hier verkürzt):
Code:
  1.  
  2. procedure TfemCustomOpenGLCanvas.Paint;
  3. // Ausgabe
  4. var
  5.   ScreenRatio: Single;
  6. begin
  7.   if FOpenGLReady then
  8.   begin
  9.     // Tiefentest aktivieren
  10.     glEnable(GL_DEPTH_TEST);
  11.     // Backface Culling deaktivieren
  12.     glDisable(GL_CULL_FACE);
  13.     // Hintergrund löschen
  14.     glClearColor(1.0, 1.0, 1.0, 0.0);
  15.     glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  16.  
  17.     // Kamera *******************************************************************
  18.     glMatrixMode(GL_PROJECTION);
  19.     // Identitätsmatrix laden
  20.     glLoadIdentity;
  21.     // Perspektive einstellen (Blickwinkel, Verhältnis Breit / Höhe, Clipping vorne, Clipping hinten)
  22.     ScreenRatio := ClientWidth / ClientHeight;
  23.     gluPerspective(FFieldOfViewAngle, ScreenRatio, FClippingNear, FClippingFar);
  24.     // Kameraverschiebung X/Y/Z
  25.     glTranslatef(FMoveX, FMoveY, FMoveZ);
  26.  
  27.     // Modell *******************************************************************
  28.     glMatrixMode(GL_MODELVIEW);
  29.     // Identitätsmatrix laden
  30.     glLoadIdentity;
  31.  
  32.     // skallieren
  33.     glScalef(1.0, 1.0, 1.0);
  34.     // rotieren des Modells
  35.     glRotatef(FRotateX, 1.0, 0.0, 0.0);
  36.     glRotatef(FRotateY, 0.0, 1.0, 0.0);
  37.     glRotatef(FRotateZ, 0.0, 0.0, 1.0);
  38.  
  39.     // hier wird gezeichnet
  40.     // ...
  41.  
  42.     // Ausgabe
  43.     SwapBuffers(FDC);
  44.   end;
  45. end;
  46.  


Wie gesagt: Initialisiert wird im "initialization"_abschnitt:
Code:
  1.  
  2. initialization
  3.  
  4. InitOpenGL;
  5.  
  6. end.
  7.  


Bin natürlich für alle Tipps empfänglich :D

Alex


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 11, 2014 16:48 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1278
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich hatte mal eine kleine Demo geschrieben, dort wird gezeigt, wie man 2 OpenGL-Grafiken unabhägig zeichen kann.
Code:
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, OpenGL, ExtCtrls, StdCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Panel1: TPanel;
  12.     Panel2: TPanel;
  13.     PaintBox1: TPaintBox;
  14.     PaintBox2: TPaintBox;
  15.     procedure FormCreate(Sender: TObject);
  16.     procedure FormDestroy(Sender: TObject);
  17.     procedure DrawScene1;
  18.     procedure DrawScene2;
  19.     procedure PaintBox1Paint(Sender: TObject);
  20.     procedure PaintBox2Paint(Sender: TObject);
  21.   private
  22.     { Private-Deklarationen }
  23.     hrc1, hrc2 : HGLRC;
  24.     dc1, dc2 : hdc;
  25.     procedure SetDCPixelFormat(Handle : HDC);
  26.   public
  27.     { Public-Deklarationen }
  28.   end;
  29.  
  30. var
  31.   Form1: TForm1;
  32.  
  33. implementation
  34.  
  35. procedure TForm1.SetDCPixelFormat(Handle: HDC);
  36. var
  37.   pfd: TPixelFormatDescriptor;
  38.   nPixelFormat: Integer;
  39.  
  40. begin
  41.   FillChar(pfd, SizeOf(pfd), 0);
  42.   with pfd do begin
  43.     nSize     := sizeof(pfd);                               // Size of this structure
  44.     nVersion  := 1;                                         // Version number
  45.     dwFlags   := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL; //or PFD_DOUBLEBUFFER;  // Flags
  46.     iPixelType:= PFD_TYPE_RGBA;                             // RGBA pixel values
  47.     cColorBits:= 24;                                        // 24-bit color
  48.     cDepthBits:= 32;                                        // 32-bit depth buffer
  49.     iLayerType:= PFD_MAIN_PLANE;                            // Layer type
  50.   end;
  51.   nPixelFormat := ChoosePixelFormat(Handle, @pfd);
  52.   SetPixelFormat(Handle, nPixelFormat, @pfd);
  53. end;
  54.  
  55. {$R *.dfm}
  56.  
  57. procedure TForm1.FormCreate(Sender: TObject);
  58. var
  59.   fdc : hdc;
  60.   base : Integer;
  61. begin
  62.   dc1 := GetDC(Panel1.Handle);
  63.   SetDCPixelFormat(dc1);
  64.   hrc1 := wglCreateContext(dc1);
  65.   dc2 := GetDC(Panel2.Handle);
  66.   SetDCPixelFormat(dc2);
  67.   hrc2 := wglCreateContext(dc2);
  68. end;
  69.  
  70. procedure TForm1.FormDestroy(Sender: TObject);
  71. begin
  72.   wglDeleteContext(hrc1);
  73.   wglDeleteContext(hrc2);
  74. end;
  75.  
  76. procedure TForm1.DrawScene1;
  77. var
  78.   fdc : hdc;
  79.   base : Integer;
  80. const
  81.   s : PChar = 'opengl 2';
  82.  
  83. begin
  84.   glClearColor(0.0, 0.5, 0.5, 0);
  85.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  86.   glBegin(GL_TRIANGLES);
  87.     glColor3f(1.0, 0, 0);
  88.     glVerTex2f(-0.5, -0.5);
  89.     glColor3f(0, 1.0, 0);
  90.     glVerTex2f(0.5, -0.5);
  91.     glColor3f(0, 0, 1.0);
  92.     glVerTex2f(-0, 0.5);
  93.   glEnd;
  94.   glColor3f(1.0, 1.0, 1.0);
  95.   wglUseFontBitmaps(dc1, 0, 255, 0);
  96.   glListBase(0);
  97.   glRasterPos2f(0.2, 0);
  98.   glCallLists(Length(s), GL_BYTE, s);
  99.   glFlush;
  100. end;
  101.  
  102. procedure TForm1.DrawScene2;
  103. var
  104.   fdc : hdc;
  105.   base : Integer;
  106. const
  107.   s : PChar = 'opengl 1';
  108.  
  109. begin
  110.   glClearColor(0.5, 0.5, 0, 0);
  111.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  112.   glBegin(GL_TRIANGLES);
  113.     glColor3f(1.0, 0, 0);
  114.     glVerTex2f(-0.5, -0.5);
  115.     glColor3f(0, 1.0, 0);
  116.     glVerTex2f(-0, 0.5);
  117.     glColor3f(0, 0, 1.0);
  118.     glVerTex2f(0.5, -0.5);
  119.   glEnd;
  120.   wglUseFontBitmaps(dc1, 0, 255, 0);
  121.   glListBase(0);
  122.   glRasterPos2f(0.2, 0);
  123.   glCallLists(Length(s), GL_BYTE, s);
  124.   glFlush;
  125. end;
  126.  
  127. procedure TForm1.PaintBox1Paint(Sender: TObject);
  128. begin
  129.   wglMakeCurrent(dc1, hrc1);
  130.   DrawScene1;
  131.   wglMakeCurrent(0, 0);
  132. end;
  133.  
  134. procedure TForm1.PaintBox2Paint(Sender: TObject);
  135. begin
  136.   wglMakeCurrent(dc2, hrc2);
  137.   DrawScene2;
  138.   wglMakeCurrent(0, 0);
  139. end;
  140.  
  141. end.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 11, 2014 19:07 
Offline
DGL Member

Registriert: Di Jun 10, 2014 06:59
Beiträge: 17
Programmiersprache: Delphi XE6
Hallo Mathias,

ist im Wesentlichen so wie bei mir jetzt auch :). Hättest ja theoretisch jedesmal die gleiche Zeichenroutine starten können, nachdem du vorher den DC umgeschaltet hast. Ich mache das in meiner Komponente halt jetzt am Eingang der "Paint"-Methode. Läuft ja alles im Vordergrund...

Eine Frage habe ich aber dazu noch:

Hat es einen bestimmten Grund, warum Du nach DrawScene wglMakeCurrent(0, 0) setzt? Da Du jeweils vor dem Zeichnen explizit DC/RC angibst wäre das ja eigentlich nicht nötig. Oder?

Alex


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 11, 2014 19:59 
Offline
DGL Member

Registriert: Mo Nov 09, 2009 12:01
Beiträge: 200
@BigAl
Dasselbe Problem hatte ich anfangs auch. Du mußt halt bei jeder Aktion des Fensters zuvor den Context binden, wie Du es wohl auch schon gemacht hast. Aufpassen muss man auch beim Destroyen, da muß zuvor auch der Context gebunden werden, sonst vernichtet man ggf ein ganz anderes Fenster.

Aufpassen muß man zusätzlich bei gedockten Fenstern mit diesen Dockingsystem. Beim Docken bzw. Entdocken ändert sich de Handle des Fensters und entsprechend muß der Context auch neu gebunden werden.


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 11, 2014 21:14 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1278
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Hat es einen bestimmten Grund, warum Du nach DrawScene wglMakeCurrent(0, 0) setzt? Da Du jeweils vor dem Zeichnen explizit DC/RC angibst wäre das ja eigentlich nicht nötig. Oder?

Ich habe jetzt 0,0 gelöscht und es läuft auch. Ich weis nicht mehr, warum ich das geschrieben habe, der Code ist schon sehr alt.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 62 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.078s | 17 Queries | GZIP : On ]