0
votes

I'm having problem rendering a texture in OpenGL. I'm getting a white color instead of the texture image but my rectangle and the whole context is working fine. I'm using the stbi image loading library and OpenGL 3.3.

Before rendering:

glViewport(0, 0, ScreenWidth, ScreenHeight);

glClearColor(0.2f, 0.0f, 0.0f, 1.0f);

int Buffer;
glGenBuffers(1, &Buffer);
glBindBuffer(GL_ARRAY_BUFFER, Buffer);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

Loading the Texture:

unsigned char *ImageData = stbi_load(file_name, 1024, 1024, 0, 4); //not sure about the "0" parameter

int Texture;
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, x, y, 0, GL_RGB, GL_UNSIGNED_BYTE, ImageData);

stbi_image_free(ImageData);

Rendering:

glClear(GL_COLOR_BUFFER_BIT);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Texture);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 6 * 3); //a rectangle which is rendered fine
glDisableVertexAttribArray(0);

I am looking for a very minimalistic and simple solution.

2
Post a SSCCE.genpfault

2 Answers

2
votes

First of all, take a second to look at the function declaration for stbi_load (...):

unsigned char *stbi_load (char const *filename,
                          int        *x,    // POINTER!!
                          int        *y,    // POINTER!!
                          int        *comp, // POINTER!!
                          int         req_comp)

Now, consider the arguments you have passed it:

file_name (presumably a pointer to a C string)
1024      (definitely NOT a pointer)
1024      (definitely NOT a pointer)
0         (definitely NOT a pointer)

The whole point of passing x, y and comp as pointers is so that stbi can update their values after it loads the image. This is the C equivalent of passing by reference in a language like C++ or Java, but you have opted instead to pass integer constants that the compiler then treats as addresses.

Because of the way you call this function, stbi attempts to store the width of the image at the address: 1024, the height of the image at address: 1024 and the number of components at address: 0. You are actually lucky that this does not cause an access violation or other bizarre behavior at run-time, storing things at arbitrary addresses is dangerous.

Instead, consider this:

GLuint ImageX,
       ImageY,
       ImageComponents;

GLubyte *ImageData = stbi_load(file_name, &ImageX, &ImageY, &ImageComponents, 4);

[...]

glTexImage2D (GL_TEXTURE_2D,    0, GL_RGBA8,
                ImageX, ImageY, 0, GL_RGBA, GL_UNSIGNED_BYTE, ImageData);

// ~~~~ You are requesting 4 components per-pixel from stbi, so this is RGBA!
1
votes

It's been a while since I've done OpenGL but aside from a few arbitrary calls, the main issue I'd guess is that you're not calling glEnable(GL_TEXTURE_2D);before you make the call to draw your function. Afterwards it is wise to call glDisable(GL_TEXTURE_2D); as well to avoid potential future conflicts.