Search code examples
c++openglsdlglew

OpenGL compute level of detail


i've tried to render some Lines to a texture and then mipmap them. But when I scale down the whole thing it is not as low detailed as I want to. How can I achieve a lower resolution of the Texture? I tried a triangle with a little bend. So when I scale down like 50% it shall look like a normal triangle. Is there anyway to render it like this? Since I have really low experience with OpenGL I will post you the whole code. Version: Glew 2.1.0 OpenGL 4.6

Code:

    SDL_Window* window;
    SDL_Init(SDL_INIT_EVERYTHING);

    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    window = SDL_CreateWindow("BA", SDL_WINDOWPOS_CENTERED, 
    SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_OPENGL);

    SDL_GLContext glContext = SDL_GL_CreateContext(window);

    std::vector<Vertex> vertices;
    vertices.push_back(Vertex{ -0.5f,-0.5f });
    vertices.push_back(Vertex{ 0.0f,0.8f });
    vertices.push_back(Vertex{ 0.0f,0.8f });
    vertices.push_back(Vertex{ 0.0f,0.5f });
    vertices.push_back(Vertex{ 0.0f,0.5f });
    vertices.push_back(Vertex{ 0.5f, -0.5f });
    vertices.push_back(Vertex{ 0.5f, -0.5f });
    vertices.push_back(Vertex{ -0.5f,-0.5f });



    GLenum err = glewInit();

    //Framebuffer
    GLuint FramebufferName = 0;
    glGenFramebuffers(1, &FramebufferName);
    glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);


    //Texture
    GLuint renderedTexture;
    glGenTextures(1, &renderedTexture);
    glBindTexture(GL_TEXTURE_2D, renderedTexture);
    

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    /*glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);*/

    glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);

    float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);


    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);

    // Set the list of draw buffers.
    GLenum DrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
    glDrawBuffers(1, DrawBuffers);

    glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
    glViewport(0, 0, 1920, 1080);


    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(struct Vertex, x));

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, 1920, 1080);


    glScalef(0.9f, 0.9f, 1.0f);
    glTranslatef(1.0f, 1.0f, 0.0f);
    

    bool closeFlag = false;
    while (!closeFlag) {


        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_LINES, 0, vertices.size());

        SDL_GL_SwapWindow(window);

        /*GLenum error = glGetError();
        std::cout << "Error: " << error;*/

        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                closeFlag = true;
            }
            if (event.key.keysym.sym == SDLK_DOWN) {
                glScalef(0.95f, 0.95f, 1.0f);

            }
            if (event.key.keysym.sym == SDLK_UP) {
                glScalef(1.05f, 1.05f, 1.0f);
            }
        }
    }

Output: Actual Output

Desired output: Desired output


Solution

  • First read the description of glGenerateMipmap.
    For a deeper understanding of mipmapping and how it is implemented: OpenGl Specification 8.14.3 Mipmapping

    In order to reach (see) your desired result, you would have to zoom more out. Down the way, there could be a reduced image, which is what you expect.

    Fine-tuning of texture filtering can be accomplished via glTexParameter and the different parameters like:

    • GL_TEXTURE_BASE_LEVEL
    • GL_TEXTURE_LOD_BIAS
    • GL_TEXTURE_MIN_FILTER
    • GL_TEXTURE_MAG_FILTER
    • GL_TEXTURE_MIN_LOD
    • GL_TEXTURE_MAX_LOD
    • GL_TEXTURE_MAX_LEVEL

    You could also generate the mipmaps yourself via glTexStorage2D and glTexSubImage2D but this requires two texture objects and multiple render steps (render reduced image into texture A, upload into specific level of texture B; see also glCopyTexImage2D, glCopyTexSubImage2D).

    You could also do Geometry LOD (more here).