具有 0 个颜色位和 0 个深度位的 SDL2 OpenGL 4.2 上下文

Posted

技术标签:

【中文标题】具有 0 个颜色位和 0 个深度位的 SDL2 OpenGL 4.2 上下文【英文标题】:SDL2 OpenGL 4.2 context with 0 color bits and 0 depth bits 【发布时间】:2015-02-25 22:43:00 【问题描述】:

我一直在尝试启动一个新的 SDL + GLEW + OpenGL 项目,但设置很困难(MinGW-w64-32 on Windows 8 64-bit with an Intel i7-4700MQ CPU and NVidia GTX 745M GPU) .

如果我将用于上下文创建的 GL 属性设置为使用 OpenGL 4.2 版,颜色和深度位大小将设置为 0。但是,如果我请求 2.1 上下文(这也是默认设置),我可以获取请求的位深度(每种颜色 8 位,深度 24 位)。然而,在任何一种情况下,glClearColor 都没有效果(只是黑色背景)。

在这两种情况下,几个 glGetString 调用的结果是相同的 - 4.2 上下文,表明 SDL 的输出远不正确。

完整的代码可以在here 找到,目前它主要是大型项目的样板。相关部分很可能是

if(SDL_Init(SDL_INIT_EVERYTHING) != 0) 
    std::cerr << "Error initializing SDL.\n";
    exit(1);


SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
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_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

SDL_Window* window = SDL_CreateWindow("RenderSystem", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);

if(!window) 
    std::cerr << "Window creation failed.\n";
    SDL_Quit();
    exit(2);


SDL_GLContext context = SDL_GL_CreateContext(window);

if(!context) 
    std::cerr << "OpenGL Context creation failed.\n";
    SDL_DestroyWindow(window);
    SDL_Quit();
    exit(3);


SDL_GL_MakeCurrent(window, context);

glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

SDL_Event evt;
bool run = true;

while(run) 

    SDL_PollEvent(&evt);

    switch(evt.type) 
        case SDL_KEYDOWN:
            if(evt.key.keysym.sym == SDLK_ESCAPE) 
                run = false;
            
            break;

        case SDL_QUIT:
            run = false;
            break;
    

    SDL_GL_SwapWindow(window);


【问题讨论】:

您如何确定上述值?在OpenGL 3.0中,在默认帧缓冲上查询GL_RED_BITSGL_DEPTH_BITS等是无效的。兼容性配置文件应提供一致的结果,但核心配置文件具有不同的行为。 你似乎没有在任何地方给glClear()打电话。 glClearColor() 只是锁存了一些状态,它实际上并没有清除任何缓冲区。 @AndonM.Coleman 我正在使用 SDL 的内置函数 SDL_GL_GetAttribute,它返回 SDL 用于创建上下文的值,而不是实际的上下文属性(据我了解)。跨度> @genpfault 我更担心来自 SDL_GL_GetAttribute 调用的 0 值,并完全跳过了它。这确实解决了 2.1 上下文请求的问题,允许我设置位深度的值,并且奇怪地解决了 4.2 上下文的问题,即使 SDL 仍然报告零位缓冲区深度。 【参考方案1】:

我正在使用 SDL 的内置函数 SDL_GL_GetAttribute,它返回 SDL 用于创建上下文的值,而不是实际的上下文属性(据我了解)。

这是不正确的,我查看了SDL_GL_GetAttribute (...) 的 SDL 实现(参见src/video/SDL_video.c),它符合我的描述。您无法查询核心配置文件上下文中的值,因为它们不是为默认帧缓冲区定义的。

这里是问题的来源:

int
SDL_GL_GetAttribute(SDL_GLattr attr, int *value)

  // ...

  switch (attr) 
  case SDL_GL_RED_SIZE:
    attrib = GL_RED_BITS;
    break;
  case SDL_GL_BLUE_SIZE:
    attrib = GL_BLUE_BITS;
    break;
  case SDL_GL_GREEN_SIZE:
    attrib = GL_GREEN_BITS;
    break;
  case SDL_GL_ALPHA_SIZE:
    attrib = GL_ALPHA_BITS;
    break;
  

  // ...

  glGetIntegervFunc(attrib, (GLint *) value);
  error = glGetErrorFunc();

该代码实际上会在核心配置文件上生成GL_INVALID_ENUM 错误,因此SDL_GL_GetAttribute (...) 的返回值应该不为零。

如果您必须从 SDL_GL_GetAttribute (...) 获取有意义的位深度值,那么这意味着您必须使用兼容性配置文件。 SDL2 不会从它选择的像素格式中提取这些信息(像 GLFW 等更智能的框架会这样做),但它会天真地尝试从 GL 中查询它。

【讨论】:

【参考方案2】:

如果没有记错的话,SDL_GL_DEPTH_SIZE 必须是所有颜色通道的总和:

使用四个颜色通道:

SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 32);

如果您使用 3 个颜色通道,那么:

SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 24);

已经遇到了一些问题,这可能是问题所在。 对不起我的英语。

【讨论】:

深度缓冲区精度与颜色通道无关。您可能会与组合的深度/模板缓冲区混淆,后者通常提供 24 位深度和 8 位模板。

以上是关于具有 0 个颜色位和 0 个深度位的 SDL2 OpenGL 4.2 上下文的主要内容,如果未能解决你的问题,请参考以下文章

16位图像的65536种颜色是指彩色,还是灰度(灰阶)?

Rust SDL2配置

单片机中高8位是啥,低8位又是啥,还有高四位低四位的,求解

32位和64位数据类型大小对比

由0到4五个数字,组成5位数,每个数字用一次,但十位和百位不能为3(当然万位不能为0),输出所有可能的五位数

BT656 10位和8位的区别