OpenGL 3.3 textures only black

Hi everyone,

I’m trying to learn OpenGL. I am able to render a triangle with fixed colors, but when I tried adding textures I only get black colors:

Main App:


    //TEXTURE
    glEnable(GL_TEXTURE_2D);
    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_STATIC_DRAW);
    //Attributes
    int tex_coords_index = glGetAttribLocation(program, "texCoords");
    glEnableVertexAttribArray(tex_coords_index);
    glVertexAttribPointer(tex_coords_index, 2, GL_FLOAT, GL_FALSE, 0, 0);
    //Image
    int width, height;
    unsigned char *image = SOIL_load_image("c:/image.png", &width, &height, 0, GL_RGB);
    glGenTextures(1, &tex);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
    //Uniform
    int sampler2D = glGetUniformLocation(program, "tex");
    glUniform1i(sampler2D, 0);

Shaders:


    char *vertex_shader_source = {

    "#version 330 core
"
    "in vec3 vertices;"
    "in vec2 texCoords;"
    "out vec2 ftexCoords;"
    "void main(){"
    "   gl_Position = vec4(vertices, 1.0f);"
    "   ftexCoords = texCoords;"
    "}"

    };

    char *fragment_shader_source = {

    "#version 330 core
"
    "in vec2 ftexCoords;"
    "out vec4 out_color;"
    "uniform sampler2D tex;"
    "void main(){"
    "    out_color = texture(tex, ftexCoords);"
    //"    out_color = vec4(0.0, 1.0, 0.0, 1.0);"
    "}"

    };

Any feedbacks and suggestions will be greatly appreciated.

Thanks.

A few things stand out:

This is only meaningful for the fixed-function pipeline. It isn’t relevant when using shaders, and isn’t valid in the core profile.

GL_RGB isn’t valid as the force_channels parameter to SOIL_load_image? Did you mean to use SOIL_LOAD_RGB instead? Or SOIL_LOAD_RGBA (see below)?

Also, you aren’t checking the return value. Passing NULL to glTexImage2D() is valid; it creates the texture with the specified format and dimensions but the contents will be undefined.

Above, you appear to be trying to load the image as RGB, but you’re then telling glTexImage2D() that the data is RGBA.

Hi GClements,

Thanks for the reply. I tried updating my code, but still getting the black textures. See my updated code below:


    //TEXTURE
    glGenBuffers(1, &tbo);
    glBindBuffer(GL_ARRAY_BUFFER, tbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(tex_coords), tex_coords, GL_STATIC_DRAW);
    //Attributes
    int tex_coords_index = glGetAttribLocation(program, "texCoords");
    glEnableVertexAttribArray(tex_coords_index);
    glVertexAttribPointer(tex_coords_index, 2, GL_FLOAT, GL_FALSE, 0, 0);
    //Image
    int width, height;
    unsigned char *image = SOIL_load_image("c:/toyo.png", &width, &height, 0, SOIL_LOAD_RGB);
    glGenTextures(1, &tex);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    //Uniform
    int sampler2D = glGetUniformLocation(program, "tex");
    glUniform1i(sampler2D, 0);

Also I did not find any return value for glTexImage2D.

Thanks again for the reply.

glTexImage2D() doesn’t have a return value. OpenGL errors are only reported by calling glGetError().

It’s the return value of SOIL_load_image() you should be checking.

Hi GClements,

I was able to make the texture appear. What happened was I did not include texture parameters:


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

I mistakenly assumed that OpenGL have default values for these parameters. I got it working now. The only thing weird is the image is upside down. I remedied it by flipping the y-coordinates for my texture coordinates.

It does have default values. But the default value for GL_TEXTURE_MIN_FILTER is GL_NEAREST_MIPMAP_LINEAR, which requires all mipmap levels to be defined (either by uploading them explicitly or using glGenerateMipmap() to generate them from the base level).

The first pixel on the first row of the texture data is at the corner with texture coordinates (0,0). If the texture data is stored with the top row first, texture coordinates (0,0) will be the top-left corner of the texture. Window coordinates have (0,0) at the bottom-left corner, normalised device coordinates have (-1,-1) at the bottom-left corner of the viewport, so if texture coordinates have the same orientation as window coordinates and normalised device coordinates, top-row-first textures will be upside-down.