OpenGL 计算细节层次

OpenGL compute level of detail

我尝试将一些线条渲染到纹理,然后对它们进行 mipmap。但是当我缩小整个事情时,它并没有我想要的那么详细。如何获得较低的纹理分辨率?我尝试了一个稍微弯曲的三角形。所以当我缩小 50% 时,它看起来应该像一个普通的三角形。有没有办法像这样渲染它?由于我对 OpenGL 的经验非常少,我将 post 给你完整的代码。 版本: 极光 2.1.0 OpenGL 4.6

代码:

    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);
            }
        }
    }

输出: Actual Output

期望的输出: Desired output

首先阅读 glGenerateMipmap 的描述。
为了更深入地了解 mipmapping 及其实现方式:OpenGl Specification 8.14.3 Mipmapping

为了达到(看到)您想要的结果,您将不得不进一步缩小。顺便说一下,可能会出现缩小图像,这是您所期望的。

纹理过滤的微调可以通过 glTexParameter 和不同的参数来完成,例如:

  • 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

您也可以通过 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).

自己生成 mipmap

您还可以进行几何 LOD(更多 here)。