Ich stand kürzlich vor dem Problem dass ich von meiner OpenGL Form einem "Screenshot" machen wollte und ich habe im Internet nichts wirklich brauchbares Gefunden, bis auf dass Man
Also habe ich so lange hin und her gebastelt bis ich zu folgendem Ergebnis gekommen bin. Das möchte ich hier präsentieren damit du nicht so lange suchen und probieren musst wie ich.
Start:
Wir brauchen also eine OpenGL-Control
Das OpenGL-Fenster muss funktionieren und alle entsprechenden Imports müssen vorhanden sein.
Zunächst die Paint-Routine unserer OpenGL-Form in meinem Fall
Wie die Objekte gezeichnet werden ist für den Screenshot irrelevant. Die Funktion kann am einfachsten getestet werden indem man den Hintergrun zum Beispiel Rot färbt.
Der eigentliche "Screenshot":
Wichtig! Diese Einträge müssen ganz ans Ende der Paint-Routine damit auch alles in der Aufnahme enthalten ist!
Wir brauchen zunächst ein Bitmap Objekt der selben Größe wie das GL-Control.
Dann brauchen wir ein Objekt das die BitmapData an sich enthält in der Größe des GL-Control und im Pixelformat das wir gerne haben möchten.
Jetzt kommt schon das
Dazu wird in OpenGL das Pixelformat BGR verwendet, UnsignedByte erlären sich von selbst und am Schluss Ein Pointer auf das Objekt
Nun einfach die Bits aus dem Datenobjekt ziehen.
Damit das Bild nicht auf dem Kopf steht müssen wir es ein Mal entlang der V-Achse (hier Y) flippen.
(Wer einen Spiegelungseffekt erreichen will kann das Bild hier schon entlang der U-Achse (hier X) Spiegeln)
Und schon ist unsere Bitmap fertig um verwendet zu werden, hier in einer einfachen Picturebox.
Da der "Screenshot" hier ja schon aufgenommen wurde kann innerhalb dieses Frames die Scene noch verändert werden, was dann keinen Einfluss auf das aufgenommene Bild hat.
Und jetzt nochmal alles zusammengefasst:
Und so sieht das dann bei mir aus mit einem einfachen Gitter:
Jetzt bin ich gespannt auf eure Fragen und Anregungen
GL.ReadPixels
verwenden kann.Also habe ich so lange hin und her gebastelt bis ich zu folgendem Ergebnis gekommen bin. Das möchte ich hier präsentieren damit du nicht so lange suchen und probieren musst wie ich.
Start:
Wir brauchen also eine OpenGL-Control
GLMain
und eine Picturebox PBScreenshot
.Das OpenGL-Fenster muss funktionieren und alle entsprechenden Imports müssen vorhanden sein.
Zunächst die Paint-Routine unserer OpenGL-Form in meinem Fall
GlMain.Paint
.Wie die Objekte gezeichnet werden ist für den Screenshot irrelevant. Die Funktion kann am einfachsten getestet werden indem man den Hintergrun zum Beispiel Rot färbt.
Der eigentliche "Screenshot":
Wichtig! Diese Einträge müssen ganz ans Ende der Paint-Routine damit auch alles in der Aufnahme enthalten ist!
Wir brauchen zunächst ein Bitmap Objekt der selben Größe wie das GL-Control.
Dann brauchen wir ein Objekt das die BitmapData an sich enthält in der Größe des GL-Control und im Pixelformat das wir gerne haben möchten.
Jetzt kommt schon das
ReadPixel
startend in der obenren linken Ecke bei Punkt(0,0) wieder in der Größe des GL-Controls.Dazu wird in OpenGL das Pixelformat BGR verwendet, UnsignedByte erlären sich von selbst und am Schluss Ein Pointer auf das Objekt
Data
in das wir die Pixelinformationen speichern wollen.Nun einfach die Bits aus dem Datenobjekt ziehen.
Damit das Bild nicht auf dem Kopf steht müssen wir es ein Mal entlang der V-Achse (hier Y) flippen.
(Wer einen Spiegelungseffekt erreichen will kann das Bild hier schon entlang der U-Achse (hier X) Spiegeln)
Und schon ist unsere Bitmap fertig um verwendet zu werden, hier in einer einfachen Picturebox.
Da der "Screenshot" hier ja schon aufgenommen wurde kann innerhalb dieses Frames die Scene noch verändert werden, was dann keinen Einfluss auf das aufgenommene Bild hat.
Und jetzt nochmal alles zusammengefasst:
VB.NET-Quellcode
- Private Sub GlMain_Paint(sender As Object, e As PaintEventArgs) Handles GlMain.Paint
- '... Code für das Zeichen der 3D-Objekte
- Dim bmp As New Bitmap(GlMain.ClientSize.Width, GlMain.ClientSize.Height)
- Dim Data As Imaging.BitmapData = bmp.LockBits(GlMain.ClientRectangle, Imaging.ImageLockMode.WriteOnly, Imaging.PixelFormat.Format24bppRgb)
- GL.ReadPixels(0, 0, GlMain.ClientSize.Width, GlMain.ClientSize.Height, PixelFormat.Bgr, PixelType.UnsignedByte, Data.Scan0)
- bmp.UnlockBits(Data)
- bmp.RotateFlip(RotateFlipType.RotateNoneFlipY)
- PBTexture.Image = bmp
- End Sub
Und so sieht das dann bei mir aus mit einem einfachen Gitter:
Jetzt bin ich gespannt auf eure Fragen und Anregungen
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()