PDA

View Full Version : stbi_image



Daniel Harrison
01-12-2011, 05:44 PM
I've used stbi_image to load a PNG image with an alpha channel and I get this:

http://img651.imageshack.us/img651/1559/64561094.png

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(&amp;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", &amp;width, &amp;height, &amp;bitdepth, 0);
glGenTextures(1, &amp;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. :(

(No "use <x> library" posts please)

Daniel Harrison
01-12-2011, 05:48 PM
Another screenshot this time slightly different "error"!
http://img266.imageshack.us/img266/4581/10229946.png

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.

mobeen
01-12-2011, 09:57 PM
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);

Daniel Harrison
01-13-2011, 06:02 AM
Excellent, thanks for the tips, I'll amend my code and see what happens.

Daniel Harrison
01-13-2011, 06:19 AM
New error, reminds me of static on a television.
http://img338.imageshack.us/img338/4225/99799563.png



#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(&amp;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", &amp;width, &amp;height, &amp;bitdepth, 0);
glGenTextures(1, &amp;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();
}

mobeen
01-13-2011, 08:46 AM
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.

Daniel Harrison
01-13-2011, 09:01 AM
Still no change. :|

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.

Daniel Harrison
01-13-2011, 09:24 AM
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*

Daniel Harrison
01-13-2011, 09:37 AM
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?

Daniel Harrison
01-13-2011, 09:39 AM
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. :)