ich beschäftige mich derzeit mit OpenGL und bin nun beim Texture Mapping angekommen. Zum Einstieg habe ich mich daran gemacht, einfach nur ein zur Laufzeit erzeugtes, quadratisches Image als Textur auf ein OpenGL-Quad zu legen. Dabei ist mir aufgefallen, dass zwischen dem Bild und der Textur leichte Farbunterschiede bestehen. Da meine Grafikarte nur sperrlich auf 3D ausgelegt ist, bin ich mir nun nicht sicher, ob es an ihr oder an meiner möglicherweise falschen Handhabung von OpenGL-Befehlen liegt. Hier mal ein Beispielcode:
Code: Alles auswählen
; ; - OpenGL-Include
; XIncludeFile "OpenGL.pbi"
; - verwendete OpenGL-Konstanten und -Funktionen
#GL_TEXTURE_2D = $0DE1
#GL_TEXTURE_MAG_FILTER = $2800
#GL_TEXTURE_MIN_FILTER = $2801
#GL_NEAREST = $2600
#GL_LINEAR = $2601
#GL_RGB8 = $8051
#GL_RGBA8 = $8058
#GL_RGBA = $1908
#GL_RGB = $1907
#GL_UNSIGNED_BYTE = $1401
#GL_COLOR_BUFFER_BIT = $00004000
#GL_DEPTH_BUFFER_BIT = $00000100
#GL_MODELVIEW = $1700
#GL_PROJECTION = $1701
#GL_VERTEX_ARRAY = $8074
#GL_TEXTURE_COORD_ARRAY = $8078
#GL_DOUBLE = $140A
#GL_FLOAT = $1406
#GL_TRIANGLE_STRIP = $0005
Import "Opengl32.lib"
glEnable_(a.l) As "_glEnable@4"
glGenTextures_(a.l,b.l) As "_glGenTextures@8"
glBindTexture_(a.l,b.l) As "_glBindTexture@8"
glTexImage2D_(a.l,b.l,c.l,d.l,e.l,f.l,g.l,h.l,i.l) As "_glTexImage2D@36"
glClear_(a.l) As "_glClear@4"
glClearColor_(a.f,b.f,c.f,d.f) As "_glClearColor@16"
glMatrixMode_(a.l) As "_glMatrixMode@4"
glLoadIdentity_() As "_glLoadIdentity@0"
glOrtho_(a.d,b.d,c.d,d.d,e.d,f.d) As "_glOrtho@48"
glTranslatef_(a.f,b.f,c.f) As "_glTranslatef@12"
glEnableClientState_(a.l) As "_glEnableClientState@4"
glVertexPointer_(a.l,b.l,c.l,d.l) As "_glVertexPointer@16"
glTexCoordPointer_(a.l,b.l,c.l,d.l) As "_glTexCoordPointer@16"
glDrawArrays_(a.l,b.l,c.l) As "_glDrawArrays@12"
glDisableClientState_(a.l) As "_glDisableClientState@4"
EndImport
EnableExplicit
; - Beispiel - Verfälschung der Texturfarben
If OpenWindow(0, 0, 0, 800, 600, "OpenGL Texturbeispiel - Farbverfälschung", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
; - Variablen definieren
Define hWnd.l, Width.l, Height.l, hDC.l, hRC.l
Define PixelFormat.PIXELFORMATDESCRIPTOR, iPixelFormat.l
Define TextureID.l, ImageID.l
Define TerminateProgram.b
hWnd = WindowID(0)
Width = WindowWidth(0)
Height = WindowHeight(0)
hDC = GetDC_(hWnd)
; - Pixelformat des DC
PixelFormat\nSize = SizeOf(PIXELFORMATDESCRIPTOR)
PixelFormat\nVersion = 1
PixelFormat\dwFlags = #PFD_SUPPORT_OPENGL | #PFD_DOUBLEBUFFER | #PFD_DRAW_TO_WINDOW
PixelFormat\iPixelType = #PFD_TYPE_RGBA
PixelFormat\cColorBits = 32
PixelFormat\cDepthBits = 16
PixelFormat\iLayerType = #PFD_MAIN_PLANE
iPixelFormat = ChoosePixelFormat_(hDC, PixelFormat)
; - dieses PixelFormat dann dem DC zuweisen
SetPixelFormat_(hDC, iPixelFormat, PixelFormat)
; - OpenGL-RenderContext
hRC = wglCreateContext_(hDC)
wglMakeCurrent_(hDC, hRC)
; - (2D-)Texturen in OpenGL aktivieren
glEnable_(#GL_TEXTURE_2D)
; - Farbtiefe des Bildes festlegen
#Color_Depth = 24
; - Bild zeichnen, dass als Textur verwendet werden wird
ImageID = CreateImage(#PB_Any, 512, 512, #Color_Depth)
If StartDrawing(ImageOutput(ImageID)) <> 0
Box(0, 0, ImageWidth(ImageID), ImageHeight(ImageID), RGB(200, 200, 200))
Box(20, 20, ImageWidth(ImageID) - 40, ImageHeight(ImageID) - 40, RGB(255, 255, 255))
Box((ImageWidth(ImageID) - 100) / 2, (ImageHeight(ImageID) - 100) / 2, 100, 100, RGB(100, 100, 240))
StopDrawing()
EndIf
; - Texturnamen generieren
glGenTextures_(1, @TextureID)
If glBindTexture_(#GL_TEXTURE_2D, TextureID)
; - Variablen definieren
Define ImageDC.l
Define ImageBufferSize.l, *ImageBuffer, bmi.BITMAPINFO
ImageDC = StartDrawing(ImageOutput(ImageID))
If ImageDC <> 0
; - Speicherbereich reservieren
ImageBufferSize = ImageWidth(ImageID) * ImageHeight(ImageID) * #Color_Depth / 8
*ImageBuffer = AllocateMemory(ImageBufferSize)
; - Headerdaten festlegen
bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
bmi\bmiHeader\biWidth = ImageWidth(ImageID)
bmi\bmiHeader\biHeight = ImageHeight(ImageID)
bmi\bmiHeader\biPlanes = 1
bmi\bmiHeader\biBitCount = #Color_Depth
bmi\bmiHeader\biCompression = #BI_RGB
; - Bilddaten aus dem Speicher erfassen
GetDIBits_(ImageDC, ImageID(ImageID), 0, ImageHeight(ImageID), *ImageBuffer, bmi, #DIB_RGB_COLORS)
StopDrawing()
; - Struktur-BGRA
Structure BGRA
b.c
g.c
r.c
a.c
EndStructure
; - Pointer auf den aktuellen Pixel/Farbwert
Define *Pixel.BGRA, i.l
; - Farben liegen im BGRA vor -> für glTexImage2D_() wird aber RGBA benötigt
For i = 0 To ImageBufferSize - 1 Step #Color_Depth / 8
; - Farbwert auslesen
*Pixel = *ImageBuffer + i
; - B- und R-Wert vertauschen
Swap *Pixel\b, *Pixel\r
Next i
EndIf
; - wenn die Farb-Tiefe 24 Bit beträgt
If #Color_Depth = 24
; - aus den obigen Bitmap-Daten eine OpenGL-Textur erstellen
glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGB8, ImageWidth(ImageID), ImageHeight(ImageID), 0, #GL_RGB, #GL_UNSIGNED_BYTE, *ImageBuffer)
; - sonst, wenn sie 32 Bit beträgt
ElseIf #Color_Depth = 32
; - aus den obigen Bitmap-Daten eine OpenGL-Textur erstellen
glTexImage2D_(#GL_TEXTURE_2D, 0, #GL_RGBA8, ImageWidth(ImageID), ImageHeight(ImageID), 0, #GL_RGBA, #GL_UNSIGNED_BYTE, *ImageBuffer)
EndIf
; - Texturfilter setzen
glTexParameteri_(#GL_TEXTURE_2D, #GL_TEXTURE_MIN_FILTER, #GL_NEAREST)
; - Vertex- und Texel-Array definieren
Dim Vertex.f(11)
Dim Texel.f(7)
; - Vertex-Array für QUAD
Vertex(0) = 0 : Vertex(1) = ImageHeight(ImageID) : Vertex(2) = -1
Vertex(3) = ImageWidth(ImageID) : Vertex(4) = ImageHeight(ImageID) : Vertex(5) = -1
Vertex(6) = 0 : Vertex(7) = 0 : Vertex(8) = -1
Vertex(9) = ImageWidth(ImageID) : Vertex(10) = 0 : Vertex(11) = -1
; - Texel-Array
Texel(0) = 0.0 : Texel(1) = 1.0
Texel(2) = 1.0 : Texel(3) = 1.0
Texel(4) = 0.0 : Texel(5) = 0.0
Texel(6) = 1.0 : Texel(7) = 0.0
EndIf
Repeat
Repeat
Define EventID.l = WaitWindowEvent(10)
Select EventID
Case #PB_Event_CloseWindow
TerminateProgram = #True
EndSelect
Until (EventID = 0 Or TerminateProgram = #True)
; - Buffer leeren
glClearColor_(200/255, 200/255, 200/255, 1)
glClear_(#GL_COLOR_BUFFER_BIT | #GL_DEPTH_BUFFER_BIT)
; - Projektionsmatrix auswählen
glMatrixMode_(#GL_PROJECTION)
glLoadIdentity_()
; - orthogonale Projektion verwenden
glOrtho_(0, Width, 0, Height, 1.0, 1000.0)
; - ModelView auswählen
glMatrixMode_(#GL_MODELVIEW)
glLoadIdentity_()
; - in das lokale Koordinatensystem des Bildes übergehen
glTranslatef_((Width - ImageWidth(ImageID)) / 2, (Height - ImageHeight(ImageID)) / 2, 0)
; - OpenGL mitteilen, dass Koordinaten-Arrays für Vertices und Texturen verwendet werden
glEnableClientState_(#GL_VERTEX_ARRAY)
glEnableClientState_(#GL_TEXTURE_COORD_ARRAY)
; - OpenGL-Quad rendern, welches das Sprite repräsentiert
glBindTexture_(#GL_TEXTURE_2D, TextureID)
glVertexPointer_(3, #GL_FLOAT, 0, @Vertex(0))
glTexCoordPointer_(2, #GL_FLOAT, 0, @Texel(0))
glDrawArrays_(#GL_TRIANGLE_STRIP, 0, 4)
; - OpenGL mitteilen, dass die Koordinaten-Arrays für Vertices und Texturen nicht mehr benötigt werden
glDisableClientState_(#GL_VERTEX_ARRAY)
glDisableClientState_(#GL_TEXTURE_COORD_ARRAY)
; - Front- und Back-Buffer vertauschen
SwapBuffers_(hDC)
Until TerminateProgram = #True
; - Textur löschen
glDeleteTextures_(1, @TextureID);
; - RenderContext löschen
wglMakeCurrent_(#Null, #Null)
wglDeleteContext_(hRC)
ReleaseDC_(hWnd, hDC)
EndIf
End
RGB(200, 200, 200)
RGB(255, 255, 255)
RGB(100, 100, 240)
Mache ich aber vom obigen, laufenden Programm einen Screenshot und lese die Farbwerte aus, dann sind diese 3 Quadrate (leicht) anders gefärbt, nämlich mit:
RGB(204, 204, 204)
RGB(255, 255, 255) -> (weiß und schwarz werden korrekt dargestellt)
RGB(102, 102, 255)
Wäre schön, wenn jemand den obigen Code mal testen könnte und mal schauen würde, ob bei ihm diese Farbverfäschung auch auftaucht. Falls das bei euch auch auftritt: Was mache ich oben falsch? Der Knackpunkt scheint mir der glTexImage2D_() Befehl zu sein, aber da entdecke ich keinen Fehler ...
Vielen Dank!
Grüße,
Christian