OpenGL累积缓冲区不起作用

Posted

技术标签:

【中文标题】OpenGL累积缓冲区不起作用【英文标题】:OpenGL Accumulation buffer not working 【发布时间】:2015-11-26 08:23:30 【问题描述】:

我正在尝试在 OpenGL 中使用累积缓冲区,但由于某种原因,缓冲区似乎没有被填充。我构建了一个简单的测试应用程序,渲染了一个 2D 平面,仅此而已。这渲染得很好。 然后我尝试做我能想到的最简单的累积缓冲区操作,将渲染帧加载到累积缓冲区中,清除屏幕,然后将累积缓冲区返回到屏幕。 当我这样做时,似乎累积缓冲区根本不包含任何信息,图像只是屏幕被清除的颜色,就好像累积缓冲区根本没有返回一样。我还尝试过进行更传统的运动模糊设置,在返回之前对场景和缓冲区进行多次更新并获得相同的结果。

这是简单测试的主循环:

SDL_Event eve;
while (true)

    //Normal stuff
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    //Accumulation///////////////////////
    glAccum(GL_LOAD, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glAccum(GL_RETURN, 1.0f);
    //Accumulation///////////////////////

    SDL_GL_SwapWindow(window);

    SDL_PollEvent(&eve);

这是运动模糊测试的主循环:

float x = 0.0f;

int step = 0;
int steps = 4;

SDL_Event eve;
while (true)

    //Test stuff
    x += 0.005f;

    GLfloat newVerts[] = 
        -0.5f + x,  0.5f,
        0.5f + x,  0.5f,
        0.5f + x, -0.5f,
        -0.5f + x, -0.5f,
    ;

    glBufferData(GL_ARRAY_BUFFER, sizeof(newVerts), newVerts, GL_STATIC_DRAW);

    //Normal stuff
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    //Accumulation///////////////////////
    if (step == 0)
    
        glAccum(GL_LOAD, 1.0f / steps);
    
    else
    
        glAccum(GL_ACCUM, 1.0f / steps);
    

    step++;

    if (step < steps)
    
        continue;
    

    step = 0;
    glAccum(GL_RETURN, 1.0f);
    //Accumulation///////////////////////

    SDL_GL_SwapWindow(window);

    SDL_PollEvent(&eve);

这是完整的应用程序源代码(只有大约 100 行,我将其包括在内以防我的 glEnableSDL_GL_SetAttribute 调用有问题):

#include "tools.h"

static string vertexSource = getFile("D:/test.vsh");
static string fragmentSource = getFile("D:/test.fsh");

int main(int argc, char *argv[])

    //SDL///////////////////////////////////////////////
    SDL_Init(SDL_INIT_EVERYTHING);

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    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_ACCUM_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8);

    SDL_Window *window = SDL_CreateWindow("Test", 50, 50, 1600, 900, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

    SDL_GLContext context = SDL_GL_CreateContext(window);

    //GLEW///////////////////////////////////////////////
    glewExperimental = GL_TRUE;
    GLint result = glewInit();

    if (result != GLEW_OK)
    
        cout << glewGetErrorString(result) << "\n";
        cout << "GLEW initialization failed.\n";
    

    //OpenGL///////////////////////////////////////////////
    glEnable(GL_DEPTH);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
    glClearDepth(1.0f);

    //Object///////////////////////////////////////////

    //Vertex Array
    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    //Vertex Buffer
    GLuint vbo;
    glGenBuffers(1, &vbo);

    GLfloat vertices[] = 
        -0.5f,  0.5f,
        0.5f,  0.5f,
        0.5f, -0.5f,
        -0.5f, -0.5f,
    ;

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //Element Buffer
    GLuint ebo;
    glGenBuffers(1, &ebo);

    GLuint elements[] = 
        0, 1, 2,
        2, 3, 0
    ;

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);

    //Shader
    GLuint shaderProgram = createShader(vertexSource, fragmentSource);
    glUseProgram(shaderProgram);

    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    glEnableVertexAttribArray(posAttrib);
    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);

    //Loop///////////////////////////////////////////////
    float x = 0.0f;

    int step = 0;
    int steps = 4;

    SDL_Event eve;
    while (true)
    
        //Test stuff
        x += 0.005f;

        GLfloat newVerts[] = 
            -0.5f + x,  0.5f,
            0.5f + x,  0.5f,
            0.5f + x, -0.5f,
            -0.5f + x, -0.5f,
        ;

        glBufferData(GL_ARRAY_BUFFER, sizeof(newVerts), newVerts, GL_STATIC_DRAW);

        //Normal stuff
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        //Accumulation///////////////////////
        if (step == 0)
        
            glAccum(GL_LOAD, 1.0f / steps);
        
        else
        
            glAccum(GL_ACCUM, 1.0f / steps);
        

        step++;

        if (step < steps)
        
            continue;
        

        step = 0;
        glAccum(GL_RETURN, 1.0f);
        //Accumulation///////////////////////

        SDL_GL_SwapWindow(window);

        SDL_PollEvent(&eve);
    

我正在使用 GLEW 来访问 OpenGL 调用,并且我正在使用 SDL 进行上下文创建和窗口管理。

我正在运行它的平台的一般规格:

OpenGL 4.5(4.3 和 3.3 也试过,没有区别)。 Windows 10 64 位 AMD FX-9590 @ 4.7 GHz NVIDIA GTX 970 SC 华硕剑齿虎 990FX 16GB DDR3 内存

【问题讨论】:

【参考方案1】:
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^

删除的功能(如累积缓冲区)在 Core 上下文中不起作用。

OpenGL 3.2 Core spec, appendix E, page 329 & 333:

E.2 已弃用和删除的功能

...

已删除的函数将生成INVALID_OPERATION 如果在核心配置文件或前向兼容的上下文中调用,则会出错。

...

E.2.2 移除的功能

...

累积缓冲区 - ClearAccumACCUM_BUFFER_BITClear 的参数中作为位无效(第 4.2.3 节); Accum; ACCUM_*_-BITS 帧缓冲区状态描述了累积缓冲区组件的大小;以及所有相关的状态。

诸如 GLX 和 WGL 之类的窗口系统绑定 API 可以选择不公开包含累积缓冲区的窗口配置,或者在绑定到 GL 上下文的默认帧缓冲区包含累积缓冲区时忽略累积缓冲区。

【讨论】:

我现在可以使用 SDL_GL_CONTEXT_PROFILE_COMPATIBILITY。那么它是故意删除的吗?有什么建议可以用来代替它吗?也许只是直接的 FrameBuffer 对象? 添加剂混合也可能有帮助

以上是关于OpenGL累积缓冲区不起作用的主要内容,如果未能解决你的问题,请参考以下文章

android opengl 2.0 模板缓冲区不起作用

在 OpenGL 中创建屏幕截图不起作用

在 OpenGL ES 1.1 中使用顶点缓冲区对象绘图不起作用

PowerBI按年累积折线图不起作用

Qt serial.readall 在 5.3.1 中不起作用

OpenGL移动对象不起作用