Search code examples
javaopengltextureslwjgltexture2d

Textures not working


So ok. That OpenGL state machine is kiddin' me! I'm serious! Just few days ago all worked with immediate mode and even VBO mode, but not today! Today im seein a white quad, cause i rewrote 80% of my old code. Thats such a cool thing, yo know.
So. I need your help guys. Here is my GL calls tracer output:

[17.02.2015 17:45:47] [--------GAME_STARTED--------]
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_COLOR_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_TEXTURE_2D) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_TEXTURE_COORD_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_VERTEX_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_INDEX_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_NORMAL_ARRAY) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_NORMALIZE) -> false
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_MATRIX_MODE) -> GL_MODELVIEW
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_DEPTH_TEST) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_ALPHA_TEST) -> false
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_STENCIL_TEST) -> false
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_DEPTH_FUNC) -> GL_LESS
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_CULL_FACE_MODE) -> GL_BACK
[17.02.2015 17:45:49] [GLTrace] glGetBoolean(GL_BLEND) -> false
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_ARRAY_BUFFER_BINDING) -> 0
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING) -> 0
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_TEXTURE_BINDING_2D) -> GL_CURRENT_BIT
[17.02.2015 17:45:49] [GLTrace] glEnable(GL_DEPTH_TEST) -> DONE
[17.02.2015 17:45:49] [GLTrace] glDisable(GL_CULL_FACE) -> DONE
[17.02.2015 17:45:49] [GLTrace] glCullFace(Off) -> DONE
[17.02.2015 17:45:49] [GLTrace] glDepthFunc(LessOrEqual) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindBuffer(VertexArray, -1) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindBuffer(ElementArray, -1) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindTexture(Texture2D, -1) -> DONE
[17.02.2015 17:45:49] [GLTrace] glViewport(0, 0, 800, 600) -> DONE
[17.02.2015 17:45:49] [GLTrace] glGetInteger(GL_MAX_TEXTURE_SIZE, java.nio.DirectIntBufferU[pos=0 lim=16 cap=16]) -> DONE
[17.02.2015 17:45:49] [GLTrace] glGenTextures() -> 2
[17.02.2015 17:45:49] [GLTrace] glBindTexture(Texture2D, 2) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_BASE_LEVEL, 0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_MAX_LEVEL, 0) -> DONE
[17.02.2015 17:45:49] [GLTrace] [Setting wrap mode: Clamp]
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_WRAP_S, GL_CLAMP) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_WRAP_T, GL_CLAMP) -> DONE
[17.02.2015 17:45:49] [GLTrace]  -> DONE
[17.02.2015 17:45:49] [GLTrace] [Setting filter mode: Nearest]
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexParameteri(Texture2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) -> DONE
[17.02.2015 17:45:49] [GLTrace]  -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexImage2D(Texture2D, 0, RGBA, 256, 256, 0, RGBA, UnsignedByte, java.nio.DirectByteBuffer[pos=0 lim=262144 cap=262144]) -> DONE
[17.02.2015 17:45:49] [GLTrace] glClear(ColorAndDepth) -> DONE
[17.02.2015 17:45:49] [GLTrace] glLoadIdentity() -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(Projection) -> DONE
[17.02.2015 17:45:49] [GLTrace] glLoadIdentity() -> DONE
[17.02.2015 17:45:49] [GLTrace] gluPerspective(70.0, 1.3333334, 0.001, 5000.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(ModelView) -> DONE
[17.02.2015 17:45:49] [GLTrace] glPushMatrix() -> DONE
[17.02.2015 17:45:49] [GLTrace] glBegin(Quads) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(0.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(0.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(1.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(1.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(1.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(1.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTexCoord2f(0.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glVertex3f(0.0, 1.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glEnd() -> DONE
[17.02.2015 17:45:49] [GLTrace] glPopMatrix() -> DONE
[17.02.2015 17:45:49] [GLTrace] glLoadIdentity() -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(Projection) -> DONE
[17.02.2015 17:45:49] [GLTrace] gluOrtho2D(0.0, 800.0, 600.0, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glMatrixMode(ModelView) -> DONE
[17.02.2015 17:45:49] [GLTrace] glTranslatef(0.375, 0.375, 0.0) -> DONE
[17.02.2015 17:45:49] [GLTrace] glDisable(GL_DEPTH_TEST) -> DONE
[17.02.2015 17:45:49] [GLTrace] glBindTexture(Texture2D, -1) -> DONE
[17.02.2015 17:45:49] [---------GAME_ENDED---------]

This is my immediate mode quad rendering - alls white! Why is it so? Im pretty sure slick-util loaded image correctly. Image is valid (tested just two days ago). There may be some changes i made (global rendering system refactoring :3)... Im not using slick-util Texture and TextureImpl. Also i'm not using mipmaps.

This is my implementation of that piece of code:

public class Texture
{

    protected int width, height, texWidth, texHeight, depth;
    protected boolean alpha;
    protected WrapMode wrapMode = WrapMode.Clamp;
    protected FilterMode filterMode = FilterMode.Nearest;
    protected TextureBuffer buffer;
    protected PixelFormat dstPixelFormat = PixelFormat.RGBA, srcPixelFormat;

    public Texture(LoadableImageData imageData, WrapMode wrapMode, FilterMode filterMode)
    {
        this.width = imageData.getWidth();
        this.height = imageData.getHeight();
        this.texWidth = imageData.getTexWidth();
        this.texHeight = imageData.getTexHeight();
        this.depth = imageData.getDepth();
        this.wrapMode = wrapMode;
        this.filterMode = filterMode;
        this.alpha = depth == 32;
        this.srcPixelFormat = alpha ? PixelFormat.RGBA : PixelFormat.RGB;

        buffer = (TextureBuffer) BufferManager.create(BufferType.Texture);
        BufferManager.setup(this, imageData.getImageBufferData(), srcPixelFormat.getSize());
    }

    public int getWidth()
    {
        return width;
    }

    public int getHeight()
    {
        return height;
    }

    public TextureBuffer getBuffer()
    {
        return buffer;
    }

    public WrapMode getWrapMode()
    {
        return wrapMode;
    }

    public FilterMode getFilterMode()
    {
        return filterMode;
    }

    public PixelFormat getDstPixelFormat()
    {
        return dstPixelFormat;
    }

    public PixelFormat getSrcPixelFormat()
    {
        return srcPixelFormat;
    }
}

This is reworked texture loader:

public class TextureLoader
{

    private static IntBuffer maxResolutionBuffer;

    public static LoadableImageData loadImage(String resourceName)
    {
        LoadableImageData imageData = ImageDataFactory.getImageDataFor(resourceName);
        ByteBuffer data = null;
        try {
            data = imageData.loadImage(new BufferedInputStream(new FileInputStream(new File("res", resourceName))),
                                       false, null);
        } catch (FileNotFoundException ex) {
            FaultManager.process("Can't find image!", ex, true);
        } catch (IOException ex) {
            FaultManager.process("Can't load image!", ex, true);
        }
        return imageData;
    }

    public static Texture getTexture(LoadableImageData imageData, WrapMode wrap, FilterMode filter) throws IOException
    {
        if (!checkTextureResolution(imageData.getTexWidth(), imageData.getTexHeight())) {
            throw new IOException("Attempt to allocate a texture too big for the current hardware");
        }
        return new Texture(imageData, wrap, filter);
    }

    public static boolean checkTextureResolution(int texWidth, int texHeight)
    {
        if (maxResolutionBuffer == null) {
            maxResolutionBuffer = BufferUtils.createIntBuffer(16);
            GLProxy.getProperty(GL11.GL_MAX_TEXTURE_SIZE, GLProxy.GLParamType.Integer, maxResolutionBuffer);
        }
        int max = maxResolutionBuffer.get(0);
        if ((texWidth > max) || (texHeight > max)) {
            return false;
        }
        return true;
    }
}

In my game code i'm just using:

        try {
            LoadableImageData imageData = TextureLoader.loadImage("test.png");
            texture = TextureLoader.getTexture(imageData, WrapMode.Clamp, FilterMode.Nearest);
        } catch (IOException ex) {
            FaultManager.process("Can't load texture test.png!", ex, true);
        }

All other classes implement their own stuff and i'm pretty sure yo can find that in GLTrace.


Solution

  • Ok. That came up to work with immediate mode rendering and buffer objects. That also happened like magic. Immediate mode rendering was fixed by enabling GL_TEXTURE_2D (blame myself) and disabling GL_VERTEX_ARRAY and GL_INDEX_ARRAY. VBO was fixed after i just tried this time. I think that was my state changed bug, cause textures and arrays was enabled by default before. So i'm not sure how i fixed VBO this time, but i'm proud to say that "stackoverflow" still have some fresh minds! Gratz to @Jean-SimonBrochu!

    MAIN PROBLEM OF OpenGL
    It's made to use with functional programming, or state programming. This means OpenGL context (that you create with Display) will make yo crying everytime yo miss one call or pass wrong data. First - if not critical it just can work even without setting error state. Second - yo JVM will be smashed by JNI cause of crash in native code (C++/Asm).

    This is my short advices how to handle this:

    1. Control everything in OOP (You should implement classes that would control proccesses corresponding to any GL calls or such)
    2. Control GL state (You should implement a data/option container class, which would contain abstract or current OpenGL state)
    3. Use glGetError every time you unsure what the heck is goin on. You should use this function right after suspicious call to OpenGL.
    4. Always build understandable system. ALWAYS! Even if you doing your project for yourself. This costs time of people who may try to help you to understand your shitworks.
    5. Handle all parts of work you can access yourself. Working on implementing this will show you how the whole system works and help you adapt your thoughts about your system to this.

    TEXTURES NOT WORKING? CHECK THIS!

    1. Check that you enable GL_TEXTURE_2D (or GL_TEXTURE in really old versions). You MUST be sure you aint disabling that any time later!
    2. Check all GL state options corresponding to your chosen one rendering mode. I mean if you're using VBO, you should also enable GL_VERTEX_ARRAY and such you use.
    3. Check that your texture coordinates (texCoords) are properly set and texture coordinates array option enabled.
    4. Check that you generating mipmaps or not using them at all. By default, OpenGL state is set to use mipmaps. You can switch this by taking right texture filter mode (GL_NEAREST/GL_LINEAR or GL_NEAREST_MIPMAP_NEAREST/GL_LINEAR_MIPMAP_LINEAR).
    5. Check that if your image use alpha channel, you set GL_BLEND on and set blending mode to Alpha through GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA.
    6. Check that normals are correct on your mesh (if you use them).
    7. Finally check your incoming data (image). Thats hard, but if you follow p.5 of advices above - that should be fairly easy.

    Thanks. Tryin' to be useful and came out with more pluses for answer rather than minuses for question :)

    That was my problem in GLState class:

    -   public boolean depthTest = true;
    +   public boolean depthTest = false;
    -   public boolean vertexArray = true, indexArray = true, colorArray = false, textureArray = false, normalArray = false;
    +   public boolean vertexArray, indexArray, colorArray, textureArray, normalArray;
    
    static {
    +       DEFAULT_3D.depthTest = true;
    +       DEFAULT_3D.vertexArray = true;
    +       DEFAULT_3D.indexArray = true;
    +
    +       DEBUG_3D.depthTest = true;
    +       DEBUG_3D.vertexArray = true;
    +       DEBUG_3D.indexArray = true;
            DEBUG_3D.faceCullingMode = FaceCullingMode.Off;
    }
    

    P.S. Explanation for LWJGL 2.9.1