8
$\begingroup$

This question has an answer here:
https://stackoverflow.com/questions/42596516/generating-mipmaps-manually
It was a silly mistake. Sorry for the inconvenience.

OpenGL is fairly difficult to learn.
According to my understanding of mipmaps, I can set each mipmap level manually, so I could change the image to use when my texture looks greater or smaller.

I tried the following code but doesn't matter the size of the triangle, it always take the first mipmap level. Why? if the triangle is closer to any other mipmap level, why does not take it?

I really hate putting a bunch of code in my questions because I force others to waste time analyzing the code instead of putting the most revelant snippet code, but I don't know where is the problem and I have not alternative. Sorry :(

#include <iostream>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

const GLchar* VERTEX_SHADER_SOURCE =
        "#version 330 core                           \n"
        "layout (location = 0) in vec2 position;     \n"
        "layout (location = 1) in vec2 myTexCoord;   \n"
        "                                            \n"
        "out vec2 TexCoord;                          \n"
        "                                            \n"
        "void main()                                 \n"
        "{                                           \n"
        "    gl_Position = vec4(position,0.0f, 1.0f);\n"
        "    TexCoord = myTexCoord;                  \n"
        "}                                           \n";

const GLchar* FRAGMENT_SHADER_SOURCE =
        "#version 330 core                         \n"
        "in vec2 TexCoord;                         \n"
        "                                          \n"
        "out vec4 color;                           \n"
        "                                          \n"
        "uniform sampler2D ourTexture;             \n"
        "                                          \n"
        "void main()                               \n"
        "{                                         \n"
        "    color = texture(ourTexture, TexCoord);\n"
        "}                                         \n";

int main()
{
    //INIT STUFFS
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    GLFWwindow* window = glfwCreateWindow(800, 600, "", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewExperimental = GL_TRUE;
    glewInit();
    glViewport(0, 0, 800, 600);



    //THE MOST INTERESTING PART
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    //Our image for the mipmap with level 0 and white color
    //The dimensions are 200 x 200 and is multiplied by 3 because I defined R,G and B colors
    unsigned char imageArray[200*200*3];
    for(int i = 0; i < 200*200*3; i++){
        imageArray[i] = 255;
    }

    //Our image for the mipmap with level 1-8 and blue color
    unsigned char imageArray2[100*100*3];
    for(int i = 0; i < 100*100*3; i++){
        if((i+1)%3 == 0)
            imageArray2[i] = 255;
        else
            imageArray2[i] = 0;
    }

    //All mipmap levels
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 200, 200, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);
    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 100, 100, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 50,  50,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 25,  25,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 13,  13,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 7,   7,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    //If I comment the line above and uncomment the following, the program will show a black triangle. Why?
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);

    GLfloat vertices[] =
    //(un)comment the first and second lines of vertex coords to swap between a bigger or smaller triangle
    //It doesn't matter, this program always take the first mipmap level
    //But... Why? the triangle should be closer to any other mipmap level :( why does not take it?
    {
//          -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,      //Bigger triangle
            -0.05f, -0.05f, 0.05f, -0.05f, 0.0f, 0.05f, //Smaller triangle
            -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f       //Triangle's texture coordinates
    };



    //VAOs AND VBOs
    GLuint VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);



    //SHADERS
    GLuint program;
    GLuint vertex, fragment;

    vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, &VERTEX_SHADER_SOURCE, NULL);
    glCompileShader(vertex);

    fragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment, 1, &FRAGMENT_SHADER_SOURCE, NULL);
    glCompileShader(fragment);

    program = glCreateProgram();
    glAttachShader(program, vertex);
    glAttachShader(program, fragment);
    glLinkProgram(program);

    glDeleteShader(vertex);
    glDeleteShader(fragment);
    glUseProgram(program);



    //DRAWING OUR TRIANGLE
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLES, 0,3);
    glfwSwapBuffers(window);
    while (!glfwWindowShouldClose(window))
        glfwPollEvents();



    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glfwTerminate();
    return 0;
}


For any reason, these two lines doesn't work together

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);

EDIT:

I think that the two lines above doesn't work because mipmaps only works with GL_TEXTURE_MIN_FILTER. However, when I replace

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//If I comment the line above and uncomment the following, the program will show a black triangle. Why?
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);

with

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

it shows a black triangle :(

I used glGetError as Dan Hulme stated in the comments but with the last change I made to my code I have not errors returned by glGetError but still showing a black triangle.

EDIT 2:

I solved the problem setting the sizes by powers of 2. However, it now takes only the first mipmap level. Here is the new source code:

#include <iostream>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

const GLchar* VERTEX_SHADER_SOURCE =
        "#version 330 core                           \n"
        "layout (location = 0) in vec2 position;     \n"
        "layout (location = 1) in vec2 myTexCoord;   \n"
        "                                            \n"
        "out vec2 TexCoord;                          \n"
        "                                            \n"
        "void main()                                 \n"
        "{                                           \n"
        "    gl_Position = vec4(position,0.0f, 1.0f);\n"
        "    TexCoord = myTexCoord;                  \n"
        "}                                           \n";

const GLchar* FRAGMENT_SHADER_SOURCE =
        "#version 330 core                         \n"
        "in vec2 TexCoord;                         \n"
        "                                          \n"
        "out vec4 color;                           \n"
        "                                          \n"
        "uniform sampler2D ourTexture;             \n"
        "                                          \n"
        "void main()                               \n"
        "{                                         \n"
        "    color = texture(ourTexture, TexCoord);\n"
        "}                                         \n";

int main()
{
    //Change the value of size by 1,2,4,8,16,32,64,128 or 256 and see how the color of the triangle doesn't change. Why does it happen?
    GLint size = 128;

    //INIT STUFFS
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    GLFWwindow* window = glfwCreateWindow(size,size, "", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glewExperimental = GL_TRUE;
    glewInit();
    glViewport(0, 0,size,size);



    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    //Our image for the mipmap with odd level and green color
    //The dimensions are 256 x 256 and is multiplied by 3 because I defined R,G and B colors
    unsigned char imageArray[256*256*3];
    for(int i = 0; i < 256*256*3; i++){
        if((i+2)%3 == 0)
            imageArray[i] = 255;
        else
            imageArray[i] = 0;
    }

    //Our image for the mipmap with pair level and red color
    unsigned char imageArray2[256*256*3];
    for(int i = 0; i < 256*256*3; i++){
        if(i%3 == 0)
            imageArray2[i] = 255;
        else
            imageArray2[i] = 0;
    }

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 8);

    //All mipmap levels defined by hand
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);
    glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 64,  64,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);
    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 32,  32,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 4, GL_RGB, 16,  16,  0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);
    glTexImage2D(GL_TEXTURE_2D, 5, GL_RGB, 8,   8,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 6, GL_RGB, 4,   4,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);
    glTexImage2D(GL_TEXTURE_2D, 7, GL_RGB, 2,   2,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray2);
    glTexImage2D(GL_TEXTURE_2D, 8, GL_RGB, 1,   1,   0, GL_RGB, GL_UNSIGNED_BYTE, imageArray);

    GLfloat vertices[] = {
            -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f,  //vertex coordinates
            0.0f, 0.0f                              //Triangle's texture coordinates
    };



    //VAOs AND VBOs
    GLuint VAO, VBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)(sizeof(GLfloat)*3*2));

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);



    //SHADERS
    GLuint program;
    GLuint vertex, fragment;

    vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, &VERTEX_SHADER_SOURCE, NULL);
    glCompileShader(vertex);

    fragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment, 1, &FRAGMENT_SHADER_SOURCE, NULL);
    glCompileShader(fragment);

    program = glCreateProgram();
    glAttachShader(program, vertex);
    glAttachShader(program, fragment);
    glLinkProgram(program);

    glDeleteShader(vertex);
    glDeleteShader(fragment);
    glUseProgram(program);



    //DRAWING OUR TRIANGLE
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLES, 0,3);
    glfwSwapBuffers(window);
    while (!glfwWindowShouldClose(window))
        glfwPollEvents();



    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glfwTerminate();
    return 0;
}


$\endgroup$
4
  • $\begingroup$ Unrelated, but your imageArray2 loop would be faster as for (int i = 0; i < 100 * 100 * 3; i += 3) { imageArray2[i] = 0; imageArray2[i + 1] = 0; imageArray[i + 2] = 255; } because it avoids a division inside the loop. I think it's clearer this way too. $\endgroup$
    – Dan Hulme
    Commented Mar 3, 2017 at 10:35
  • 2
    $\begingroup$ Obviously mipmaps are turned off in the program as-is: the thing you're debugging is why you get a black screen when you uncomment the line that turns them on. First rule of GL debugging is to use glGetError everywhere and see if any of the gl* function calls are failing. $\endgroup$
    – Dan Hulme
    Commented Mar 3, 2017 at 10:37
  • $\begingroup$ @Dan Hulme How can I turn on mipmaps? The tutorial I'm following doesn't make mention of how to turn on/off mipmaps. $\endgroup$
    – Adrian
    Commented Mar 3, 2017 at 23:36
  • 1
    $\begingroup$ Setting the GL_TEXTURE_MIN_FILTER to GL_NEAREST means the mipmaps won't be used, which is why you only see level 0 when you do this. $\endgroup$
    – Dan Hulme
    Commented Mar 4, 2017 at 9:47

1 Answer 1

3
$\begingroup$

You need to round down the mipmap sizes. In your case the correct sequence is 200, 100, 50, 25, 12, 6, 3, 1.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.