0

I am trying to draw my font texture atlas to the screen using LWJGL, but OpenGL instead draws a solid white square.

A working example using my drawing code:

import java.awt.image.*;
import java.io.*;
import java.nio.*;
import javax.imageio.*;
import org.lwjgl.*;
import org.lwjgl.opengl.*;

public class OpenGLImageTest
{
    private static int textureID;

    public static void main(String[] args) throws Exception
    {
        Display.setTitle("OpenGL Image Test");
        Display.setDisplayMode(new DisplayMode(640, 480));
        Display.create();

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 640, 0, 480, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        textureID = bindTextureFile("textures/font.png");

        while(!Display.isCloseRequested())
        {
            Display.sync(60);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);

            GL11.glColor4f(1, 0, 0, 1);
            drawFontAtlas(0, 0);

            Display.update();
        }

        Display.destroy();
    }

    private static void drawFontAtlas(int x, int y)
    {
        GL11.glPushMatrix();
            GL11.glTranslatef(x, y, 0);
            GL11.glDisable(GL11.GL_DEPTH_TEST);
            GL11.glEnable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
                GL11.glBegin(GL11.GL_QUADS);
                    GL11.glVertex2i(0, 0);
                    GL11.glVertex2i(0, 256);
                    GL11.glVertex2i(256, 256);
                    GL11.glVertex2i(256, 0);
                GL11.glEnd();
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glDisable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glPopMatrix();
    }

    private static int bindTextureFile(String file)
    {
        try
        {
            BufferedImage image = ImageIO.read(new FileInputStream(file));

            int[] pixels = new int[image.getWidth() * image.getHeight()];

            image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

            ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);

            for(int y = 0; y < image.getWidth(); y++)
            {
                for(int x = 0; x < image.getHeight(); x++)
                {
                    int pixel = pixels[y * image.getWidth() + x];

                    buffer.put((byte)((pixel >> 16) & 0xFF));
                    buffer.put((byte)((pixel >> 8) & 0xFF));
                    buffer.put((byte)(pixel & 0xFF));
                    buffer.put((byte)((pixel >> 24) & 0xFF));
                }
            }

            buffer.flip();

            int textureID = GL11.glGenTextures();

            GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);

            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);

            return textureID;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        return -1;
    }
}

Can anyone tell me what I am doing wrong and how to fix it?

Edit: font.png is white on transparent white. It's the default Minecraft font for testing purposes.

condorcraft110 II
  • 261
  • 1
  • 2
  • 15
  • what type of texture file are you using? – Ubica Feb 20 '15 at 23:22
  • @Ubica it's a PNG with an alpha channel. It displays properly in an image viewer. – condorcraft110 II Feb 20 '15 at 23:25
  • I did this with LWJGL some time ago, when I tried to make a console like in quake and it shouldn't be hard. From your code it's hard to see what is wrong, cause it's not a working example. In my experience... create a testing ground application with minimum code that gives you texture loading ability on a single poly and try to make it work there. Then apply what you learned in a real situation. – Ubica Feb 20 '15 at 23:30
  • @Ubica Changed to a compilable working example ;) – condorcraft110 II Feb 20 '15 at 23:37
  • Sadly I have to go, but if no1 answers the question by the time I am back, I will check it out... try putting `GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);` before glPushMatrix ... first thing that comes to my mind – Ubica Feb 20 '15 at 23:58
  • 2
    You're creating a texture with internal format `GL_RGB8`. By definition, an RGB texture has no alpha component. You'll need to use an RGBA format. – Reto Koradi Feb 21 '15 at 00:51
  • @condorcraft110II: You are also not setting any texture coordinates at all, so the GL will sample the very sampe texture location for the whole primitive. – derhass Feb 21 '15 at 01:51
  • Downvoter: care to give feedback? – condorcraft110 II Mar 18 '15 at 21:44

1 Answers1

0

Your problem can be fixed by adding texture coordinates:

    {
        GL11.glTexCoord2f(0, 1); // added texture coordinate
        GL11.glVertex2i(0, 0);
        GL11.glTexCoord2f(0, 0); // added texture coordinate
        GL11.glVertex2i(0, 256);
        GL11.glTexCoord2f(1, 0); // added texture coordinate
        GL11.glVertex2i(256, 256);
        GL11.glTexCoord2f(1, 1); // added texture coordinate
        GL11.glVertex2i(256, 0);
    }

I actually used slick-util.jar to load your texture, but it will work with your code just the same... you can find a working example of my code bellow... slick-util.jar can be found here

In order to get actual transparency, you also need to change this line in your code: GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer); and what needs to be changed is GL11.GL_RGB8 into GL11.GL_RGBA

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

public class OpenGLImageTest {

    private static Texture tex; //private static int textureID;

    public static void main(String[] args) throws Exception {
        Display.setTitle("OpenGL Image Test");
        Display.setDisplayMode(new DisplayMode(640, 480));
        Display.create();

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 640, 0, 480, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        tex = loadTexture("textures/font.png"); //textureID = bindTextureFile("textures/font.png");

        while (!Display.isCloseRequested()) {
            Display.sync(60);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);

            GL11.glColor4f(1, 1, 1, 1);
            drawFontAtlas(0, 0);

            Display.update();
        }

        Display.destroy();
    }

    private static void drawFontAtlas(int x, int y) {
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GL11.glPushMatrix();
        GL11.glTranslatef(x, y, 0);
        GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glEnable(GL11.GL_BLEND);

        tex.bind(); //GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2f(0, 1); // added texture coordinate
            GL11.glVertex2i(0, 0);
            GL11.glTexCoord2f(0, 0); // added texture coordinate
            GL11.glVertex2i(0, 256);
            GL11.glTexCoord2f(1, 0); // added texture coordinate
            GL11.glVertex2i(256, 256);
            GL11.glTexCoord2f(1, 1); // added texture coordinate
            GL11.glVertex2i(256, 0);
        }
        GL11.glEnd();
        GL11.glDisable(GL11.GL_BLEND);
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glPopMatrix();
    }

    public static Texture loadTexture(String texturePath) {
        try {
            return TextureLoader.getTexture("png", new FileInputStream(new File(texturePath)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
Ubica
  • 1,011
  • 2
  • 8
  • 18
  • Thanks, this works perfectly, but it somehow manages to render the image upside down... Any ideas as to what on Earth I did wrong there? – condorcraft110 II Feb 21 '15 at 10:56
  • Never mind, I got my texture coordinates wrong. Also, this little 2D game is an attempt to learn some basic OpenGL, so I have restricted myself to using only LWJGL ;) – condorcraft110 II Feb 21 '15 at 10:57