GL not displaying my textures properly

Started by kstenerud, November 25, 2005, 11:35:14

Previous topic - Next topic

kstenerud

I've been banking my head against the keyboard for two days now trying to figure out what's wrong with my code.

This is a simple program to open a window and display a square with a runtime-generated texture.

When I run it, I get a window filled with yellow.  If I don't fill the texture pixel data completely, I get a 1 pixel wide bar on the bottom and/or side depending on how much data I set to nonzero.

Can anyone tell me what's wrong?  Code follows:

package org.stenerud.emujava;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.glu.GLU;
import org.lwjgl.util.GL;

public class GLTest {

    public static void main(String[] args) throws Exception
    {
        new GLTest().run();
    }

    public void run() throws Exception
    {
        String title = "GL Test";
        int width=256;
        int height=256;

        Display.setDisplayMode(new DisplayMode(width, height));
        Display.setTitle(title);
        Display.create();

        // enable textures
        GL.glEnable(GL11.GL_TEXTURE_2D);
        // disable the OpenGL depth test since we're rendering 2D graphics
        GL.glDisable(GL11.GL_DEPTH_TEST);

        // set up 2D mode
        GL.glMatrixMode(GL11.GL_PROJECTION);
        GL.glLoadIdentity();
        GLU.gluOrtho2D(0, width, height, 0);
        GL.glMatrixMode(GL11.GL_MODELVIEW);
        GL.glLoadIdentity();
        GL.glViewport(0, 0, width, height);

        //set clear color to black
        GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        // Make texture buffer
        ByteBuffer bytePixels = ByteBuffer.allocateDirect(4 * width*height).order(ByteOrder.nativeOrder());
        IntBuffer intPixels = bytePixels.asIntBuffer();
        // Fill it in with rainbow colors
        fillAllPixels(intPixels);

        // Create texture
        int textureId = createTexture();
        GL.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

        // Set the texture contents
        GL.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0,
                          GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, bytePixels );

        // Main loop.  Runs at around 60 fps
        long frameDuration = 1000/60;
        for(;;)
        {
            long startTime = System.currentTimeMillis();

            // store the current model matrix
            GL.glPushMatrix();

            GL.glBindTexture(GL11.GL_TEXTURE_2D, textureId);

            GL.glBegin(GL11.GL_QUADS);
            {
                GL.glTexCoord2f(0, 0);
                GL.glVertex2f(0, 0);
                GL.glTexCoord2f(0, width);
                GL.glVertex2f(0 , height);
                GL.glTexCoord2f(width, height);
                GL.glVertex2f(width, height);
                GL.glTexCoord2f(height, 0);
                GL.glVertex2f(width, 0);
            }
            GL.glEnd();

            // restore the model view matrix to prevent contamination
            GL.glPopMatrix();

            Display.update();

            long elapsedTime = Timer.getTime() - startTime;
            if(elapsedTime < frameDuration)
                try {Thread.sleep(frameDuration - elapsedTime);} catch(Exception e) {}
        }
    }

    public void fillAllPixels(IntBuffer pixels)
    {
        // Just cycle through all the colors
        for(int i = 0; i < pixels.capacity(); i++)
            pixels.put(i, i);
    }

    private int createTexture()
    {
        IntBuffer tmp = BufferUtils.createIntBuffer(1);
        GL.glGenTextures(tmp);
        return tmp.get(0);
    }
}

lightbringer

The problem is with your gluOrtho function. You're setting it up with the origin at the upper left but are still drawing the quad counter-clockwise.

Try it this way:
GLU.gluOrtho2D(0, width, 0, height);

Or, alternatively, reverse the order of your vertices.

Edit: Also, I forgot to mention this, but your texture coords are wrong. Texture coords go from 0.0f to 1.0f. Just change all the width and height references in the TexCoord2f commands to 1.0f.

kstenerud

Yes, I had it like that before, but it was just displaying a yellow screen so I changed it.

It does the same thing either way.

I just changed the quad display to this:

               GL.glTexCoord2f(0, 0);
               GL.glVertex2f(0, 0);
               GL.glTexCoord2f(0, 1);
               GL.glVertex2f(0 , 1);
               GL.glTexCoord2f(1, 1);
               GL.glVertex2f(1, 1);
               GL.glTexCoord2f(1, 0);
               GL.glVertex2f(1, 0);

Same result as before.  A yellow screen.

lightbringer

Ok, let's try that again:

1) take the original code in your post
2) change the orthogonal mode OR the vertex order
3) change texture coordinates to be from 0.0f to 1.0f
4) do NOT change the vertex coordinates. Only the texture coordiantes

After doing all the above I got a rainbow quad, so you can do it too ^_^

Edit: If you still can't get it to work, here's your code modified. This works for me:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.glu.GLU;
import org.lwjgl.util.GL;

public class GLTest {

    public static void main(String[] args) throws Exception
    {
        new GLTest().run();
    }

    public void run() throws Exception
    {
        String title = "GL Test";
        int width=256;
        int height=256;

        Display.setDisplayMode(new DisplayMode(width, height));
        Display.setTitle(title);
        Display.create();

        // enable textures
        GL.glEnable(GL11.GL_TEXTURE_2D);
        // disable the OpenGL depth test since we're rendering 2D graphics
        GL.glDisable(GL11.GL_DEPTH_TEST);

        // set up 2D mode
        GL.glMatrixMode(GL11.GL_PROJECTION);
        GL.glLoadIdentity();
        GLU.gluOrtho2D(0, width, 0, height);
        GL.glMatrixMode(GL11.GL_MODELVIEW);
        GL.glLoadIdentity();
        GL.glViewport(0, 0, width, height);

        //set clear color to black
        GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        // Make texture buffer
        ByteBuffer bytePixels = ByteBuffer.allocateDirect(4 * width*height).order(ByteOrder.nativeOrder());
        IntBuffer intPixels = bytePixels.asIntBuffer();
        // Fill it in with rainbow colors
        fillAllPixels(intPixels);

        // Create texture
        int textureId = createTexture();
        GL.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
        GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

        // Set the texture contents
        GL.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0,
                          GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, bytePixels );

        // Main loop.  Runs at around 60 fps
        long frameDuration = 1000/60;
        for(;;)
        {
            long startTime = System.currentTimeMillis();

            // store the current model matrix
            GL.glPushMatrix();

            GL.glBindTexture(GL11.GL_TEXTURE_2D, textureId);

            GL.glBegin(GL11.GL_QUADS);
            {
                GL.glTexCoord2f(0, 0);
                GL.glVertex2f(0, 0);
                GL.glTexCoord2f(0, 1.0f);
                GL.glVertex2f(0 , height);
                GL.glTexCoord2f(1.0f, 1.0f);
                GL.glVertex2f(width, height);
                GL.glTexCoord2f(1.0f, 0);
                GL.glVertex2f(width, 0);
            }
            GL.glEnd();

            // restore the model view matrix to prevent contamination
            GL.glPopMatrix();

            Display.update();

//            long elapsedTime = Timer.getTime() - startTime;
//            if(elapsedTime < frameDuration)
//                try {Thread.sleep(frameDuration - elapsedTime);} catch(Exception e) {}
        }
    }

    public void fillAllPixels(IntBuffer pixels)
    {
        // Just cycle through all the colors
        for(int i = 0; i < pixels.capacity(); i++)
            pixels.put(i, i);
    }

    private int createTexture()
    {
        IntBuffer tmp = BufferUtils.createIntBuffer(1);
        GL.glGenTextures(tmp);
        return tmp.get(0);
    }
}

lightbringer

Actually it seems that changing the orthogonal mode upside down doesn't have any influence on this, sorry for the confusion. You only need to change the texture coordinates as in the example above.

kstenerud

Excellent!  That worked like a charm!

Thanks for the help.


BTW, if I have the ortho set like this:

       GLU.gluOrtho2D(0, width, height, 0);

does that set the origin to the top left?

I'm still really new at openGL, and the javadocs for GL et all have no descriptions =(

lightbringer

Yeah, it does put it in the top left corner afaik. Sorry I must've been still asleep when writing that you need to change the orthogonal mode :S From trying again that part at least didn't seem to matter. The tex coords were the real issue.

The javadocs have no description for a reason, the devs had low priority for documentation. The truth is, the wrappers are almost one-to-one match for the OpenGL commands, with a bit of creative thinking and some help on the ByteBuffer mess it's not so difficult to figure out. What you want to do is read the original specs, and then read the javadoc to see how it maps over, and you're good to go.

You need to read the blue book and the red book, both available for free from links over at opengl.org
http://www.opengl.org/documentation/index.html

Those are a bit dated, and don't have all the latest extensions, so you'll need to browse opengl.org docs and forums for other info (2.0 language spec, shader language spec) )if you want to get into shaders or vertex buffer objects and the like, but chances are you aren't that far yet.