2012-04-12 12 views
0

Wie kann ich Pixel von einem einfachen Byte-Array in eine OpenGl-Textur hochladen?glTexImage2D + byte []

Ich benutze glTexImage2D und alles, was ich bekomme, ist ein weißes Rechteck anstelle einer pixeligen Textur. Der 9. Parameter (32-Bit-Zeiger auf die Pixeldaten) ist IMO das Problem. Ich habe dort viele Parametertypen ausprobiert (byte, ref-Byte, byte [], ref-Byte [], int & IntPtr + Marshall, out-Byte, out-Byte [], Byte *). glGetError() gibt immer GL_NO_ERROR zurück. Es muss etwas passieren, das ich falsch mache, weil es nie irgendwelche Kauderwelsch Pixel sind. Es ist immer weiß. glGenTextures funktioniert korrekt. Die erste ID hat wie immer in OpenGL den Wert 1. Und ich zeichne farbige Linien ohne Probleme. Also stimmt etwas nicht mit meiner Texturierung. Ich habe die Kontrolle über den DllImport. So kann ich bei Bedarf die Parametertypen ändern.

GL.glBindTexture(GL.GL_TEXTURE_2D, id); 
int w = 4; 
int h = 4; 
byte[] bytes = new byte[w * h * 4]; 
for (int i = 0; i < bytes.Length; i++) 
    bytes[i] = (byte)Utils.random(256); 
GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, w, h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, bytes); 


[DllImport(GL_LIBRARY)] public static extern void glTexImage2D(uint what, int level, int internalFormat, int width, int height, int border, int format, 
      int type, byte[] bytes); 
+0

Woran denken Sie, dass das Hochladen des Bildes das Problem ist? –

+0

Wie wird ein .NET-Byte-Array an eine C-API-Funktion gemanaged? Ihr Kommentar "Ich habe die Kontrolle über den DllImport" schlägt vor, dass Sie OpenTK oder eine andere vorgefertigte OpenGL-Bindung nicht verwenden. Wie sieht der Code aus? –

+0

Was könnte es dann sein? Ich zeichne es mit GL_QUADS, aber es füllt es immer mit meinem aktuellen glColor() (weiß). Ich binde die Textur-ID und aktiviere GL_TEXTURE_2D. – miniMe

Antwort

3

Ein häufiger Fehler ist, ändern nicht die MIN-Filter, da der Standard mipmapped ist, die Texturen unvollständig macht. Tun Sie dies:

GL.glBindTexture(GL_TEXTURE_2D, id); 
GL.glTexParameteri(GL_TEXTURE_2D, GL_MIN_FILTER, GL_NEAREST); 

Dann zeichnen Sie die Textur.

+0

Ok thx Matias, jetzt sehe ich ETWAS. Jetzt kann ich meine Byte [] Pixel nach oben schicken und einige sichtbare Änderungen vornehmen. Ich habe immer noch ein paar Fehler. Vielleicht muss ich die Bytes irgendwie noch marshallen? Ich habe meinen dllimport dort oben gepostet. – miniMe

1

Eine Textur, die weiß bleibt, obwohl etwas hochgeladen wurde, zeigt an, dass nicht alle Mipmap-Ebenen korrekt hochgeladen wurden oder die Filtereinstellungen nicht korrekt festgelegt wurden.

Von Interesse ist dann

glTexParameteri(GL_TEXTURE_..., GL_MIN_FILTER, GL_...); 

Mit GL_NEAREST oder GL_LINEAR Mipmapping zu deaktivieren. Das Mipmapping ist standardmäßig aktiviert.

Die andere wichtige Sache ist, die Struktur der Daten vor dem Hochladen festzulegen, d. H. GlTexImage aufzurufen. Verwenden Sie dazu die Funktion glPixelStorei, um die Parameter GL_UNPACK _... einzustellen. Sie müssen Dinge wie Ausrichtung, Schritt und so weiter einstellen. Ich verweise Sie auf die Dokumentation.

0

Ihre P/Invoke-Deklaration ist falsch.

Die kurze Antwort lautet:

[System.Runtime.InteropServices.DllImport(Library, EntryPoint = "glTexImage2D", ExactSpelling = true)] 
internal extern static void glTexImage2D(int target, int level, int internalformat, Int32 width, Int32 height, int border, int format, int type, IntPtr pixels); 

Diese P/Invoke Erklärung ein sicherer (nicht direkt Zeiger verwenden, aber IntPtr).

Das Problem ist die .NET-Speicherverwaltung. Speicherblöcke sind nicht auf eine bestimmte Speicheradresse festgelegt: Der Garbage Collector (GC) kann Speicher überall frei verschieben (z. B. kann er einen Stapelspeicher im Heapspeicher verschieben und umgekehrt).

In der Tat, was Sie brauchen, ist der .NET GC zu sagen, dass der Speicher nicht verschoben werden soll. Um dies zu tun, verwenden Sie die feste Anweisung oder andere Garbage Collector bezogene Methode.

Zum Beispiel:

public static void TexImage2D(int target, int level, int internalformat, Int32 width, Int32 height, int border, int format, int type, object pixels) { 
    GCHandle pp_pixels = GCHandle.Alloc(pixels, GCHandleType.Pinned); 
    try { 
     if  (Delegates.pglTexImage2D != null) 
      Delegates.pglTexImage2D(target, level, internalformat, width, height, border, format, type, pp_pixels.AddrOfPinnedObject()); 
     else 
      throw new InvalidOperationException("binding point TexImage2D cannot be found"); 
    } finally { 
     pp_pixels.Free(); 
    }   
} 

Der Objektparameter der TexImage2D Funktion mit einem beliebigen Anordnung von Daten verwendet werden soll (diese Objekte die Array Klasse Implementierung (das heißt, byte [], short [], int [] und so weiter)

Wesentlichen über den Code auf dem GC sagen. nehmen sie die Adresse von Pixel, und bewegen sich nicht es bis ich rufen Free() auf dem Speicherpunkt.

Usin die feste Aussage ist eine weitere Option, erfordert aber eine unsichere P/Invoke Erklärung und es ist ein wenig ausführlicher im Code zu verwenden (für jeden Anruf müssen Sie eine unsichere und Fest Anweisungen definieren).

+0

Das obige Problem kann durch Hinzufügen der Zeile GL.glTexParameteri (GL_TEXTURE_2D, GL_MIN_FILTER, GL_NEAREST); Weiß jemand, warum sonst die Textur weiß wäre? In meinem Projekt ging es wieder auf Weiß und ich stellte alle 4 Texparameter ein. – miniMe

Verwandte Themen