stbi_image

I’ve used stbi_image to load a PNG image with an alpha channel and I get this:

Here’s my code, small project but one of my first OpenGL ones!


#include <cstdlib>
#include <cstdio>
#include <GL/freeglut.h>
#include <GL/glu.h>
#include "stb_image.h"

unsigned char * data;
int width = 256;
int height = 256;
int bitdepth = 4;
GLuint texture;

int x = 10;
int y = 10;
int fx = 0;
int fy = 0;
int gravity = 0;
unsigned char keys[256];

void processKeys(int timer)
{
    if (keys['a'])
    {
        fx -= 2;
    }

    if (keys['d'])
    {
        fx += 2;
    }

    if (keys['w'])
    {
        fy -= 2;
    }

    if (keys['s'])
    {
        fy += 2;
    }

    if (keys['e'])
    {
        fx = 0;
        fy = 0;
    }
    glutTimerFunc(10, processKeys, timer);
}

void tick(int timer)
{
    glutPostRedisplay();
    glutTimerFunc(10, tick, timer);
}

void physics(int timer)
{
    if (y < 980)
    {
        gravity = 1;
    }
    else
    {
        gravity = 0;
    }
    x += fx;
    y += fy + gravity;
    /*if (fx > 0)
    {
        fx -= 1;
    }
    else if (fx < 0)
    {
        fx += 1;
    }
    if (fy > 0)
    {
        fy -= 1;
    }
    else if (fy < 0)
    {
        fy += 1;
    }*/
    if (x > 980)
    {
        // rebound off the right edge
        fx = 0 - fx;
    }
    if (x < 0)
    {
        // rebound off the left edge
        fx = 0 - fx;
    }
    if (y > 980)
    {
        // rebound off the bottom edge
        fy = 0 - fy;
    }
    if (y < 0)
    {
        // rebound off the top edge
        fy = 0 - fy;
    }
    glutTimerFunc(10, physics, timer);
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glBindTexture(GL_TEXTURE_2D, texture);
    glBegin(GL_POLYGON);
    glVertex2i(x, y);
    glTexCoord2i(x, y);
    glVertex2i(x, y + 256);
    glTexCoord2i(x, y + 256);
    glVertex2i(x + 256, y + 256);
    glTexCoord2i(x + 256, y + 256);
    glVertex2i(x + 256, y);
    glTexCoord2i(x + 256, y);
    glEnd();
    glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{
    keys[key] = true;
}

void keyboardUp(unsigned char key, int x, int y)
{
    keys[key] = false;
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Physics Engine");
    gluOrtho2D(0, 1000, 1000, 0);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutTimerFunc(10, physics, 1);
    glutTimerFunc(10, tick, 2);
    glutTimerFunc(10, processKeys, 3);
    // Start texture load
    data = stbi_load("texture.png", &width, &height, &bitdepth, 0);
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    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, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    // End texture load
    glutMainLoop();
}

Any suggestions would be greatly appreciated as I’m struggling considerably with loading textures. :frowning:

(No “use <x> library” posts please)

Another screenshot this time slightly different “error”!

For the record, the image is just a transparent one that says “DAN” in big red letters. The image has dimensions of 256x256, is PNG format and has an alpha channel.

Hi,
There are a couple of things wrong in your code.

  1. The texture coordinates are specified before the vertex call but you are giving them after the vertex call. Thus the texture coordinates are offset by one vertex.
  2. Your texture coordinates are specified in integer coordinates. In that case, u have to do this (ref: http://www.gamedev.net/topic/474881-diff-btw-gltexcoord2i-and-gltexcoord2f/)

glMatrixMode(GL_TEXTURE);
glLoadIdentity();
   glScalef(1.0/256., 1/256., 1);

Instead a much efficient method is to use the float overload (glTexCoord2f) like this,


glTexCoord2f(0., 0.);  glVertex2i(x, y);
glTexCoord2f(0., 1.);  glVertex2i(x, y + 256);
glTexCoord2f(1., 1.);  glVertex2i(x + 256, y + 256);
glTexCoord2f(1., 0.);  glVertex2i(x + 256, y);

See if this helps,
Mobeen

PS: I don’t think you need so many timers? and you are continuously attaching them? Remove them and instead create an idle func. like this


void OnIdle() {
   processKeys();
   glutPostRedisplay();
}

in main attach the callback like this,

glutIdleFunc(OnIdle);

Excellent, thanks for the tips, I’ll amend my code and see what happens.

New error, reminds me of static on a television.


#include <cstdlib>
#include <cstdio>
#include <GL/freeglut.h>
#include <GL/glu.h>
#include "stb_image.h"

unsigned char * data;
int width = 256;
int height = 256;
int bitdepth = 4;
GLuint texture;

int x = 10;
int y = 10;
int fx = 0;
int fy = 0;
int gravity = 0;
unsigned char keys[256];

void processKeys()
{
    if (keys['a'])
    {
        fx -= 2;
    }

    if (keys['d'])
    {
        fx += 2;
    }

    if (keys['w'])
    {
        fy -= 2;
    }

    if (keys['s'])
    {
        fy += 2;
    }

    if (keys['e'])
    {
        fx = 0;
        fy = 0;
    }
}

void physics(int timer)
{
    if (y < 980)
    {
        gravity = 1;
    }
    else
    {
        gravity = 0;
    }
    x += fx;
    y += fy + gravity;
    /*if (fx > 0)
    {
        fx -= 1;
    }
    else if (fx < 0)
    {
        fx += 1;
    }
    if (fy > 0)
    {
        fy -= 1;
    }
    else if (fy < 0)
    {
        fy += 1;
    }*/
    if (x > 980)
    {
        // rebound off the right edge
        fx = 0 - fx;
    }
    if (x < 0)
    {
        // rebound off the left edge
        fx = 0 - fx;
    }
    if (y > 980)
    {
        // rebound off the bottom edge
        fy = 0 - fy;
    }
    if (y < 0)
    {
        // rebound off the top edge
        fy = 0 - fy;
    }
    glutTimerFunc(10, physics, timer);
}

void idle()
{
    processKeys();
    glutPostRedisplay();
}

void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glBindTexture(GL_TEXTURE_2D, texture);
    glBegin(GL_POLYGON);
    glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
    glEnd();
    glutSwapBuffers();
}

void keyboard(unsigned char key, int x, int y)
{
    keys[key] = true;
}

void keyboardUp(unsigned char key, int x, int y)
{
    keys[key] = false;
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(0, 0);
    glutInitWindowSize(400, 400);
    glutCreateWindow("Physics Engine");
    //gluOrtho2D(0, 1000, 1000, 0);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutKeyboardUpFunc(keyboardUp);
    glutTimerFunc(10, physics, 1);
    glutIdleFunc(idle);
    // Start texture load
    data = stbi_load("texture.png", &width, &height, &bitdepth, 0);
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    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, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    // End texture load
    glutMainLoop();
}

Ur code looks ok to me. Are u sure that the image is 32 bit RGBA format. I think you remove this call in display

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

and also move glEnable(GL_TEXTURE_2D) call to main before u first bind the texture.

Still no change. :expressionless:

This image is PNG format, I’m certain it’s RGBA 32-bit, too.

Edit:

Perhaps you could give me an extract from a piece of code you’ve written so I can compare/study it, as long as you know it works of course.

Oh, I just cried with happiness!

I ran the program from the terminal instead of through Netbeans and it works fine except the texture is upside down (i’m sure I can figure that one out myself)

THANKS MOBEEN! I appreciate it so much! overjoyed

Final question!

the code you posted:


glTexCoord2f(0., 0.);  glVertex2i(x, y);
glTexCoord2f(0., 1.);  glVertex2i(x, y + 256);
glTexCoord2f(1., 1.);  glVertex2i(x + 256, y + 256);
glTexCoord2f(1., 0.);  glVertex2i(x + 256, y);

I assume that will make the texture stretch to the full size of the vertices?

Oh I see, no it won’t.

I’d have to use -1 to 1 mapping to do that, right?

Edit: nevermind, I forgot to change gluOrtho2D()! Texture appears normal size now, thankyou again. :slight_smile: