OpenGL - MipMaps werden nicht benutzt

Hi,
Aus irgendeinem Grund werden meine MipMaps nicht benutzt. Immer wenn ich als Sampler Parameter (GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR oder _NEAREST) einstelle wird das Objekt durchsichtig. Die MipMaps lade ich via
glCompressedTexImage2D(GL_TEXTURE_2D, mipLevel, format, width, height, 0, buffer); hoch.
Um zu überprüfen ob die MipMaps überhaupt korrekt aus dem File gelesen werden hatte ich testweise eine MipMap auf mipLevel 0 hochgeladen und sie wurde auch benutzte, also am Lesen aus dem DDS File sollte es eigentlich nicht liegen.
Muss ich um MipMaps zu nutzen irgendetwas im Shader machen ?

Wenn ich die Textur lade setze ich:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, header.mipMapCount-1);

Und später im Sampler

glSamplerParameteri(samplerID, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(samplerID, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); //TODO
glSamplerParameteri(samplerID, GL_TEXTURE_WRAP_S, GL_REPEAT);
glSamplerParameteri(samplerID, GL_TEXTURE_WRAP_T, GL_REPEAT);

Vor dem Rendern binde ich dann Textur und Sampler wie folgt:

glDisable(GL_CULL_FACE);
mipSampler.bindSampler(); // wenn ich diese Zeile auskommentiere wird das Objekt gerendert, aber immer nur mit dem MipMap Level 0 --> also die normale, nicht verkleinerte Textur
glBindSampler(0, samplerID);
quad.render(); // Rendert ein Quadrat
glEnable(GL_CULL_FACE);

Auch wenn ich nicht glaube das hier das Problem liegt, hier der Code mit dem Das Bild aus dem DDS File geladen wird:

DDSLoader
[spoiler]```
/**
* loads an 2D DDS-Texture with all MipMaps
* @throws IOException
* */
private static Texture load2DTexture(int size, int format, int blocksize, DDSHeader header, BinaryFileReader bis) throws IOException
{

      // size = aus der Höhe und weite errechnete Größe des Ganzen. Wird wie in der for Schleife berechnet
     // format = Das OpenGL Format der DDS Textur wie zB GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
    // blocksize = die größe eines Blockes. Im Falle von DXT1 = 8 ansonste 16
   // header = Repräsentiert den DDS Header
  // bis =  Liest aus dem File, ist zu dem Zeitpunkt schon am 129 Byte (nach dem Header)

	int texID = glGenTextures();
	glBindTexture(GL_TEXTURE_2D, texID);
	
	ByteBuffer buffer = BufferUtils.createByteBuffer(size);
	byte[] array = new byte[size];
	bis.readByteArray(array);
	
	System.out.println(array); // TODO
	buffer.put(array);
	buffer.rewind();
	
	glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, header.width, header.height, 0, buffer);
	
	if(header.mipMapCount > 1)
	{
		int width = header.width;
		int height = header.height;
		
		for(int i = 1; i < header.mipMapCount; i++)
		{
			width >>= 1; // Move one bit to the right, like "Divided by 2"
			width >>= 1; // Move one bit to the right, like "Divided by 2"
			
			if(width == 0) width = 1;
			if(height == 0) height = 1;
			
			size = ((width + 3) / 4 ) * ((height + 3) / 4) * ((header.depth + 3) / 4) * blocksize;
			
			array = new byte[size];
			buffer = BufferUtils.createByteBuffer(size);
			
			bis.readByteArray(array);
			buffer.put(array);
			buffer.rewind();
			
			glCompressedTexImage2D(GL_TEXTURE_2D, i, format, width, height, 0, buffer); 
                           /* Gibt es eine Möglichkeit einen Size Parameter zu übergeben wie in C++ ? Hier wird ja immer buffer.limit() genommen. 
                            * Und da die Texturen hier immer kleiner werden könnte man es sich so sparen immer einen neuen Buffer zu erzeugen */
		}
	}
	
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, header.mipMapCount-1);
	
	
	glBindTexture(GL_TEXTURE_2D, 0);
	
	return new Texture(texID, header.width, header.height, (header.bitCount / 8), (header.mipMapCount > 1 ? true : false) );
	
}


Und hier die DDS Textur mit allen MipMaps: [http://www.mediafire.com/download/eakxe2qo936fj28/Miptest.dds](http://www.mediafire.com/download/eakxe2qo936fj28/Miptest.dds)

Was mache ich falsch ?

Mfg,
~Oneric

EDIT: 
Wenn ich den Textur Sampler auf mehren Textur Units binde

glBindSampler(0, samplerID);
glBindSampler(1, samplerID);
glBindSampler(2, samplerID);
usw …


Wird das Objekt nicht durchsichtig, einen Wechsel zwischen den MipMaps kann ich trotzdem nicht erkennen.

Ich hatte gerade eine KSKB erstellt da ich dachte das dies vielleicht helfen könnte, aber da diese viel zu groß werden würde wäre das wohl eher mehr verwirrend als hilfreich.

Mfg,
~Oneric

Vielleicht hilft hier schon ein ganz subtiles @Fancy :wink: Ansonsten würde ich mir das auch mal anschauen, habe aber MipMaps selbst noch nicht wirklich “aktiv” benutzt… :o

Moin,

ohne KSKB ist es oft schwierig etwas zu schreiben, außer: “Das könnte an allem Möglichen liegen.”

Ein KSKB für Mipmaps zusammen zu dengeln sollte auch nicht so schwierig sein, hier ist eins. :wink:

Wenn Du Dein Problem da einbauen kannst, kann man den Fehler vermutlich finden.

Viele Grüße
Fancy

Ich habe jetzt mit Hilfe dieser Vorlage eine kleine KSKB erstellt und zu einem Rar-Archiv gepackt.
Im Ordner “src” befindet sich der Sourcecode, im Ordner “res” die DDS Texture.
Auch hier wird das ganze Schwarz wenn man GL_LINEAR_MIPMAP_LINEAR benutzt. Damit man das Rechteck trotzdem noch erkennen kann, habe ich die Hintergrundfarbe des Fensters auf gelb festgelegt.

Den originalen Code kann ich nicht testen da meine Grafikkarte maximal OpenGl 4.2 unterstützt und dort wird GLSL 430 benutzt.

Mfg,
~Oneric

Versuchs mal so:

            throws IOException
    {

        final int texID = glGenTextures();
        glBindTexture(GL_TEXTURE_2D, texID);

        ByteBuffer buffer = BufferUtils.createByteBuffer(size);
        byte[] array = new byte[size];
        bis.readByteArray(array);

        buffer.put(array);
        buffer.rewind();

        glTexStorage2D(GL_TEXTURE_2D, header.mipMapCount, format, header.width, header.height); // <--
        glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, header.width, header.height, format, buffer); // <--

        System.out.println("error: " + glGetError());

        if (header.mipMapCount > 1)
        {
            int width = header.width;
            int height = header.height;

            for (int i = 1; i < header.mipMapCount; i++)
            {
                width >>= 1; // "Divided by 2"
                height >>= 1; // "Divided by 2" <--

                if (width == 0)
                    width = 1;

                if (height == 0)
                    height = 1;

                size = ((width + 3) / 4) * ((height + 3) / 4) * ((header.depth + 3) / 4) * blocksize;

                array = new byte[size];
                buffer = BufferUtils.createByteBuffer(size);

                bis.readByteArray(array);
                buffer.put(array);
                buffer.rewind();

                glCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, width, height, format, buffer); // <--

            }
        }

        System.out.println("error: " + glGetError());

        glBindTexture(GL_TEXTURE_2D, 0);

        return new Texture(texID, header.width, header.height, (header.bitCount / 8), (header.mipMapCount > 1 ? true : false));

    }

Ich hab nicht drüber nachgedacht, ob das alles so stimmt, aber zumindest liefert es hier optisch ein vernünftiges Ergebnis. :wink:

Edit: Hab die Frage mit dem Buffer erst jetzt gesehen. Das sollte gehen:

            // buffer = BufferUtils.createByteBuffer(size);

            bis.readByteArray(array);
            buffer.position(0);
            buffer.put(array);
            buffer.flip();

            glCompressedTexSubImage2D(GL_TEXTURE_2D, i, 0, 0, width, height, format, buffer); // <--```

Viele Grüße
Fancy

:slight_smile: Danke
Jetzt wo die Höhe verkleinert wird funktioniert es super. Die glTexStorage2D Methode habe ich aber mal weg gelassen, da ich von den Systemanforderungen nicht über OpenGL 3 hinaus will.
Auch das mit den Buffern funktioniert wunderbar.

MfG,
~Oneric

Schön das es nun geht.

Bezüglich des glTexStorage2D ist dieses hier vermutlich lesenswert. Insbesondere der Unterschied zwischen Immutable- und Mutable- Storage.

Auch wenn die Funktion erst seit OpenGL 4.2 core ist, so gibt es die passende ARB-Extension dazu schon länger. Über diese kann man die Funktion auch in einem OpenGL 3 Kontext verwenden. Wenn man es ganz sauber machen will, prüft man auf das Vorhandensein dieser Extension:

            
            ARBTextureStorage.glTexStorage2D(GL_TEXTURE_2D, header.mipMapCount, format, header.width, header.height); 
            glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, header.width, header.height, format, buffer);        
            ...

        } else {
            
            glCompressedTexImage2D(GL_TEXTURE_2D, 0, format, header.width, header.height, 0, buffer);
            ...
            
        }```

Muss man aber natürlich nicht, es geht ja auch ohne glTexStorage2D. ;)

Viele Grüße
Fancy