JOGL2 eigene mipmaps laden

Der_Therion

Mitglied
Hallo,

ich versuche mich derzeit an JOGL2 und bin an einer 3th person landschaft
die richtig viele texturen benötigt. irgendwie bin ich über die möglichkeit
gestossen die kombination shader+textureatlas zu nutzen ...klappt im prinzip auch supertoll
(nur das randbluten der mimaps is so garnicht schick)

ich denke mir das es besser funktioniert wenn ich die mipmap-level per hand lade..
leider bin ich nicht grade der grösste experte wie das in jogl2 funktioniert.

hiermit lade ich die texturen inkl auto-mipmapping
...
texture = TextureIO.newTexture(new File(loc+"gfx/level0.png"), true);//bzw false für mipmap aus
...

aber wie bekomme ich nun z.b.: Die datei level1.png in mipmap-stufe1 geladen ..level2.png in stufe 2 usw....

ich hab gesehen das es die funktion glTexSubImage2D gibt..ich habe aber absolut keinen blassen
schimmer wie ich das zum laufen kriege

kann mir von euch jemand dabei unter die arme greifen(mein englisch ist leider nicht soooo gut)?
(p.s.: und ist das mit dem textur-atals und den manuellen mipmaps ne schnappsidee? )

viele grüße Theri
 
G

Guest2

Gast
Moin,

grundsätzlich kann sich die dargestellte Texturqualität durch selbst erstellte mipmaps schon verbessern, allerdings solltest Du da keinen zu großen Unterschied erwarten.

Im allgemeinen würde ich also ehr vermuten, dass der Fehler woanders liegt. Hast Du mal ein Screenshot, auf dem das Problem sichtbar ist? Oder noch besser, ein KSKB, mit dem man das Problem nachvollziehen kann und anhand dessen man Dir dann auch eine mögliche Lösung zeigen könnte?

Viele Grüße,
Fancy
 

Der_Therion

Mitglied
Hallo Fancy,


das Problem liegt bei einem Textur Atlas das sobald man mipmapping benutzt
natürlich die gesammte textur runtergerechnet wird (power of 2) damit die performance steigt,
und damit werden die ränder der einzelnen oberflächen innerhalb der atlas textur vermischt.

In Netz wird das entstehende Problem als Textur bleeding (Textur Bluten) bezeichnet.
Es bilden sich Kanten an den Randlosen Oberflächen wo keine Ränder sein sollten.


(0.0->0.5 Grass) (0.5->1.0 Stein ) je höher das miplevel umso mehr werden beide
oberflächen vermischt.

Hab jetzt eine alternative Lösung zum Textur-Atlas Problem im Netz gefunden.

Bei einer sehr einfachen 2x2 Atlas Textur darf ich nicht die ränder u/v (0.0,0.5,1.0) ansteuern
sondern z.b. nur den innenbereich (z.b.: u/v 0.125->0.375 der Grass Oberfläche) allerdings muss sich
das Grass in der Fläche (u/v 0.0->0.5) ingesammt 4x befinden...damit wird
die Kantenbildung troz Mipmapping verhindert.

so ungefähr:

11|22
11|22
------
33|44
33|44


Hab jetzt im Shader 6 Textur-Atlas Texturen (4096x4096) mit jeh 16Segmenten= 96 Oberflächen im
Shader mit nur einem einzigen Renderdurchgang ohne Grafikfehler bei 320fps ...das macht echt laune

viele Grüße Theri
 
G

Guest2

Gast
Moin,

ja, das scheint eine Lösung zu sein. Rein subjektiv habe ich jedoch das Gefühl, das es nicht unbedingt immer die Einfachste und Schnellste sein muss. Gegen welche OpenGL Version entwickelt Du den? Imho sollte sich ab 3.0 was Eleganteres finden lassen (z.B. via GL_TEXTURE_2D_ARRAY).

Viele Grüße,
Fancy
 

Der_Therion

Mitglied
ja, ich hab auch mit dem gedanken gespielt textur-arrays zu benutzen

scheiterte aber an einem "einfachen" tutorial wie man das umsetzt...
etwas zu den arrays in opengl ist schnell gegoogelt..leider nicht wie
man das 'einfach' mit opengl/jogl2 verwendet.

die adressierung im vs/fs shader ist klar (xyz), aber es ist im prinzip das gleiche problem
wie bei den mipmaps..ich habe nur das wissen über das texturladen per texturIO,
deswegen bin ich auch nicht in der lage einfache bilder in bestimmte mipmap stufen zu packen.
( texture = TextureIO.newTexture(new File(fso.map_name+"_height.png"), true); )

dafür gibt es leider wirklich keine "einfachen/verständlichen" tutorials für jogl2 :(
 
G

Guest2

Gast
Wenn ich heute Abend en bissel Zeit übrig habe, werde ich mal sehen, ob ich dazu nicht ein kskb gebaut bekomme (incl. dem GL_TEXTURE_2D_ARRAY).

Das normale laden einer Textur (ohne TextureIO) geht in etwa so:

Java:
private int createTexture(final String resource) {
 
        try {
 
            final BufferedImage image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(resource));
            final byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            final ByteBuffer texture = GLBuffers.newDirectByteBuffer(data);
            final IntBuffer buffer = GLBuffers.newDirectIntBuffer(1);
 
            gl.glGenTextures(1, buffer);
            final int textureHandle = buffer.get(0);
 
            gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
 
            gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
            gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGB, image.getWidth(), image.getHeight(), 0, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, texture);
 
            return textureHandle;
 
        } catch (final IOException e) {
 
            throw new RuntimeException(e);
 
        }
 
    }

Viele Grüße,
Fancy
 

Der_Therion

Mitglied
Vielen Dank für deine Hilfe fancy :)


hab mal ein wenig experimentiert :

Das klappt prima,solange ich beim min+mag filter auf linear bleibe,
sobald ich versuche mipmaps zu laden und auf Linear_MipMap_Nearest umzuschalten
,wird keine textur angezeigt.



Code:
 createTexture(drawable,map_folder+"gfx/d0020.png",0); //Funktioniert Prima !!

//MipMap Versuch (inkl der mipmap texturen)
        createTexture(drawable,map_folder+"gfx/d0020a.png",1);
        createTexture(drawable,map_folder+"gfx/d0020b.png",2);
        createTexture(drawable,map_folder+"gfx/d0020c.png",3);
        createTexture(drawable,map_folder+"gfx/d0020d.png",4);
        createTexture(drawable,map_folder+"gfx/d0020e.png",5);


Code:
final int createTexture(GLAutoDrawable drawable,String resource,int mip_level) {
 GL2 gl = drawable.getGL().getGL2();


 
        try {

            final BufferedImage image = ImageIO.read(new File(resource));
            final byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            final ByteBuffer texture = GLBuffers.newDirectByteBuffer(data);
            final IntBuffer buffer = GLBuffers.newDirectIntBuffer(1);

            gl.glGenTextures(1, buffer);
            textureHandle = buffer.get(0);

            gl.glBindTexture(GL2.GL_TEXTURE_2D, textureHandle);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
            gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);

            gl.glTexParameteri(GL2.GL_TEXTURE_2D   , GL2.GL_TEXTURE_MAG_FILTER , GL2.GL_LINEAR);
  	    gl.glTexParameterf(GL2.GL_TEXTURE_2D   , GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_NEAREST_MIPMAP_LINEAR);


            gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
            gl.glTexImage2D(GL2.GL_TEXTURE_2D, mip_level, GL2.GL_RGB, image.getWidth(), image.getHeight(), 0, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, texture);


            return textureHandle;

        } catch (final IOException e) {

            throw new RuntimeException(e);

        }


    }
 
G

Guest2

Gast
Nur kurz, ein Schuss ins Blaue:

Java:
gl.glTexParameterf(GL2.GL_TEXTURE_2D   , GL2.GL_TEXTURE_MIN_FILTER , GL2.GL_NEAREST_MIPMAP_LINEAR);

müsste imho glTexParameteri(..) sein. Und GL_LINEAR_MIPMAP_NEAREST oder GL_LINEAR_MIPMAP_LINEAR liefert wahrscheinlich bessere Ergebnisse.

Außerdem müsste da wahrscheinlich noch was in der Richtung von

Java:
gl.glTexParameteri(GL2.GL_TEXTURE_2D   , GL_TEXTURE_MAX_LEVEL,  4);

rein, damit OpenGL weis wie viele mipmap level Du geladen hast. Außerdem musst Du mit 0 anfangen oder GL_TEXTURE_BASE_LEVEL entsprechend anpassen.


Viele Grüße,
Fancy
 

Der_Therion

Mitglied
createTexture(drawable,map_folder+"gfx/d0020.png",0);// Nur Stufe 0

+ Min/Mag auf Linear = langsam,aber läuft


createTexture(drawable,map_folder+"gfx/d0020.png",0); // Stufe 0
createTexture(drawable,map_folder+"gfx/d0020a.png",1); // Stufe 1

+ Min = GL2.GL_NEAREST_MIPMAP_LINEAR // Mag auf LINEAR
+gl.glTexParameteri(GL2.GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL, 2)

= Alles schwarz,keine Texturen werden dargestellt
 
G

Guest2

Gast
Wieder nur kurz und ins Blaue (sitze gerade nicht an einem Rechner, auf dem ich das ausprobieren kann): Hast Du mal mit GL_TEXTURE_MAX_LEVEL = 1 versucht?
(Imho ist das der höchste verwendete index).

Viele Grüße,
Fancy
 
G

Guest2

Gast
Ach so, und die müssen auch alle aufs dasselbe handle, so wie Du das oben aufrüfst, werden die einzelnen mitmap level auf verschiedene handle gelegt.

Ich poste heute Abend mal ein Beispiel.

Gruß,
Fancy
 
G

Guest2

Gast
Zumindest ein kskb zum manuellen laden der Mipmaps hab ich jetzt online gestellt: CustomMipmap.java

Letztendlich steckt da nicht viel hinter und geht so ähnlich, wie Du es schon versucht hast.

Wenn ich dazu komme, werde ich auch noch ein kskb zu den Texture Arrays bauen.

Gruß,
Fancy
 

Der_Therion

Mitglied
Hallo Fancy,

wow...super Tutorial :)

das funktioniert,und ich hab bereits jetzt keine fehler mehr im textur-atlas,
es war also eine kombination von adressierung des atlases im shader und der
qualität der mipmaps die zu "einer" lösung führten..bin aber echt auf den array gespannt!


tausend dank :)
 

Ähnliche Java Themen

Neue Themen


Oben