OpenGL Texture not displaying - my first class.

Jones
Unregistered
 
Post: #1
Well, I just started messing around with OOP classes, and so far I've found them to be pretty cool. As my first, I figured I'd start with something relatively simple: A form of SDL_Surface, but for OpenGL. It uses DevIL and OpenGL. Unfortunatly, my texture does not appear.

I've actually posted a thread about this over at gameDev, but then I realized. Oh wait... what am I doing? It's the mac users that are the smart ones, I'll ask them. Wink

Here's the other thread, for reference.

What I've tried:

- Binding the texture directly from IL, instead of from my class variables. (When drawing.)
- Inserting little warning tags after every action. (Showed no problems.)
- Swapping up the vertex ordering of the texture grabbing.

No luck, anyhow. Here's my class:
(Feel free to tell me how useless it is! Rasp )

Code:
#include <cstdlib>
#include <cstring>

#include "OpenGL/gl.h"
#include "OpenGL/glu.h"

#include "IL/il.h"
#include "IL/ilu.h"
#include "IL/ilut.h"

using namespace std;

class glSurface {
    
    protected:
        GLint components;
        GLsizei width;
        GLsizei height;
        GLenum format;
        GLvoid *pixels;
        
        ILuint image_IL;
        GLuint texture_GL;
        
        int x;
        int y;
        int firstDraw;
        
        
    public:
        glSurface();
        int Open(char *);
        void Position(int, int);
        void Draw();
        
        
};

glSurface::glSurface() {
    ilGenImages(1, &image_IL);
    glGenTextures(1, &texture_GL);
    firstDraw = 1;
}

int glSurface::Open(char filename[]) {

    ILint open_currentBound_IL = ilGetInteger(IL_CUR_IMAGE);
    ILboolean open_success_IL;
        
    ilBindImage(image_IL);
    open_success_IL = ilLoadImage(filename);
    if (open_success_IL == IL_FALSE) {
        ilBindImage(open_currentBound_IL);
        cout << "Problem!" << endl;
        return(-1);
    }
    components = ilGetInteger(IL_IMAGE_BPP);
    width = ilGetInteger(IL_IMAGE_WIDTH);
    height = ilGetInteger(IL_IMAGE_HEIGHT);
    format = ilGetInteger(IL_IMAGE_FORMAT);
    pixels = ilGetData();
    
    ilBindImage(open_currentBound_IL);
    
    return(0);
}

void glSurface::Position(int tx, int ty) {
    x = tx;
    y = ty;
}

void glSurface::Draw() {
    glBindTexture(GL_TEXTURE_2D, texture_GL);
    
    if (firstDraw = 1) {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, format, GL_UNSIGNED_BYTE, pixels);
        firstDraw = 0;
    }
    
    glBegin(GL_QUADS);
        glTexCoord2i(0, 0);    glVertex2i(x, y);
        glTexCoord2i(0, 1); glVertex2i(x + width, y);
        glTexCoord2i(1, 1); glVertex2i(x + width, y + height);
        glTexCoord2i(1, 0); glVertex2i(x, y + width);
    glEnd();
}

Thanks for any help you can give!
Quote this message in a reply
Member
Posts: 30
Joined: 2006.05
Post: #2
I don't know DevIL, so your code might already do this depending on DevIL's setup of surfaces. But remember that OpenGL (afaik) can't load non-power-of-two textures. That might be your problem.

On another note, I am using SDL for loading of OpenGL textures, and loving it. Took some doing to set up, but there's a tutorial (GLtest) in the SDL source code that shows exactly how to do it. If you use SDL at some point instead of DevIL, try it out.

Hope you solve your problem - I hate getting white squares or nothing instead of textures.
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #3
Everything looks OK, but when you say that the texture doesn't appear - what happens? White square, or nothing? Also, is GL_TEXTURE_2D enabled?
Quote this message in a reply
Jones
Unregistered
 
Post: #4
Greywhind Wrote:I don't know DevIL, so your code might already do this depending on DevIL's setup of surfaces. But remember that OpenGL (afaik) can't load non-power-of-two textures. That might be your problem.

That must be the third or forth time I've forgotten that rule. *sigh*

Thanks, my problem should be solved now.

*1 minute later*

Yeah, it's solved... sorta. One problem remains though.

My colors... check out the original tiff:
[Image: copter_base.tif]

Now, after load:
[Image: copter_wtf.png]
Ignore the rotation, that's actually just a texpos mis-type. But why is it Pink? I'm guessing it's because of some sort of byte ordering error. It's a tif, with transparency, and DevIL should be passing the right format. This *might* be another pixen error, but I viewed it in photoshop and it seemed fine.
Quote this message in a reply
Member
Posts: 245
Joined: 2005.11
Post: #5
The dark blue windows becoming light yellow suggests that you are inverting the RGB channels, although the green/pink area maintains its shadows so this may not be quite right. It could be a little endian/big endian error with the RGB values. Also check you are reading the correct pixel format (not mixing up RGBA with ARGB or something), although I think you are OK on that one.
Quote this message in a reply
Jones
Unregistered
 
Post: #6
backslash Wrote:The dark blue windows becoming light yellow suggests that you are inverting the RGB channels, although the green/pink area maintains its shadows so this may not be quite right. It could be a little endian/big endian error with the RGB values. Also check you are reading the correct pixel format (not mixing up RGBA with ARGB or something), although I think you are OK on that one.

That's what I was thinking... might it be my "type" in glTexImage2D? It's set at GL_UNSIGNED_BYTE, perhaps GL_BITMAP or another choice could help...

I also can't get it to be oriented correctly, If I assume that the top-left corner is 0,0 of my texture it looks like the above picture. If I assume that bottom-left corner is 0,0... it's upside down. Huh I'm gonna take a wild guess and try drawing the from the right corners.

Using DevIL, I tried forcing the image to be RGBA with:

Code:
ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);

But it remained tinted pink and yellow.

EDIT: Trying to make it any other type results in a type 4 crash.

EDIT 2: I tried making GL use ONLY GL_RGBA isntead of what DevIL gave it, like this:

Code:
glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

It's still pink. Sad Grr. I'm gonna try another format besides tif.

EDIT 3: Make another go, but with a gif... it just doesn't even draw the quad now! *smashes head against keyboard.* I mean come-on, the image only has like 4 little colors! No blending at all! Argh!

EDIT 4: Well, just noticed something... even if I rotated the image, or changed where it's drawn from, it'll still be backwards. This must be a byte ordering thing, with my tifs and DevIL. Pity, that's the only format I can export too that supports transparency. That and gif, which doesn't load.
Quote this message in a reply
Member
Posts: 245
Joined: 2005.11
Post: #7
Personally, I've always used PNGs. Libpng may not be the easiest library in the world, but the example code is quite good, and you only really have to write this stuff once. Don't feel constrained by only being able to export TIFFs - Preview can convert to many formats (including PNG), and there are plenty of free tools out there.
Anyway...
For your texture coordinates, you should have (0,0) in the top left and (1,0) in the top right. You appear to have the x and y coordinates mixed up between the texture coords and the the polygon coords in the code above. Also, remember that if (0,0) is the bottom left corner of the screen then you need to use y-height for the lower corners. I think this is why you are seeing it backwards - you are actually looking at the back of it.
Quote this message in a reply
Oldtimer
Posts: 834
Joined: 2002.09
Post: #8
Are you on an Intel or PPC mac?
Quote this message in a reply
Jones
Unregistered
 
Post: #9
Wow... it took me a while to get back to this thread.

Anyways:

I'm on PPC, too cheap for an intel one yet. Smile

Anyways, I've got a problem again similar to this one, so I put it in this thread.

I've tried out libpng (again, after leaving it for DevIL) and I wrote a C++ class for using it with OpenGL. It supports error codes, arbitrary sized textures and stuff too. Here's the source:

Code:
#include <cstdlib>
#include <fstream>

#include "OpenGL/gl.h"
#include "OpenGL/glu.h"

#include <png.h>

#define PNG_NO_FILE        89224
#define PNG_BAD_FILE    71120
#define PNG_STRUCT_ERR    22398
#define PNG_LIB_ERR        10893
#define PNG_NO_MEMORY    62009
#define PNG_NO_ERR        55872
#define PNG_BUF_FULL    01512
#define PNG_BUF_EMPTY    11943
#define PNG_BAD_TEX        99124

using namespace std;

class PNG {
    protected:
        FILE            *p_stream;
        png_structp        p_pngPTR;
        png_infop        p_infoPTR;
        png_bytepp        p_rowPointers;
        
        unsigned char    p_sig[8];
        unsigned int    p_cur_error;
        bool            p_imageLoaded;
        
    public:
        
        GLenum p_targArgs;
        GLenum p_colArgs;
        
        unsigned char    *p_image;
        unsigned int    p_depth;
        unsigned int    p_colorType;
        unsigned long    p_width;
        unsigned long    p_height;
        unsigned int    p_rowbytes;
        
        PNG();
        bool Open(char*);
        bool Flush();
        bool Texture(GLuint);
        
};

/*    Constructor, sets some pointers to null.    */
PNG::PNG() {
    p_image = NULL;
    p_rowPointers = NULL;
    p_imageLoaded = FALSE;
    p_cur_error = PNG_NO_ERR;
}

/*    Open a png image.    */
bool PNG::Open(char *p_file) {
    
    if (p_imageLoaded == TRUE) {
        p_cur_error = PNG_BUF_FULL;
        return(FALSE);
    }
    
    /*    Open the file.    */
    p_stream  = fopen(p_file, "rb");
    if (!p_stream) {
        p_cur_error = PNG_NO_FILE;
        return(FALSE);
    }
    
    /*    Read the file signature, and validate it.    */
    fread(p_sig, 1, 8, p_stream);
    if (!png_check_sig((unsigned char *)p_sig, 8)) {
        p_cur_error = PNG_BAD_FILE;
        fclose(p_stream);
        return(FALSE);
    }
    
    /*    Create the png struct.    */
    p_pngPTR = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!p_pngPTR) {
        fclose(p_stream);
        p_cur_error = PNG_STRUCT_ERR;
        return(FALSE);
    }
    
    /*    Create the info struct.    */
    p_infoPTR = png_create_info_struct(p_pngPTR);
    if (!p_infoPTR) {
        png_destroy_read_struct(&p_pngPTR, (png_infopp) NULL, (png_infopp) NULL);
        fclose(p_stream);
        p_cur_error = PNG_STRUCT_ERR;
        return(FALSE);
    }
    
    /*    Handles libpng errors.    */
    if (setjmp(png_jmpbuf(p_pngPTR))) {
        png_destroy_read_struct(&p_pngPTR, &p_infoPTR, NULL);
        fclose(p_stream);
        p_cur_error = PNG_LIB_ERR;
        return(FALSE);
    }
    
    /*    Store our file stream pointer.    */
    png_init_io(p_pngPTR, p_stream);
    
    /*    Tell libpng not to look for the file signature.    */
    png_set_sig_bytes(p_pngPTR, 8);
    
    /*    Get everything up to actual image data.    */
    png_read_info(p_pngPTR, p_infoPTR);
    
    /*    Take in the info, stick it in variables.    */
    png_get_IHDR(p_pngPTR, p_infoPTR, &p_width, &p_height,
                (int*)&p_depth, (int*)&p_colorType, NULL, NULL, NULL);
    
    
    /*    Convert some stuff, if we have to.    */
    if (p_colorType & PNG_COLOR_MASK_ALPHA) {
        png_set_strip_alpha(p_pngPTR);
    }
    if (p_depth > 8) {
        png_set_strip_16(p_pngPTR);
    }
    if (p_colorType == PNG_COLOR_TYPE_GRAY ||
        p_colorType == PNG_COLOR_TYPE_GRAY_ALPHA) {
            png_set_gray_to_rgb(p_pngPTR);
    }
    if (p_colorType == PNG_COLOR_TYPE_PALETTE) {
        png_set_palette_to_rgb(p_pngPTR);
    }
    
    /*    Update the info.    */
    png_read_update_info(p_pngPTR, p_infoPTR);

    /*    Number of rowsize, in bytes.    */
    p_rowbytes = png_get_rowbytes(p_pngPTR, p_infoPTR);
    
    /* Allocate memory for pixel data.    */
    if ((p_image = (unsigned char*)malloc(p_rowbytes * p_height)) == NULL) {
        png_destroy_read_struct(&p_pngPTR, &p_infoPTR, NULL);
        p_cur_error = PNG_NO_MEMORY;
        return(FALSE);
    }
    
    if ((p_rowPointers = (png_bytepp)malloc(p_height * sizeof(png_bytepp))) == NULL) {
        png_destroy_read_struct(&p_pngPTR, &p_infoPTR, NULL);
        free(p_image);
        p_image = NULL;
        p_cur_error = PNG_NO_MEMORY;
        return(FALSE);
    }
    
    /*    Correct the row pointer offsets.    */
    for (int p_counter = 0; p_counter < p_height; p_counter++) {
        p_rowPointers[p_height - 1 - p_counter] = p_image + p_counter * p_rowbytes;
    }
    
    /*    Read in the image.    */
    png_read_image(p_pngPTR, p_rowPointers);
    
    free(p_rowPointers);
    fclose(p_stream);
    
    /*    Is it arbitrary, and non power of two?    */
    if (p_width & (p_width * -1) != 0) {
        p_targArgs = GL_TEXTURE_RECTANGLE_ARB;
    }
    else if (p_height & (p_height * -1) != 0) {
        p_targArgs = GL_TEXTURE_RECTANGLE_ARB;
    }
    else {
        p_targArgs = GL_TEXTURE_2D;
    }
    
    /*    Check COLOR settings...    */
    if (p_colorType == PNG_COLOR_TYPE_RGB_ALPHA) {
        p_colArgs = GL_RGBA;
    }
    else if (p_colorType == PNG_COLOR_TYPE_RGB) {
        p_colArgs = GL_RGB;
    }
    
    p_cur_error = PNG_NO_ERR;
    
    p_imageLoaded = TRUE;
    return(TRUE);
}

/*    Clean out PNG data.    */
bool PNG::Flush() {
    if (p_imageLoaded == FALSE) {
        p_cur_error = PNG_BUF_EMPTY;
        return(FALSE);
    }
    
    png_destroy_read_struct(&p_pngPTR, &p_infoPTR, NULL);
    free(p_image);
    p_image = NULL;
    
    p_imageLoaded = FALSE;
    p_cur_error = PNG_NO_ERR;
    return(TRUE);
}

/*    Bind a gl texture.    */
bool PNG::Texture(GLuint p_tex) {
    
    /*    Is the image loaded?    */
    if (p_imageLoaded == FALSE) {
        p_cur_error = PNG_BUF_EMPTY;
        return(FALSE);
    }
    
    /*    Are it's sizes valid?    */
    if ((p_width <= 0) || (p_height <= 0)) {
        p_cur_error = PNG_BAD_TEX;
        return(FALSE);
    }
    
    /*    Make a texture, use the ARB/2D values and color types.    */
    glBindTexture(p_targArgs, p_tex);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(p_targArgs, 0, p_colArgs, p_width, p_height,
                    0, p_colArgs, GL_UNSIGNED_BYTE, p_image);
    
    
    p_cur_error = PNG_NO_ERR;
    return(TRUE);
}

Here's my main file (simple testing one):

Code:
#include <cstdlib>
#include <cstring>
#include <cmath>

#include "GLUT/glut.h"
#include "OpenGL/gl.h"
#include "OpenGL/glu.h"

#include "PNG_class.h"

using namespace std;

PNG myPicture;
GLuint hello;

void init(void)
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClearDepth(0.0);
    glShadeModel(GL_SMOOTH);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_TEXTURE_RECTANGLE_ARB);
    
    myPicture.Open("/hello.png");
    glGenTextures(1, &hello);
    myPicture.Texture(hello);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    glLoadIdentity();
    
    glBindTexture(myPicture.p_targArgs, hello);
    
    glTranslated(0, 0, -3);
    
    glBegin(GL_QUADS);
        glTexCoord2i(0,0);
        glVertex3i(-1, 1, 0);
        
        glTexCoord2i(1,0);
        glVertex3i(1, 1, 0);
        
        glTexCoord2i(1,1);
        glVertex3i(1, -1, 0);
        
        glTexCoord2i(0,1);
        glVertex3i(-1, -1, 0);
    glEnd();
    
    glFlush();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
    glMatrixMode(GL_MODELVIEW);
}


int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutInitWindowSize(320, 240);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("OpenGL");
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
    return(0);
}

But my quad is still white... Blink

Wait... *thought* shouldn't I convert the signature for Big-Endian support? Sneaky

I'll try that.

Thanks for any other plausible problems/solutions you can offer!

EDIT: Nope, sigs are chars... not a good solution.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #10
I know I'm a little late (didn't see this thread before), but when using DevIL, instead of using GL_RGBA in glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); you probably should have used GL_BGRA. (for inverted blue and red channels)

For your libpng demo, is the texture a 2D texture or rectangular texture? You enable both GL_TEXTURE_2D and GL_TEXTURE_RECTANGLE_ARB, and I believe GL_TEXTURE_RECTANGLE_ARB takes precedence. If it's really a 2D texture, it won't display correctly.

BTW, you multiply by -1 to negate some numbers there: the unary - sign works. For example, this would be valid:
p_height & -p_height != 0
It won't make much of a difference, but it would take up a few less cycles. Wink (well, assuming you have optimizations turned on, it actually likely be optimized out. Rasp)
Quote this message in a reply
Jones
Unregistered
 
Post: #11
akb825 Wrote:I know I'm a little late (didn't see this thread before), but when using DevIL, instead of using GL_RGBA in glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); you probably should have used GL_BGRA. (for inverted blue and red channels)

For your libpng demo, is the texture a 2D texture or rectangular texture? You enable both GL_TEXTURE_2D and GL_TEXTURE_RECTANGLE_ARB, and I believe GL_TEXTURE_RECTANGLE_ARB takes precedence. If it's really a 2D texture, it won't display correctly.

BTW, you multiply by -1 to negate some numbers there: the unary - sign works. For example, this would be valid:
p_height & -p_height != 0
It won't make much of a difference, but it would take up a few less cycles. Wink (well, assuming you have optimizations turned on, it actually likely be optimized out. Rasp)

Would it really? I've always done it * -1 because it seemed to be more... correct. Dunno why. Sneaky

I enable both ARB and 2D because the class can handle both, and needs to have both enabled. I'll try removing one...
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #12
If GL_TEXTURE_RECTANGLE_ARB is enabled, GL ignores whether GL_TEXTURE_2D is enabled (GL_TEXTURE_RECTANGLE_ARB takes precedence). Basically, it never makes sense to have more than one enabled at once.
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #13
...on the same texture unit.
Quote this message in a reply
Jones
Unregistered
 
Post: #14
Enabled just 2D (the one I'd need for my test picture), but nothing appears yet. This is strange, and I'm willing to bet it's something really stupid and simple I've completely missed. Rasp
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #15
BTW, did you check your error values? Perhaps you just didn't successfully open the texture.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL ES Texture Masking airfire 6 14,533 Mar 17, 2014 07:07 PM
Last Post: baioses
  OpenGL ES Texture Compression ajrs84 9 3,898 May 7, 2013 03:36 PM
Last Post: ajrs84
  OpenGL ES Texture Masking dalasjoe sin 0 3,810 Apr 13, 2012 12:17 AM
Last Post: dalasjoe sin
  Texture in OpenGL ES 2 looks pixelated vunterslaush 18 22,799 Aug 30, 2011 09:44 PM
Last Post: Frogblast
  Another beginner's question about displaying an animated object superlemonster 2 4,767 Jan 28, 2011 08:03 AM
Last Post: OptimisticMonkey