简体   繁体   English

OpenGl glViewport 调用重置 vao、vbo 和着色器程序

[英]OpenGl glViewport call resets vao, vbo and shader program

So I've been starting with OpenGL by following this tutorial and managed to get everything to draw fine, but when I resize my viewport, the vao, vbo and shader program are unbound.所以我一直按照本教程从 OpenGL 开始,并设法让一切都画得很好,但是当我调整视口大小时,vao、vbo 和着色器程序未绑定。 I need to rebind everything and resend the buffer data , I don't know if this is the expected behaviour, but it seems a bit ridiculous to me so maybe I'm missing something.我需要重新绑定所有内容并重新发送缓冲区数据,我不知道这是否是预期的行为,但这对我来说似乎有点荒谬,所以也许我遗漏了一些东西。 I did some searching and tried couple of different ways (with/without vaos, using glVertexAttribFormat / glVertexAttribBinding...) with no progress.我做了一些搜索并尝试了几种不同的方法(有/没有 vaos,使用 glVertexAttribFormat / glVertexAttribBinding ...)但没有任何进展。

I made a logGl functions to get as much information as I could:我制作了一个 logGl 函数来获取尽可能多的信息:

void logGl() {
    int value, value2;
    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &value);
    std::cout << "bound buffer: " << value << std::endl;

    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &value);
    std::cout << "bound vao: " << value << std::endl;

    glGetIntegerv(GL_CURRENT_PROGRAM, &value);
    std::cout << "bound program: " << value << std::endl;

    glGetIntegerv(GL_MAJOR_VERSION, &value);
    glGetIntegerv(GL_MINOR_VERSION, &value2);
    std::cout << "GL version: " << value << "." << value2 << std::endl;

    float data[9];
    glGetBufferSubData(GL_ARRAY_BUFFER, 0, 9 * sizeof(float), data);
    std::cout << "Buffer Data: ";
    for (size_t i=0; i<9; i++) { std::cout << data[i] << " ";};
    std::cout << std::endl;
}

this is the output:这是 output:

Shader Program ID: 3
bound buffer: 1
bound vao: 1
bound program: 3
GL version: 4.6
Buffer Data: -0.5 -0.5 0 0 0.5 0 0.5 -0.5 0 
changing viewport ******* 
bound buffer: 0
bound vao: 0
bound program: 0
GL version: 4.6
Buffer Data: 1.23555e-31 4.59163e-41 28.875 0 30.0201 0 2.05719e+32 4.55772e-41 1.23552e-31 
We see everything is unbound (Here I recreate shader program)
Shader Program ID: 39
Viewport size: 0 0 801 600
In main loop, just before isssuing draw call:
bound buffer: 1
bound vao: 0
bound program: 39
GL version: 4.6
Buffer Data: 3.8357e+34 4.55772e-41 3.47159e+34 4.55772e-41 4.56443e+34 4.55772e-41 1.5695e+11 3.09e-41 1.23552e-31 
Error: 1282
--------------------------------

The error code 1282 did not really provide me with any clue, I did not get any compiling / linking errors from my setShaders function.错误代码 1282 并没有真正为我提供任何线索,我没有从我的 setShaders function 得到任何编译/链接错误。

This is my main loop, I can provide the implementations of the shader function if needed, but it's pretty much tutorial textbook..这是我的主循环,如果需要,我可以提供着色器 function 的实现,但它几乎是教程教科书。

int main() {
    // Init SDL, get GL context, set initial viewport init glew ...
    Systems sys = initWindow(800, 600);

    // Init a buffer
    float vertices[] = {
            -0.5f, -0.5f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.5f, -0.5f, 0.0f
    };

    unsigned int vbo, vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);   // bind first!

    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void *) 0);
    glEnableVertexAttribArray(0);

    unsigned int shader = setShaders("Shaders.txt");

    logGl();

    bool running = true;
    while (running) {
        bool log = false;

        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = false;

                case SDL_KEYDOWN:
                    if (event.key.keysym.sym == SDLK_ESCAPE) running = false;

                case SDL_WINDOWEVENT:
                    switch (event.window.event) {
                        case SDL_WINDOWEVENT_RESIZED:
                            int dims[4];
                            std::cout << "changing viewport ******* \n";
                            glViewport(0, 0, event.window.data1, event.window.data2);
//                            glViewport(0, 0, 500, 500);
                            logGl();
                            std::cout << "We see everything is unbound" << std::endl;

                            // Updating viewport unbinds vao, shader program
                            // and seems to empty vbo data
                            // since I get this error code after viewport call at glDraw:

                            shader = setShaders("Shaders.txt");
                            glUseProgram(shader);

                            glGetIntegerv(GL_VIEWPORT, dims);
                            std::cout << "Viewport size: "
                                      << dims[0] << " "
                                      << dims[1] << " "
                                      << dims[2] << " "
                                      << dims[3] << std::endl;

                            log = true;
                    }

            }
        }

        // random bg color
        Uint32 rdCol = SDL_GetPerformanceCounter();
        glClearColor((float) (rdCol & 0x0000FF00) / 0x0000FF00,
                     (float) (rdCol & 0x00FF0000) / 0x00FF0000,
                     (float) (rdCol & 0xFF000000) / 0xFF000000, 1);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Why is this not needed ..???
        glBindVertexArray(vao);

        ///////////////////////////////////////////////////////////////////////
        // *** The four lines below are necessary to keep drawing on win resize
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
//        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//
//        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) 0);
//        glEnableVertexAttribArray(0);
        ///////////////////////////////////////////////////////////////////////


        if (log) {
            std::cout << "In main loop, just before isssuing draw call:" << std::endl;
            logGl();
            std::cout << "Error: " << glGetError() << std::endl;
            std::cout << "--------------------------------" << std::endl;
        }
        glDrawArrays(GL_TRIANGLES, 0, 3);

        /* 'flip' Window */
        SDL_GL_SwapWindow(sys.window);

    }

    SDL_FreeSurface(sys.winSurf);
    SDL_DestroyWindow(sys.window);
    SDL_Quit();

    return 0;
}

So the big question is why eveything gets unbound when I call glViewport, as I would believe it should keep drawing only by binding vao and vbo (which works until I resize the window)所以最大的问题是为什么当我调用 glViewport 时所有东西都没有绑定,因为我相信它应该只通过绑定 vao 和 vbo 来继续绘制(在我调整窗口大小之前一直有效)

I have found the culprit, which is that when resizing the window in SDL, it creates a new OpenGL context and thus removes every binding made.我找到了罪魁祸首,即在 SDL 中调整 window 的大小时,它会创建一个新的 OpenGL 上下文,从而删除所有绑定。 So, I could either rebind everything (ridiculous but it works) or use GLFW, SFML or other librairies.因此,我可以重新绑定所有内容(荒谬但有效)或使用 GLFW、SFML 或其他库。 I found my answer here , if anyone ever encounters this problem.如果有人遇到这个问题,我在这里找到了答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM