# LWJGL IllegalArgument Exception bei glTexImage2D



## Runtime (2. Feb 2012)

Hallo zusammen,

ich bekomme wie im Titel beschrieben von LWJGL eine IllegalArgumentException geworfen mit der Message 
	
	
	
	





```
Number of remaining buffer elements is 1512756, must be at least 3145728. Because at most 3145728 elements can be returned, a buffer with at least 3145728 elements is required, regardless of actual returned element count
```
, wobei ich diese ungerechtfertigt finde weil:
GPUs, die ARB_texture_non_power_of_two nicht unterstützen müssen zwingend eine Texturgrösse haben, bei der Breite und Höhe eine Potenz von 2 ist. Um aber trotzdem ein Bild hochzuladen, dessen Breite und Höhe keine Potenz von 2 sind, hab ich mit 
	
	
	
	





```
glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, width)
```
 die Breite eingegrenzt. LWJGL will aber trotzdem die volle Anzahl bytes, auch wenn es diese nicht bräuchte, da ich ja nur ein Ausschnitt laden will.Gibts irgend einen (LWJGL) Weg, dieser Exception aus dem Weg zu gehen?

LG Runtime


----------



## Kr0e (2. Feb 2012)

Ich bräuchte für eine qualifizierte Aussage schon etwas Code. So aus dem Stehgreif könnte es viele Ursachen geben.

Aber mal aus Neugier: Unterstützen diese Fähigkeit (Laden von Texturen ohne zwingend als 2er-Potenz) nicht so ziemlich alle Grafikkarten mittlerweile ? Ich meine ,wenn du gezwungen bist, ok dann seh ichs ein. Aber jenachdem machst du dir vlt zuviel Stress...


----------



## Evil-Devil (2. Feb 2012)

Runtime, du musst das entsprechende Checking deaktivieren.

Siehe dazu im Wiki den NoCheck Parameter.
LWJGL Hidden Switches - LWJGL

Allerdings solltest du darauf achten das dein Programm nicht nur bei dir sondern auch anderen läuft. Das kann bei deaktivierten Checks durchaus auf die Schnauze fallen bzw. ein fehlerhaftes Verhalten provozieren.


----------



## Runtime (2. Feb 2012)

Kr0e hat gesagt.:


> Ich bräuchte für eine qualifizierte Aussage schon etwas Code. So aus dem Stehgreif könnte es viele Ursachen geben.



Stimmt! Da hab ich was vergessen :S Ich denke folgende Erklärung sollte reichen:
Die Exception wird geworfen, weil der DataBuffer, der übergeben wird kleiner als width * height * numChannels ist, weil ja nicht das gesamte Bild gefüllt werden soll. Deshalb meckert LWJGL, es habe zu wenig Daten, obwohl es eigentlich reichen würde.



Kr0e hat gesagt.:


> Unterstützen diese Fähigkeit (Laden von Texturen ohne zwingend als 2er-Potenz) nicht so ziemlich alle Grafikkarten mittlerweile ? Ich meine ,wenn du gezwungen bist, ok dann seh ichs ein. Aber jenachdem machst du dir vlt zuviel Stress...


Der Sinn dieses Codes ist, auf möglichst vielen Computer zu funktionieren zu können, auch wenn diese relativ alt sind, deshalb möchte ich möglichst viele Ausnahmen behandeln und Extensions nutzen.


----------



## Runtime (2. Feb 2012)

Ich hab mal an den Anfang der init-Methode 
	
	
	
	





```
System.setProperty("org.lwjgl.util.NoChecks", "true")
```
 reingeschrieben, aber die Exception tritt noch immer auf.


----------



## Evil-Devil (2. Feb 2012)

Entsprechen deine width* height*bitdepth Werte der Textur Größe oder sind das 2er Potenzen?

Poste am besten das Programm oder den Bereich damit man es nachstellen kann.


----------



## Guest2 (2. Feb 2012)

Moin,

mir ist zugegebenermaßen nicht klar, was Du erreichen möchtest, aber kann es sein das Du eigentlich glTexSubImage2D suchst?

Viele Grüße,
Fancy


----------



## Spacerat (3. Feb 2012)

Runtime hat gesagt.:


> Der Sinn dieses Codes ist, auf möglichst vielen Computer zu funktionieren zu können, auch wenn diese relativ alt sind, deshalb möchte ich möglichst viele Ausnahmen behandeln und Extensions nutzen.


Wäre es dann nicht Klüger, die Bildbreiten und -höhen direkt anzupassen bevor man einen Puffer draus macht?

```
public static BufferedImage reSize(BufferedImage img)
{
	int w = nearestPowerOfTwo(img.getWidth());
	int h = nearestPowerOfTwo(img.getFeight());
	Image rc = new BufferedImage(w, h, img.getType());
	rc.getGraphics().drawImage(img, 0, 0, w, h, null);
	return rc;
}

public static int nearestPowerOfTwo(int value)
{
	int next = nextPowerOfTwo(value);
	int last = lastPowerOfTwo(value);
	return (value - last < next - value)? last : next;
}

public static int lastPowerOfTwo(int value)
{
	return (int) Math.pow(2.0, Math.floor(log10(value) / log10(2)));
}

public static int nextPowerOfTwo(int value)
{
	return (int) Math.pow(2.0, Math.ceil(log10(value) / log10(2)));
}
```
Hier mal ein paar Utility-Methoden dafür.


----------



## Runtime (3. Feb 2012)

@Spacerat
Tut mir leid, ich hab mich verschrieben. Ich übergebe einen nio Buffer, nicht einen DataBuffer :S

@Fancy
Funktioniert glSumImage2D denn auch mit Zahlen, die keine Zweierpotenzen sind? Woher kennt OpenGL dann die tatsächliche Grösse der Textur?

@Evil-Devil
Width & height sind im Beispiel Zweierpotenzen.

Ich kann leider erst am Abend Code posten, da ich Schule hab.


----------



## Evil-Devil (3. Feb 2012)

Öhm, du übergibst OpenGL (LWJGL) die größen einer Zweierpotenzen Tex und willst dann eine NonPowerOfTwo hochladen? Das kann so doch gar nicht gehen. Du müsstet ja den verbleibenden Speicher leer lassen bzw. mit Weiß oder Schwarz füllen. Besser wäre es den Buffer entsprechend anzupassen, keine NPoT Texturen zu verwenden oder die NPot Textur auf eine PoT zu kopieren.


----------



## Spacerat (3. Feb 2012)

Runtime hat gesagt.:


> @Spacerat
> Tut mir leid, ich hab mich verschrieben. Ich übergebe einen nio Buffer, nicht einen DataBuffer :S


Das leuchtet mir ein. Genaugenommen sogar einen DirectBuffer. Auch hier ist wieder so eine Stelle, wo ich auf ein Machwerk von mir hinweisen könnte - http://www.java-forum.org/spiele-multimedia-programmierung/130336-lwjgl-opengl-text.html#post852545. Des Jar-Archiv ist nicht blos für Text, sondern beinhaltet auch einen TexturMaker aus beliebigen Image-Instanzen statt einen auf Dateinamen beruhenden.


----------



## Guest2 (3. Feb 2012)

glTexImage2D setzt eine ganze Textur (der Buffer muss also gleich oder größer als die Textur sein). glTexSubImage2D setzt nur einen Teil einer Textur (der Buffer kann also auch kleiner sein). 

Mit NPOT können beide umgehen. Ab OpenGL 2.0 muss jeder Grafikkartentreiber NPOT Texturen unterstützen. NPOT Texture hilft vielleicht bei der Frage, ob man diese nutzen möchte oder nicht.

(glTexSubImage2D wird (/wurde) gerne genutzt um größere Texturen langsam und stückweise auf die Grafikkarte zu schieben, hat dann ein wenig was von einem "stream". Heute gibt es aber GL_ARB_sync (ab GL 3.2 im "core"), mit dem auch verschiedene GL Threads synchronisiert werden können - ein streamen mit glTexSubImage2D wird dadurch unnötig)  

Viele Grüße,
Fancy


----------



## Runtime (3. Feb 2012)

@Fancy
Wenn ich also glTexSubImage2D aufrufe, woher weiss denn OpenGL wie gross diese Textur ist? Es wird ja nur ein Ausschnitt gezeigt, die Breite und die Höhe der Textur sind damit ja noch nicht definiert.

@Spacerat
Ich könnte für alles, was ich bisher in OpenGL schrieb und schreibe, fremden Code nehmen. Mein Ziel ist nicht die Produktivität, sondern der Lerneffekt und der Spass den ich beim Programmieren habe.

Wie ich es bisher versucht habe:

```
public static Texture createTexture(int width, int height, TextureDataFormat format, int bitDepth, byte[] data) {
        TextureData texData = new TextureData(width, height, format);
        
        int wPower2;
        int hPower2;
        
        if(GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
            wPower2 = width;
            hPower2 = height;
        } else {
            wPower2 = (int) Math.pow(2, Math.ceil(Math.log(width) / Math.log(2)));
            hPower2 = (int) Math.pow(2, Math.ceil(Math.log(height) / Math.log(2)));
            GL11.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, width);
        }
        
        texData.bind();
        
        switch(bitDepth) {
            case 1:
                FloatBuffer palette = InkWaveUtils.wrap(new float[] {0, 1});
                GL11.glPixelMap(GL11.GL_PIXEL_MAP_I_TO_R, palette);
                GL11.glPixelMap(GL11.GL_PIXEL_MAP_I_TO_G, palette);
                GL11.glPixelMap(GL11.GL_PIXEL_MAP_I_TO_B, palette);
                GL11.glPixelMap(GL11.GL_PIXEL_MAP_I_TO_A, palette);

                GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, DATA_TYPES_4BIT[format.numChannels() - 1], wPower2, hPower2,
                        0, GL11.GL_COLOR_INDEX, GL11.GL_BITMAP, InkWaveUtils.wrap(data));
                break;

            case 2:
                GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, DATA_TYPES_8BIT[format.numChannels() - 1], wPower2, 
                        hPower2, 0, DATA_FORMAT[format.numChannels() - 1], GL11.GL_UNSIGNED_BYTE, InkWaveUtils.wrap(convert2to8(data)));
                break;

            case 4:
                GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, DATA_TYPES_4BIT[format.numChannels() - 1], wPower2,
                        hPower2, 0, DATA_FORMAT[format.numChannels() - 1], GL12.GL_UNSIGNED_SHORT_4_4_4_4, InkWaveUtils.wrap(data));
                break;

            case 8:
                GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, DATA_TYPES_8BIT[format.numChannels() - 1], wPower2, 
                        hPower2, 0, DATA_FORMAT[format.numChannels() - 1], GL11.GL_UNSIGNED_BYTE, InkWaveUtils.wrap(data));
                break;

            case 16:
                GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, DATA_TYPES_16BIT[format.numChannels() - 1], wPower2, 
                        hPower2, 0, DATA_FORMAT[format.numChannels() - 1], GL11.GL_UNSIGNED_SHORT, InkWaveUtils.wrap(data));
                break;

            default:
                throw new IllegalArgumentException(bitDepth + " is an unsupported bit depth.");
        }
        return new Texture(texData, width, height);
    }
```


----------



## Spacerat (4. Feb 2012)

Lerneffekt ist gut und schön, der ist ja eigentlich immer da, sogar auch dann, wenn man Fremdcode analysiert bzw analysieren muss, weil nicht dokumentiert. Ich hatte z.B. irgend wann mal gelernt, dass jeder gerne auf Vorhandenes zurückgreift, in Sachen GL ganz speziell, wenn es darum geht Objekte und Bilder der verschiedensten Formate zu lesen und oder zu schreiben. So ist man dann recht schnell dabei und sucht sich einen Wolf nach z.B. Texturladern, die einem letztendlich nie genügen und man es deswegen doch selber macht. Dein Code sieht da nicht anders aus, deine Textur-Klassen lassen jedenfalls darauf schliessen.
[OT]BTW.: Ich weis zwar nicht, was [c]InkWaveUtils.wrap()[/c] bei dir macht, zumindest kann in DirectBuffers nicht "gewrapped" werden. Musste mich dahingehend auch durch dieses Forum "belehren" lassen. LMR.: Du weisst es auch nicht, weil der Texturlader nicht von dir stammt?[/OT]
Aber wie sonst käme man auf die Idee, Texturen anhand einiger ints, einem Datenformat und eines Bytearrays erstellen zu wollen, wo es doch eigentlich auf der Hand liegt (berichtigt mich bitte, wenn ich da falsch liege), sie anhand eines ladbaren Images zu erstellen.
Um z.B. an eines dieser Bytearrays zu gelangen, welches Daten eines bisher nicht unterstützten mit unter auch recht exotischen Datenformates (z.B. TIFF oder gar ACBM/ILBM) liefern soll, lernt man nun mitunter auch noch, fern ab vom eigentlichen Ziel, den Aufbau diverser Grafik- oder gar Objektformate kennen. Schon ist man erneut auf der Suche oder meisselt mal wieder selbst, wie gesagt, fern ab vom Ziel GL (oder Java3D oder JOGL oder ähnliches) lernen zu wollen.
[OT]Ich kenne im übrigen vier verschiedene Lader für WaveFront-Objekte die alle zueinander inkompatibel sind, aber nur einen, der die vier anderen durchaus ersetzen könnte (faktisch tut er dies sogar, bei mir jedenfalls). Ähnliches gilt für Grafik- und Soundformate. Der jeweils zu allen anderen APIs kompatible Dateilader ist Teil einer sauber von jeglichen anderen APIs getrennten und inzwischen exessiv von mir genutzten Datentyperkennung aus eigener Feder (mein erstes und bisher grösstes Projekt). Das mal zum Thema Lerneffekt.[/OT]


----------



## Runtime (4. Feb 2012)

Spacerat hat gesagt.:


> Lerneffekt ist gut und schön, der ist ja eigentlich immer da, sogar auch dann, wenn man Fremdcode analysiert bzw analysieren muss, weil nicht dokumentiert.


Diese Aussage hat schon etwas Wahres, aber wenn man es selbst macht, kann man es sich besser merken und auch besser anwenden.



Spacerat hat gesagt.:


> BTW.: Ich weis zwar nicht, was [c]InkWaveUtils.wrap()[/c] bei dir macht, zumindest kann in DirectBuffers nicht "gewrapped" werden. Musste mich dahingehend auch durch dieses Forum "belehren" lassen. LMR.: Du weisst es auch nicht, weil der Texturlader nicht von dir stammt?


InkWaveUtils ist eine von mir geschriebene Utility Klasse. Wrap ist schon nicht wirklich ein Wrap-Vorgang, sondern es alloziiert einen direkten Buffer mit der entsprechenden Grösse, kopiert das byte-Array rein und setzt die Endianness aus ByteOrder.LITTLE_ENDIAN.



Spacerat hat gesagt.:


> Um z.B. an eines dieser Bytearrays zu gelangen, welches Daten eines bisher nicht unterstützten mit unter auch recht exotischen Datenformates (z.B. TIFF oder gar ACBM/ILBM) liefern soll, lernt man nun mitunter auch noch, fern ab vom eigentlichen Ziel, den Aufbau diverser Grafik- oder gar Objektformate kennen. Schon ist man erneut auf der Suche oder meisselt mal wieder selbst, wie gesagt, fern ab vom Ziel GL (oder Java3D oder JOGL oder ähnliches) lernen zu wollen.


Ich hab gar nie gesagt, dass ich mich nur auf OpenGL konzentrieren möchte, ich denke Datenformate zu kennen ist schon nützlich.

Könntest du noch den Link zu deinem Projekt posten? Ich werde vllt Nutzen daran finden. Wenn ich Code von dir verwende (wenn ich darf) werde ich deinen Namen hinzufügen, aber mir gehts mal darum herauszufinden, wie du das ganze aufgebaut hast.
Btw: Dein Post kann mir nur meine nicht im Forum gestellten Fragen beantworten.


----------



## Spacerat (4. Feb 2012)

Runtime hat gesagt.:


> Könntest du noch den Link zu deinem Projekt posten? Ich werde vllt Nutzen daran finden. Wenn ich Code von dir verwende (wenn ich darf) werde ich deinen Namen hinzufügen, aber mir gehts mal darum herauszufinden, wie du das ganze aufgebaut hast.
> Btw: Dein Post kann mir nur meine nicht im Forum gestellten Fragen beantworten.


Meinst du dieses hier? Oder JGL? Egal... mit dem Link hätte ich in soweit ein Problem, weil es keinen gibt. Als privater Einzelkämpfer entzieht es sich meiner Kenntnis, wo ich meine Projekte sinnvoll veröffentlichen könnte (Okay, man kann googeln und stösst dann vllt. auf Hoster für Webspace und anderes unbekanntes Zeugs, aber man hat keinerlei Möglichkeit ein Projekt zu umwerben bzw. bekannt zu machen). Alles was ich bisher tun kann, ist hier da und dort ein immer aktuelleres Archiv hochladen und den jeweiligen Host (vorzugsweise wäre es eben dieses Forum hier) damit "füllen" aber genau das würde ich gern vermeiden. Im Moment lassen sich meine Projekte entweder nur verwenden oder analysieren, weil sie überwiegend undokumentiert sind. Bei der oben verlinkten Lib würde ein stetes posten schon allein deswegen wenig Sinn machen, weil ständig eine Installations- bzw. Konfigurationsanleitung und eine Anleitung, wie man eigene Codecs schreibt, dabei sein müsste.
Wäre ja mal interessant, welche Fragen du hier im Forum nicht gestellt hast... Ich jedenfalls bin der Ansicht, dass Dateilader, welche auf spezielle APIs zugeschnitten sind, definitiv der falsche Ansatz sind. So wie ich meine, dass es sein sollte manifestiert sich in meinen Porjekten (DataTypesLibrary und JGL). Vllt. beantwortet das ja schon einige von diesen Fragen.


----------



## Runtime (4. Feb 2012)

Dass die beiden Libraries im Grunde unabhängig sein sollen, kann ich nachvollziehen, da IO und Grafik zu unterschiedlich sind. Danke für die Idee mit den DataTypes , das ist die Art System, die ich gesucht hab, ich werde das so durchziehen. Die vorherigen Fragen müssen nur nonoch geklärt werden, dann bin ich vollends zufrieden  und unheimlich dankbar, weil das Projekt schon seit Wochen aus diesem Grund still steht.


----------



## Guest2 (5. Feb 2012)

Bei glTexSubImage definierst Du vorher die Textur ganz normal mit glTexImage2D, dort kannst Du als Buffer auch null übergeben. So wird z.B. nur die linke Hälfte der Textur gesetzt:


```
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width * 2, height, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, (ByteBuffer) null);
        GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, width, height, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, texture);
```

Das skaliert Dir Deine Textur aber nicht auf POT.

Unabhängig davon kannst Du imho davon ausgehen, dass jede Grafikkarte außerhalb eines Museums intern alles als 32Bit RGBA8 darstellt, egal was Du für Parameter setzt. Imho ist es deshalb auch sinnvoll die Java Image Methoden zu nutzen, um Dir das Bild als RGBA zurückgeben zu lassen. BufferedImage.getRGB() gibt genau 32Bit RGBA zurück und berücksichtigt dabei sowohl den Farbraum (sRGB) als auch das ColorModel (TYPE_INT_ARGB). Imho vollkommen stressfrei.

Wenn Du es für sinnvoll hältst, lässt sich das Bild damit auch leicht auf POT skalieren, bevor es dann auf die Grafikkarte geschoben wird.

Viele Grüße,
Fancy


----------



## Runtime (6. Feb 2012)

Ok, das wäre dann alles  Ich bin euch unheimlich dankbar, da das Projekt aufgrund dessen schon einige Wochen still stand.


----------



## Marco13 (6. Feb 2012)

Guest2 hat gesagt.:


> Imho ist es deshalb auch sinnvoll die Java Image Methoden zu nutzen, um Dir das Bild als RGBA zurückgeben zu lassen. BufferedImage.getRGB() gibt genau 32Bit RGBA zurück und berücksichtigt dabei sowohl den Farbraum (sRGB) als auch das ColorModel (TYPE_INT_ARGB). Imho vollkommen stressfrei.



Für jeden Pixel getRGB dürfte ziemlich langsam sein, dann lieber getPixels oder direkt den DataBufferInt-Inhalt holen. Ich meine auch da wären noch ein paar Glitches wegen ARGB vs. RGBA... aber vielleicht täusche ich mich auch.


----------



## Guest2 (6. Feb 2012)

Ich hatte das hier im Sinn: 


```
BufferedImage image = ImageIO.read(inputStream);

[..]

		final int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);
        final IntBuffer texture = BufferUtils.createIntBuffer(pixels.length);
        texture.put(pixels);
        texture.rewind();

[..]

        GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, texture);
```

Dann muss man eigentlich nur noch aufpassen das man entweder das image oder die pixels spiegelt um den Ursprung von oben/links auf unten/links zu bekommen.

Der Weg über das Raster geht natürlich auch (mach ich selber auch oft ), allerdings muss man da ihmo ein wenig vorsichtiger sein, falls der Farbraum des image nicht sRGB ist, sondern z.B. "irgendwas" anderes. Laut JavaDoc berücksichtigt getRGB sowohl ColorModel als auch Farbraum. (Ich hab z.B. keinen Schimmer, wie weit die Werte sonst abweichen, wenn z.B. ein JPG in Adobe Wide RGB eingelesen wird.)

Viele Grüße,
Fancy


----------



## Marco13 (6. Feb 2012)

Oh ja stympt, beim BufferedImage heißt's getRGB, das getPixels war beim Raster ... aber wo da was mit ColorModel oder nicht umgewandelt wird, müßte ich mir auch noch genauer ansehen. Meine Frage resultierte wohl eher aus einem mangelnden Verständnis meinerseits für die _genaue_ Bedeutung der Parameter:


```
void glTexImage2D(GLenum  target,  GLint  level,  GLint  internalFormat,  GLsizei  width,  GLsizei  height,  GLint  border,  GLenum  format,  GLenum  type,  const GLvoid *  data);

// Bei dir:
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, texture);
```

Ich dachte immer, 'internalFormat' wäre das, wie es intern gespeichert wird, und 'format' das, wie es tatsächlich im Datenblock gegeben ist, aber das stimmt wohl so nicht (und die Dokus zu dieser Methode sind meistens total besch^C^C^C^C nur eine Auflistung der akzeptierten Konstanten :autsch: )

Ich dachte: 
- Der type ist GL_UNSIGNED_BYTE, weil das der Typ der einzelnen Komponenten ist (und welche Komponenten es gibt, geht aus dem format/internalFormat hervor). Bei dir ist das jetzt GL_UNSIGNED_INT_8_8_8_8_REV, was ich vorher noch nie gesehen hatte...

- Das format und das internalFormat ist eher eine art "Vereinbarung", wie die übergebenen Daten zu interpretieren sind - und man darf lügen  Man kann also irgendwelche Daten übergeben, und OpenGL interpretiert sie so, wie im 'format' angegeben, und wandelt sie ins 'internalFormat' - die beiden bestimmen also lediglich eine art "Permutation" der echt gegebenen Daten. 

Aber das ist wohl grober Unfug  Werd' wohl nochmal eine Weile websuchen müssen, um eine Definition des Unterschiedes zwischen GL_RGBA8 und GL_RGBA zu finden, und eine Definition von GL_UNSIGNED_INT_8_8_8_8_REV und was genau wo zu stehen hat. Erstaunlich finde ich jetzt nur, dass mit
type = GL_UNSIGNED_BYTE;
internalFormat = GL_RGBA;
format = GL_BGRA;
die ARGB (!)-Daten, die ich aus einem Image hole, richtig angezeigt werden


----------



## Guest2 (6. Feb 2012)

So sehr liegst Du gar nicht daneben! 

Vielleicht hilft:

Image precision
Textures Internal and External

Da stehen dann auch so Feinheiten wie:



			
				http://www.opengl.org/wiki/Textures_-_more hat gesagt.:
			
		

> GL_RGBA8 doesn't truly mean that the GPU will store it as GL_RGBA8. It might actually store it as GL_BGRA8.




Auch hinter dem GL_UNSIGNED_INT_8_8_8_8_REV steckt nicht sonderlich viel. Aus dem getRGB() kommt ARGB und wir wollen BGRA. Das ist genau dasselbe nur eben jeweils 4 Bytes gelesen und von hinten nach vorne interpretiert und genau das macht GL_UNSIGNED_INT_8_8_8_8_REV. 


Viele Grüße,
Fancy


----------



## Guest2 (6. Feb 2012)

Nachtrag:



Marco13 hat gesagt.:


> Erstaunlich finde ich jetzt nur, dass mit
> type = GL_UNSIGNED_BYTE;
> internalFormat = GL_RGBA;
> format = GL_BGRA;
> die ARGB (!)-Daten, die ich aus einem Image hole, richtig angezeigt werden



texture ist ein IntBuffer mit little endian. Deshalb ist GL_UNSIGNED_BYTE und GL_UNSIGNED_INT_8_8_8_8_REV im Ergebnis gleich. Aber stimmt, GL_UNSIGNED_BYTE sollte hier die bessere Wahl sein. Bei einem ByteBuffer muss es allerdings GL_UNSIGNED_INT_8_8_8_8_REV sein.

Viele Grüße,
Fancy


----------



## Spacerat (7. Feb 2012)

@Guest2: Der TO will ja seine Software auf möglichst vielen Rechnern (auch ältere) lauffähig machen (Bemerkenswert, wie ich finde). Deswegen glaube ich kaum, das GL_UNSIGNED_INT_8_8_8_8_REV auch nur annähernd hilfreich ist, denn meines Wissens ist das in GL1.x nicht vorhanden. Ich arbeitete extrem lange (viel zu lange nehm ich an) mit OpenGL1.1, ganz einfach deswegen, weil JOGL dies tat - naja keine Zeit für die Geschichte, warum ich LWJGL nun vorziehe. Deswegen aber existieren in meiner JGL-Lib diese Komponentendreher ebenfalls (benötigen natürlich CPU-Zeit).

Mir drängt sich im übrigen angesichts dieser Massen an Varianten dringende Verständnisfragen auf...

1. Neueren Grakas scheint das Pixelformat ja relativ egal zu sein, deswegen gibt es in OGL nun weitere Formatkonstanten. Sind es auschliesslich die Grakas die andere Formate unterstützen oder springt GL zur Not auch ein, das Format softwareteschnisch (CPU-Zeit) zu ändern, wenn die Graka es nicht unterstützt?
2. läuft ein neueres GL überhaupt auf älterer Hardware? Wenn ja, dann müsste man doch eigentlich nur die OGL-Version auf dem älteren System vorraussetzen und sich während der SW-Entwicklung um diverse Programmiertechniken keinen Kopf mehr machen. Wenn nicht, dürfte man maximal mit OGL1.1 arbeiten und den ganzen aktuelleren "Kram" softwaretechnich lösen - Umgebung erforschen und Methodenaufrufe ggf. umleiten oder selbst implementieren und CPU-Zeit nutzen. Das bringt mich zu...
3. Immer besser werdende Grakas laufen wohl kaum auf älteren Systemen (passt ja schon von der Schnittstelle nicht - PCI-E). Immer besser werdende Grakas benötigen aber auch immer weniger CPU-Zeit, weil sie halt alles selber machen, z.B. Pixelformate von Texturen umwandeln. Benötigen besser werdende Grakas überhaupt noch CPU-Zeit geschweige denn eine wahnsinnig schnelle CPU?
4. Das Bemerkenswerte am Vorhaben des TO ist doch, dass neuere Technologien auf älteren Systemen gar nicht lauffähig sind. Sie mögen zwar funktionieren, aber man hätte unheimlich niedrige Bildwechselfrequenzen vllt. 25fpd (Frames per Decade :lol. @TO: Was genau hast du vor?


----------



## Guest2 (7. Feb 2012)

Viele Fragen und viele relative Antworten: 

1. GL_UNSIGNED_INT_8_8_8_8_REV ist in OpenGL 1.2 definiert. Dank dem anstupser von Marco oben, ist aber aufgefallen, dass dies hier gar nicht nötig ist, da getRGB() ARGB als int[] zurückgibt, welches in einen IntBuffer mit little endian abgelegt werden kann. Bei der Angabe von GL_UNSIGNED_BYTE wird das aber eben auch als BGRA interpretiert und ist damit im Ergebnis gleich zu  GL_UNSIGNED_INT_8_8_8_8_REV.

JOGL unterstützt dieselben OpenGL Profile wie LWJGL (alle aktuellen).

Die gebräuchlichsten (auch älteren) dedizierten Grafikkarten unterstützen entweder OpenGL 3.1 (wenn kein Geometrieshader vorhanden ist), OpenGL 3.3 (wenn er vorhanden ist) oder OpenGL 4.2 (wenn ein Tessellationshader vorhanden ist). Die gebräuchlichsten onbord Grafikkarten unterstützen mindestens OpenGL 2.0.

Theoretisch könnte es noch uralt onbord Grafikkarten geben, welche lediglich OpenGL 1.4 unterstützen. Auf noch älteren Rechnern läuft dann aber vermutlich auch kein Java mehr.

Wenn ein OpenGL Feature in OpenGL spezifiziert ist und der Grafikkartentreiber diese OpenGL Version unterstützt, dann muss das Feature zur Laufzeit zur Verfügung stehen (entweder per Hartware oder per Software). Wenn das Feature als OpenGL Extension spezifiziert wurde, dann kann es zur Laufzeit zur Verfügung stehen, muss aber nicht.

2. Normalerweise wird der Treiber soweit aktualisiert (und stellt damit neuere OpenGL Versionen zur Verfügung) bis andere Anforderungen an die Hartware gestellt werden. Das war bei OpenGL 3.2 der Fall, als der Geometrieshader verpflichtend wurde oder bei OpenGL 4.0 als der Tessellationshader verpflichtend wurde.

3. Bei allem, was mit Grafik zu tun hat, wird die CPU in der Tat immer unwichtiger. Allerdings können heutige Grafikkarten ungeheure Datenmengen verarbeiten. Unter Umständen mehr als in den Speicher der Grafikkarte passt, dann muss die CPU schnell zuarbeiten können. Außerdem führen einige OpenGL Befehle zu einer Synchronisation zwischen CPU und GPU, dann kann die CPU die GPU durchaus ausbremsen.

4. Imho sollte man sich bei einem Projekt mit OpenGL eine realistische Version als Mindestanforderung setzen und dann seinen Renderpfad entsprechend umsetzen. Zu versuchen alles zu unterstützen wird in den meisten Fällen imho nur ein unbefriedigendes (umständliches) Ergebnis liefern.

Hier gibt es einen Überblick über die verschiedenen OpenGL Versionen und stichpunktartig die Grafikkarten, welche mindestens dazu notwendig sind. Vielleicht hilft das.

Viele Grüße,
Fancy


----------



## Runtime (7. Feb 2012)

Ich möchte eine weitere Gamegrafiklibrary machen, aber im Style von JavaFX, weil JavaFX zum Programmieren sehr umständlich ist und nur sehr begrenzt unterstützt wird (Java 5). Die maximal verwendete OpenGL Version ist 2.0.


----------

