在Linux上无法使用屏幕外OpenGL上下文生成mipmap

时间:2014-03-31 13:36:32

标签: c++ linux opengl

这个问题是我所描述的here问题的延续。这是我见过的最奇怪的错误之一。我的引擎在两种模式下运行:显示模式和屏幕外。操作系统是Linux。我为纹理生成mipmap,在显示模式下它一切正常。在那种模式下,我使用GLFW3进行上下文创建。现在,有趣的部分:在屏幕外模式下,我用下面的代码手动创建的上下文,mipmap生成偶然失败!在某些运行中,结果输出看起来没问题,而在其他情况下,缺少的级别可以清楚地看到帧充满纹理垃圾数据或完全为空。 起初我虽然我的mipmap gen例程错了,但是这样:

glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_2D, textureName);          
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imageInfo.Width, imageInfo.Height, 0, imageInfo.Format, imageInfo.Type, imageInfo.Data);
glTexParameteri  ( GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0 );


  glGenerateMipmap(GL_TEXTURE_2D);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

我也试过玩这个参数:

glTexParameteri  ( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, XXX); 

包括最高水平检测公式:

  int numMipmaps =  1 + floor(log2(glm::max(imageInfoOut.width, imageInfoOut.height)));

但所有这些东西并没有一致地工作。在10-15次运行中3-4出现了破碎的Mipmaps。然后我发现切换到GL_LINEAR解决了它。在mipmap模式下,只设置1最后我开始认为在上下文层面可能有问题,因为在屏幕模式下它可以工作!我将上下文创建切换到GLFW3并且它有效。所以我想知道这里发生了什么?我想念一些东西吗?在打破mipmaps生成的Pbuffer设置中?我怀疑它是因为AFAIK是由驱动程序完成的。

这是我自定义的离屏上下文创建设置:

  int visual_attribs[] = {
             GLX_RENDER_TYPE,
        GLX_RGBA_BIT,
        GLX_RED_SIZE, 8,
        GLX_GREEN_SIZE, 8,
        GLX_BLUE_SIZE, 8,
        GLX_ALPHA_SIZE, 8,
        GLX_DEPTH_SIZE, 24,
        GLX_STENCIL_SIZE, 8,
            None
        };
        int context_attribs[] = {
            GLX_CONTEXT_MAJOR_VERSION_ARB, vmaj,
            GLX_CONTEXT_MINOR_VERSION_ARB, vmin,
            GLX_CONTEXT_FLAGS_ARB,

            GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB
#ifdef  DEBUG           
            |  GLX_CONTEXT_DEBUG_BIT_ARB 
#endif
            ,  
            GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
            None
        };

        _xdisplay = XOpenDisplay(NULL);
        int fbcount = 0;
        _fbconfig = NULL;


        //  _render_context
        if (!_xdisplay) {
                            throw();
        }
        /* get framebuffer configs, any is usable (might want to add proper attribs) */
        if (!(_fbconfig = glXChooseFBConfig(_xdisplay, DefaultScreen(_xdisplay), visual_attribs, &fbcount))) {
                       throw();
        }

        /* get the required extensions */
        glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB((const GLubyte *) "glXCreateContextAttribsARB");
        glXMakeContextCurrentARB = (glXMakeContextCurrentARBProc) glXGetProcAddressARB((const GLubyte *) "glXMakeContextCurrent");


        if (!(glXCreateContextAttribsARB && glXMakeContextCurrentARB)) {

            XFree(_fbconfig);
                              throw();

        }

        /* create a context using glXCreateContextAttribsARB */
        if (!(_render_context = glXCreateContextAttribsARB(_xdisplay, _fbconfig[0], 0, True, context_attribs))) {

            XFree(_fbconfig);
                            throw();

        }

                  //  GLX_MIPMAP_TEXTURE_EXT
        /* create temporary pbuffer */
        int pbuffer_attribs[] = {
            GLX_PBUFFER_WIDTH, 128,
            GLX_PBUFFER_HEIGHT, 128,
            None
        };

        _pbuff = glXCreatePbuffer(_xdisplay, _fbconfig[0], pbuffer_attribs);

        XFree(_fbconfig);
        XSync(_xdisplay, False);

        /* try to make it the current context */
        if (!glXMakeContextCurrent(_xdisplay, _pbuff, _pbuff, _render_context)) {
            /* some drivers does not support context without default framebuffer, so fallback on
             * using the default window.
             */
            if (!glXMakeContextCurrent(_xdisplay, DefaultRootWindow(_xdisplay),
                    DefaultRootWindow(_xdisplay), _render_context)) {

                throw();

            }
        }

几乎忘了:我的系统和硬件:

Kubuntu 13.04 64bit。 GPU:NVidia Geforce GTX 680。该引擎使用OpenGL 4.2 API

完整的OpenGL信息:

** OpenGL供应商字符串:NVIDIA Corporation

OpenGL渲染器字符串:GeForce GTX 680 / PCIe / SSE2

OpenGL版本字符串:4.4.0 NVIDIA 331.49

OpenGL着色语言版本字符串:4.40 NVIDIA通过Cg编译器**

不过,我还使用了较老的司机,但这并不重要。

更新

似乎我对GLFW的假设是错误的。当我编译引擎并从终端运行它时也会发生同样的情况。但是 - 如果我从IDE运行引擎(调试或发布),则mipmap没有问题。独立应用程序是否可以针对不同的SO工作?

为了说清楚,我没有使用Pbuffers渲染到。我渲染到自定义帧缓冲区。

UPDATE1:

我已经读过2个纹理的非强大功能可能很难自动生成mipmap。并且在OpenGL无法生成所有级别的情况下,它会转换纹理使用情况。这可能是我遇到的问题这里?因为一旦mipmapped纹理出错,剩下的纹理(非mipmap)也会消失。但是如果是这种情况那么为什么这种行为是不一致的呢?

1 个答案:

答案 0 :(得分:0)

呃,为什么你首先使用PBuffers? PBuffers有太多警告,因为只有一个合理的理由在新项目中使用它们?

你想要屏幕外渲染吗?然后使用帧缓冲对象(FBO)。

你需要纯粹的屏幕外环境吗?然后创建一个普通窗口,您只是不显示它并在其上创建一个FBO。