Reputation: 7735
This is a simplified version of my exact code,
I'm expecting to see all red(as I'm setting only red to 255,others to 0), but actually got this:
#include <GLUT/glut.h>
static GLuint texture;
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2, 2, -2, 2, -2, 2);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
static void callback(unsigned char *data, long width, long height) {
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
int i,j;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
data[i * 3 * width + 3 * j] = 255;
data[i * 3 * width + 3 * j + 1] = 0;
data[i * 3 * width + 3 * j + 2] = 0;
}
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
}
void init() {
glClearColor(0, 0, 0, 0);//RGBA
}
void display() {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
unsigned char data[3 * 350 * 168];
callback(data, 350, 168);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);glVertex2f(-2, -2);
glTexCoord2f(0, 1);glVertex2f(-2, 2);
glTexCoord2f(1, 1);glVertex2f(2, 2);
glTexCoord2f(1, 0);glVertex2f(2, -2);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH|GLUT_RGBA);
glutInitWindowSize(512, 512);
glutInitWindowPosition(100, 100);
glutCreateWindow("hello world texture window");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutIdleFunc(display);
init();
glutMainLoop();
return 0;
}
What am I doing wrong here?
Upvotes: 1
Views: 94
Reputation: 474066
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
There's your problem. This is a common, though subtle, mistake.
You told OpenGL that you would be providing color data with three components: R, G, and B. You said that each component is an UNSIGNED_BYTE
in size.
But you also told OpenGL something else. Something not mentioned in the function call. Namely, the alignment of the individual rows of pixel data. The default row alignment is 4. This means OpenGL will assume that every row's byte width will be padded out to four bytes.
That's especially important because your row width is 350. 350 * 3 bytes per pixel is 1050 bytes. Which is not divisible by four. This means that OpenGL will assume that each row takes up 1052 bytes. Hence the color screwup; this is why the pattern repeats. It's also why you get garbage pixels in the upper right (since OpenGL puts the first row on the bottom, it's reading garbage from memory for the top few pixels).
You need to set the alignment whenever you upload pixel data (mostly just to make sure it's set to what you need it to be). This is done with glPixelStorei:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
This sets the row alignment to 1. Essentially, it's unaligned.
Alternatively, you can simply upload GL_RGBA data, which will always be 4-byte aligned. Then you won't have to worry about it.
Upvotes: 8