AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Direkt auf Bitmap zeichnen (OpenGL)

Direkt auf Bitmap zeichnen (OpenGL)

Ein Thema von EWeiss · begonnen am 23. Jun 2019 · letzter Beitrag vom 28. Jun 2019
Antwort Antwort
Seite 1 von 2  1 2   
EWeiss
(Gast)

n/a Beiträge
 
#1

Direkt auf Bitmap zeichnen (OpenGL)

  Alt 23. Jun 2019, 21:59
Ich rendere meine Plugins auf das DC von meinem Window. (Das Flackert aber ohne spezielle tricks)

Jetzt möchte ich aber direkt auf ein Bitmap zeichnen wie muss ich den CreateRenderingContext erstellen damit dieser erkennt das ich auf ein Bitmap zeichnen will?
Das HBitmap wird von außerhalb übergeben.
Delphi-Quellcode:
    glDC := GetDC(WinHandle);

    // Renderkontext erstellen (32 Bit Farbtiefe,
    // 32 Bit Tiefenpuffer, Doublebuffering)
    h_RC := CreateRenderingContext(glDC, [opDoubleBuffered], 24, 32, 0, 0, 0, 0);
verwende ich jetzt
glDC := CreateCompatiblemDC(GetDC(WinHandle));

Dann wird im CreateRenderingContext erkannt das ich ein Bitmap anstelle eines Fenster verwenden will.
Aber es rendert nichts.
Fehler gibt es aber auch nicht.

crosspost: https://delphigl.com/forum/viewtopic.php?f=2&t=11685

gruss

Geändert von EWeiss (24. Jun 2019 um 00:09 Uhr)
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
635 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#2

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 24. Jun 2019, 10:42
Emil,
mit der Menge an Information kann man schwerlich helfen.
Wie machst Du den RC Current, wie wird gezeichnet......... Flush, Finish, swap buffers etc.......
Fritz Westermann
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#3

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 24. Jun 2019, 11:10
CreateRenderingContext..
Delphi-Quellcode:
  glDC := GetDC(WinHandle);

  // Renderkontext erstellen (32 Bit Farbtiefe,
  // 32 Bit Tiefenpuffer, Doublebuffering)
  h_RC := CreateRenderingContext(glDc,
    [opDoubleBuffered], 24, 32, 0, 0, 0, 0);
  // Erstellten Renderkontext aktivieren
  ActivateRenderingContext(glDc, h_RC, True);
gezeichnet wird so..
Delphi-Quellcode:
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
        glLoadIdentity();

        EnterCriticalSection(CritSect);
        try
          glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, StretchWidth, StretchHeight, GL_BGRA,
            GL_UNSIGNED_BYTE, VisInfo^.VisBuf);
        finally
          LeaveCriticalSection(CritSect);
        end;

        glColor4f(1, 1, 1, 1);
        glEnable(GL_TEXTURE_2D);

        if VisTexture <> 0 then
          glBindTexture(GL_TEXTURE_2D, VisTexture);
        glBegin(GL_QUADS);
        glTexCoord2d(0.0, 0.0);
        glVertex2f(0.0, 0.0);
        glTexCoord2d(0.0, 1.0);
        glVertex2f(0.0, LastHeight);
        glTexCoord2d(1.0, 1.0);
        glVertex2f(LastWidth, LastHeight);
        glTexCoord2d(1.0, 0.0);
        glVertex2f(LastWidth, 0.0);
        glEnd();

        if length(BassSoInfo.SongTitle) > 0 then
        begin
          BassSoVis.SongRender;
          if SON_ShowFPS then
            BassSoVis.GetFramesInSec;

          if SON_ShowPrgBar then
          begin
            SON_Current_YPos := 20;
            ProgressBarRender;
          end
          else
            SON_Current_YPos := 5;
        end;

        glFlush;
        SwapBuffers(glDC);
      end;
Bedingt durch diese Zeile teile ich dem CreateRenderingContext mit das ich auf ein Window zeichnen will das möchte ich aber nicht.
glDC := GetDC(WinHandle);

also gibt es nur die Möglichkeit das DC auf andere weise zu erstellen.
Über...
Delphi-Quellcode:
glDC := CreateCompatibleDc(0);
SelectObject(glDC, MeinÜbergebenesBitmap);
Sollte stimmen das Problem ist nur es rendert nicht.

In der Function CreateRenderingContext wird dann abhängig von der Erstellung des DC (MemoryDC, WindowDc.. usw..) das entsprechende Flag gesetzt.
Delphi-Quellcode:
  if GL_LibHandle = nil then
    InitOpenGL;

  FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);

  with PFDescriptor do
  begin
    nSize := SizeOf(PFDescriptor);
    nVersion := 1;
    dwFlags := PFD_SUPPORT_OPENGL;

    AType := GetObjectType(DC);

    if AType = 0 then
      RaiseLastOSError;

    if AType in MemoryDCs then
      dwFlags := dwFlags or PFD_DRAW_TO_BITMAP
    else
      dwFlags := dwFlags or PFD_DRAW_TO_WINDOW;
Aber wie gesagt es tut sich nichts.

Im Moment mache ich es so das ich auf das DC meiner Haupt Anwendung zeichne und den Canvas auf die korrekte Position verschiebe.
Logischerweise ist das Fenster nicht sichtbar, es rendert zwar aber man sieht es nicht.
Deshalb wende ich einen Trick an in dem ich das darüberliegende Fenster einfach mit dem WS_EX_LAYERED Style versehe und den Alpha Kanal auf 160 einstelle.

Nur dann sind die Schriften etwas verblasst, was ich umgehen möchte indem ich direkt auf das Bitmap zeichne. (siehe Pic)
Direkt auf das Hauptfenster zeichnen Funktioniert nicht das Flackert extrem deshalb der Umweg über das Bitmap. (WM_ERASEBKGND) macht hier Probleme.

gruss

Geändert von EWeiss (11. Jul 2019 um 15:58 Uhr)
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
355 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 24. Jun 2019, 11:34
Ich rendere meine Plugins auf das DC von meinem Window. (Das Flackert aber ohne spezielle tricks)

Jetzt möchte ich aber direkt auf ein Bitmap zeichnen wie muss ich den CreateRenderingContext erstellen damit dieser erkennt das ich auf ein Bitmap zeichnen will?
Das HBitmap wird von außerhalb übergeben.
Delphi-Quellcode:
    glDC := GetDC(WinHandle);

    // Renderkontext erstellen (32 Bit Farbtiefe,
    // 32 Bit Tiefenpuffer, Doublebuffering)
    h_RC := CreateRenderingContext(glDC, [opDoubleBuffered], 24, 32, 0, 0, 0, 0);
verwende ich jetzt
glDC := CreateCompatiblemDC(GetDC(WinHandle));

Dann wird im CreateRenderingContext erkannt das ich ein Bitmap anstelle eines Fenster verwenden will.
Aber es rendert nichts.
Fehler gibt es aber auch nicht.

crosspost: https://delphigl.com/forum/viewtopic.php?f=2&t=11685

gruss
Naja, Du hats ja absolute nichts unternommen, um die Bitmap mit dem erzeugten device context zu verbinden. Sieh Dir mal die SelectObject API Funktion an. Wichtig: Speicher den Rückgabewert der Funktion und selektiere diesen wieder per SelectObject in den glDC bevor Du den zerstörst, sonst ist deine Bitmap futsch.
Peter Below
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#5

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 24. Jun 2019, 11:40
Zitat:
Naja, Du hats ja absolute nichts unternommen, um die Bitmap mit dem erzeugten device context zu verbinden. Sieh Dir mal die SelectObject API Funktion an. Wichtig: Speicher den Rückgabewert der Funktion und selektiere diesen wieder per SelectObject in den glDC bevor Du den zerstörst, sonst ist deine Bitmap futsch.
Du meinst sicherlich OldBmp := SelectObject(… Ich habe festgestellt das meistens das OldBitmap 0 ist, es ist also nicht sicher auf der weise die Rückgabe auszuwerten.

Das ist ja mein Problem
Was soll ich unternehmen um das DC mit dem device context zu verbinden?

Das Bitmap kann nicht zerstört werden es wird von außen zugeführt und ist solange gültig wie die Anwendung läuft.
Das einzige was verloren geht ist das DC.. nach jedem
Delphi-Quellcode:
        glFlush;
        SwapBuffers(glDC);
Ich könnte vor glClearColor das DC neu zuweisen und selektieren.. was anderes fällt mir da jetzt nicht ein.
Delphi-Quellcode:
glDC := CreateCompatibleDc(0);
SelectObject(glDC, MeinÜbergebenesBitmap);
PS:
Bitmap erstellen..

Delphi-Quellcode:
    if gBin.UsePlugin then
    begin
      sFile := SpriteResPath + 'plugin.png';
      if FileExists(sFile) then
        gSprDisplayC.GI_SetFromFile(HSprDisplayC, PWideChar(sFile))
    end
    else
    gSprDisplayC.GI_SetFromFile(HSprDisplayC, gG.PhoneBackground);
Dieses wird in meiner Lib intern gespeichert und kann damit zurückgeholt werden..
Mein Container und dessen Handle mit dem das Bitmap erstellt wurde. (Typ Bitmap)

gSprDisplayC.GI_GetProperty(HSprDisplayC, GI_BITMAP);

Jetzt übergeben ich das an meinen BassVis Wrapper..
Delphi-Quellcode:
          mExec.Pluginfile := PAnsiChar(Filename);
          mExec.SON_ConfigFile := PAnsiChar(PluginDir + 'vis.ini');
          mExec.SON_UseOpenGL := true;
          mExec.SON_ParentHandle := HSprDisplayC;
          mExec.SON_ViewportWidth := 1024;
          mExec.SON_ViewportHeight := 800;
          mExec.SON_ShowPrgBar := false;
          mExec.SON_ShowFPS := false;
          mExec.SON_UseCover := false;
          mExec.SON_PaintHandle := gSprDisplayC.GI_GetProperty(HSprDisplayC, GI_BITMAP); // hier das Bitmap
          mExec.Left := 0;
          mExec.Top := 0;
          mExec.Width := Rect.Right;
          mExec.Height := Rect.Bottom;
Delphi-Quellcode:
        Base.VisHandle := BASSSoVisAPI.SONIQUEVIS_CreateVis(Param^.PluginFile,
                                                    Param^.SON_ConfigFile,
                                                    Param^.Left,
                                                    Param^.Top,
                                                    Param^.Width,
                                                    Param^.Height,
                                                    Param^.SON_ParentHandle,
                                                    Param^.SON_ViewportWidth,
                                                    Param^.SON_ViewportHeight,
                                                    Param^.SON_ShowPrgBar,
                                                    Param^.SON_ShowFPS,
                                                    Param^.SON_UseCover,
                                                    Param^.SON_PaintHandle,
                                                    Param^.SON_UseOpenGL);
In der DLL erstelle ich das DC

Delphi-Quellcode:
function TBASSSoVis.IntMeinGL(WinHandle: HWND): BOOL;
var
  IntI, IntJ: integer;

begin
  // OpenGL-Funtionen initialisieren
  Result := False;

  try
    LastWidth := 0;
    LastHeight := 0;

    if not InitOpenGL then
      Halt;

    glDC := CreateCompatibleDc(GetDC(WinHandle)); // hier mein DC
nur damit ich über CreateRenderingContext die richtigen Flags bekomme.

Und nun beim rendern vor glClearColor..
Delphi-Quellcode:
        if VisRenderThread.PaintHandle <> 0 then
        begin
          glDC := CreateCompatibleDc(GetDC(VisRenderThread.ParentHandle));
          SelectObject(glDC, VisRenderThread.PaintHandle);
        end;
Was wird gerendert? Nichts!

Nebenbei gelöscht werden darf das Bitmap in meinem Wrapper nicht der ist nicht der Eigentümer davon das ist mein Container mit dem es erstellt wurde
der gibt das beim beenden wieder frei.

gruss

Geändert von EWeiss (24. Jun 2019 um 14:35 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#6

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 25. Jun 2019, 15:20
Sorry das ich das nach 24 Stunden nochmal hoch pushe.. Hat noch jemand eine Idee?
Informationen sollten ja genug vorhanden sein

Das mit dem Flag "PFD_DRAW_TO_BITMAP" kann ich mir abschminken ist Software Rendering und uninteressant..
Frage mich nur warum man so etwas in einer Bibliothek noch drin lässt wenn es nichts taugt. Hmmmm

gruss

Geändert von EWeiss (26. Jun 2019 um 00:05 Uhr)
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
635 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#7

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 28. Jun 2019, 13:46
So sollte es gehen:

Delphi-Quellcode:
unit glHelper;

interface

uses
   Windows,
   graphics,
   dglOpenGl;

type
   TGlHelper = class
   private
      function GetGlBitmap(aWidth, aHeight: integer): TBitmap;
   protected
      procedure RenderSceneGL; virtual;
   end;

implementation

function TGlHelper.GetGlBitmap(aWidth, aHeight: integer): TBitmap;

type
   ByteArray = array [0 .. 0] of byte;
   pByteArray = ^ByteArray;

var
   lDataSize: Cardinal;
   lFrameBufferid: GLuint;
   lRenderbufferId: GLuint;
   lActViewtexure: GLuint;
   lData: Pointer;

   Y, X, x4: integer;
   pSrc, pDest: pByteArray;

begin
   result := nil;
   lDataSize := aWidth * aHeight * 4;
   if lDataSize > 0 then
      begin
  // Prepare fbo
         glDrawBuffer(GL_BACK);
         glGenFramebuffers(1, @lFrameBufferid);
         glBindFramebuffer(GL_FRAMEBUFFER, lFrameBufferid);

         glGenRenderbuffers(1, @lRenderbufferId);
         glBindRenderbuffer(GL_RENDERBUFFER, lRenderbufferId);

         glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, aWidth, aHeight);
         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, lRenderbufferId);

         GLGenTextures(1, @lActViewtexure);
         GLBindTexture(GL_TEXTURE_2D, lActViewtexure);
         GLTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
         GLTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         GLTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, aWidth, aHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);

         GLFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, lActViewtexure, 0);

         glBindFramebuffer(GL_FRAMEBUFFER, lFrameBufferid);
         GLViewPort(0, 0, aWidth, aHeight);


  // render the scene part

         RenderSceneGL;
         GLFinish;

         glDrawBuffer(gl_Front);

         glBindRenderbuffer(GL_FRAMEBUFFER, 0);
         GLDeleteRenderbuffers(1, @lRenderbufferId);
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
         GLDeleteFramebuffers(1, @lFrameBufferid);

         lData := AllocMem(lDataSize);
         try
            GLGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, lData);
            GLBindTexture(GL_TEXTURE_2D, 0);
            GLDeleteTextures(1, @lActViewtexure);
      // Prepare the Bitmap

            result := TBitmap.Create;
            result.PixelFormat := pf32bit;
            result.Width := aWidth;
            result.Height := aHeight;

            pSrc := @pByteArray(lData)[aWidth * 4 * (aHeight - 1)];
            for Y := 0 to aHeight - 1 do
               begin
                  pDest := result.ScanLine[Y];
                  for X := 0 to aWidth - 1 do
                     begin
                        x4 := X * 4;
                        pDest[x4 + 0] := pSrc[x4 + 2];
                        pDest[x4 + 1] := pSrc[x4 + 1];
                        pDest[x4 + 2] := pSrc[x4 + 0];
                        pDest[x4 + 3] := pSrc[x4 + 3];
                     end;
                  Dec(pSrc, aWidth * 4);
               end;
         finally
            FreeMem(lData);
         end;
      end;
end;

procedure TGlHelper.RenderSceneGL;
begin

end;

end.
Fritz Westermann
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#8

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 28. Jun 2019, 17:24
Hi Fritz..
Danke für deine Mühe werde es mal testen.

Verstehe nur nicht wie ich das in meinen Buffer portieren soll
Delphi-Quellcode:
          glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, StretchWidth, StretchHeight, GL_BGRA,
             GL_UNSIGNED_BYTE, VisInfo^.VisBuf);
Ich werde mal meinen Quelltext abändern der nur den einen Plugintyp unterstützt und dir den Source davon mal schicken wenn du möchtest.
Ohne Beispiel mit Quelltext wird das schwierig.

gruss

Geändert von EWeiss (28. Jun 2019 um 18:16 Uhr)
  Mit Zitat antworten Zitat
EWeiss
(Gast)

n/a Beiträge
 
#9

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 28. Jun 2019, 20:29
@Fritz.. Habe die DLL und ein Beispiel Projekt zum testen der DLL fertig..
Wenn du zeit und Lust dazu hast kann ich es gerne hochladen vielleicht kannst du mir das dann implementieren?

Ich weis leider nicht wie ich das alles zusammen bringen soll. (FBO keinerlei Erfahrung.)
Wir müssen dann nur ein Bitmap aus der Anwendung an die DLL schicken auf der dann gerendert werden soll.. (HBitmap also das Handle sollte doch reichen oder?)
wenn du Interesse daran hast werde ich das noch implementieren so das du dich damit nicht rumschlagen must.

gruss

Geändert von EWeiss (11. Jul 2019 um 15:58 Uhr)
  Mit Zitat antworten Zitat
Fritzew

Registriert seit: 18. Nov 2015
Ort: Kehl
635 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#10

AW: Direkt auf Bitmap zeichnen (OpenGL)

  Alt 28. Jun 2019, 21:39
Mache ich dir gerne, kommt im Moment etwas auf die Temperaturen an... 😄
Fritz Westermann
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 06:29 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf