Texture not getting rendered, only black triangle

Hello guys, I’m using opengl 4.5.0 and this is what my code looks like :

int main(void)
{
    ios_base::sync_with_stdio(0);
    if(glfwInit())
        cout<<"glfw success init\n";
    else cout<<"error in glfw init\n";

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwSetErrorCallback(error_callback);

    GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);

    if (!window)
        cout<<"Window (OPENGL Context) creation failed"<<endl;
    else cout<<"Window (OPENGL Context) creation success"<<endl;

    glfwMakeContextCurrent(window);
    gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);

    if(gladLoadGL())
        cout<<"gladloadgl true\n";
    else cout<<"gladloadgl false\n";
    glfwSetKeyCallback(window, key_callback);
    debugLog();
    //opengl context established -------------------------------------

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);

    double time = glfwGetTime();
    cout<<"time = "<<time<<endl;
    glfwSwapInterval(0);

    //shader code
    const char* vertexShader[] = {
        "#version 450 core \n",
        "layout(location=0) in vec2 pos; \n",
        "layout(location=1) in vec2 aTexCoord; \n",
        "out vec2 TexCoord; \n",
        "void main(void){ \n",
            "gl_Position = vec4(pos, 0.0, 1.0); \n",
            "TexCoord = aTexCoord; } \n"
    };
    const char* fragmentShader[] = {
        "#version 450 core \n",
        "in vec2 TexCoord; \n",
        "uniform sampler2D ourTexture; \n",
        "out vec4 color; \n",
        "void main(void){ \n",
        "color = texelFetch(ourTexture, ivec2(gl_FragCoord.xy), 0); } \n"
    };


    //Load Textures
    int texWidth, texHeight, nrChannels;
    unsigned char *data = stbi_load("container.bmp", &texWidth, &texHeight, &nrChannels, 0);
    if(data)
    {
        cout<<"Texture Data Loaded \n";
        cout<<"  > width of tex : "<<texWidth<<", height = "<<texHeight<<", color channels : "<<nrChannels<<"\n";
    }
    else cout<<"Texture Data Failed to Load \n";
    //Texture Loader Done
       //Generate Texture
    cout<<"trying to generate texture \n";
    unsigned int texture;
    glCreateTextures(GL_TEXTURE_2D, 1, &texture);
    glTextureStorage2D(texture, 1, GL_RGB32F, texWidth, texHeight);
    glBindTexture(GL_TEXTURE_2D, texture);
    if(data)
    {
        glTextureSubImage2D(texture, 0, 0, 0, texWidth, texHeight, GL_RGB32F, GL_FLOAT, data);
        cout<<"texture generated \n";
    }
    else cout<<"failed to load tex : "<<endl;
    stbi_image_free(data);
    //End of Texture code

    //Vertex Shader compilation
    GLuint vertex_shader = loadAndCompileShader(GL_VERTEX_SHADER, vertexShader, 7);
    if(!vertex_shader){
        cout<<"   Vertex Shader Failed \n";
        return -1;
    }else cout<< " Vertex Shader Compiled \n";
    //Fragment Shader compilation
    GLuint fragment_shader = loadAndCompileShader(GL_FRAGMENT_SHADER, fragmentShader, 6);
    if(!fragment_shader){
        cout<<"   Fragment Shader Failed \n";
        return -1;
    } else cout<<" Fragment Shader Compiled \n";
    //Shaders Successfully compiled



    GLuint program = glCreateProgram();

    glAttachShader(program, vertex_shader);
    glAttachShader(program, fragment_shader);

    glLinkProgram(program);

    GLint isLinked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
    if (isLinked == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);

        // The maxLength includes the NULL character
        vector<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
        cout<<"\n linking failed reason : ";
        for(int i=0; i<infoLog.size();i++)
            cout<<infoLog[i];
        // The program is useless now. So delete it.
        glDeleteProgram(program);

        // Provide the infolog in whatever manner you deem best.
        // Exit with failure.
        return -1;
    }

    glDetachShader(program, vertex_shader);
    glDetachShader(program, fragment_shader);

        //pos           //tex
    float vertices[] = {
        +0.0f, +0.5f,   0.5f, 1.0f,   //top
        -0.5f, -0.5f,   0.0f, 0.0f,   //left
        +0.5f, -0.5f,   1.0f, 0.0f    //right
    };

    //load vertices into GPU vertex buffer
    GLuint vbo;
    glCreateBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, 12*sizeof(float) , &vertices[0], GL_STATIC_DRAW);


    //specify layout
    GLuint vao;
    glCreateVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), (void*)0); //vertex
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), (void*)(2*sizeof(float))); //texture
    glEnableVertexAttribArray(1);

    glUseProgram(program);

    while (!glfwWindowShouldClose(window)){
        time = glfwGetTime();
        float _ratio;
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        _ratio = width / (float) height;
        glViewport(0, 0, width, height);

        const float colors[] = {1.0f, 1.f, 1.0f, 1.0f};
        glClearBufferfv(GL_COLOR, 0, colors);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glfwPollEvents();
        glfwSwapBuffers(window);
        cout<<(glfwGetTime() - time)<<"\n";
    }
    glfwDestroyWindow(window);

    glfwTerminate();
    exit(EXIT_SUCCESS);
    return 0;
}

Note that upon executing this program, all the shaders compile successfully and i can see triangle drawn onto the screen however its completely black.

I earlier tried with .jpg format and then changed to .bmp yet it doesnt work so please do let me know what im doing wrong. :frowning:
Thanks in advance :slight_smile:

(Note that texture is getting loaded in memory so that is not the issue)

I doubt that stbi_load is returning data in this format. It’s probably either GL_RGB8 or GL_RGBA8, depending upon whether the texture has an alpha channel (see the nrChannels variable, or use the last argument to stbi_load to force a specific number of channels.
Try

glTextureSubImage2D(texture, 0, 0, 0, texWidth, texHeight, GL_RGB8, GL_UNSIGNED_BYTE, data);

Thanks for replying, so i tried what you said but still its a black triangle, and the nrChannel is showing value of “3”, but anyway i still changed last parameter to force 3 externally.

Now, regarding format, once i tried your GL_RGB8 method which didn’t worked, i tried to make a new texture in MS-Paint and save it as ‘256-COLOR’ bmp format yet its completely black.

well, there are some improper codes in your post, but the major error is glTextureSubImage2D should use “format” not “sized format”, so, for the texture you created, allocate the storage with GL_RGB8, and upload data with GL_RGB in glTextureSubImage2D should solve your problem.
and don’t forget to add glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); after the texture is bound if the issue is not fixed.

1 Like