OpenGL + PBO + FBO +一些ATI卡 - 颜色和像素移位

时间:2013-10-08 15:09:15

标签: opengl fbo ati pbo

我们正在开发用于创建幻灯片的软件并使用OpenGL。 我们使用FBO + PBO从VGA到RAM的快速数据读取,但在ATI的一些视频卡上,我们遇到了以下问题:

  1. 交换RGB组件
  2. 像素转换
  3. 如果我们不使用PBO,没有问题。 我们也注意到PBO / FBO(4:3)的纵横比解决了像素移位问题。

    有任何想法或建议吗?

    以下是更多详情:

    • ATI Radeon HD 3650

    PBO代码:

    public bool PBO_Initialize(
            int bgl_size_w,
            int bgl_size_h)
        {
            PBO_Release();
            if (mCSGL12Control1 != null)
            {
                GL mGL = mCSGL12Control1.GetGL();
                mCSGL12Control1.wgl_MakeCurrent();
                //
                // check PBO is supported by your video card
                if (mGL.bglGenBuffersARB == true &&
                    mGL.bglBindBufferARB == true &&
                    mGL.bglBufferDataARB == true &&
                    mGL.bglBufferSubDataARB == true &&
                   mGL.bglMapBufferARB == true &&
                   mGL.bglUnmapBufferARB == true &&
                   mGL.bglDeleteBuffersARB == true &&
                   mGL.bglGetBufferParameterivARB == true)
                {
                    mGL.glGenBuffersARB(2, _pbo_imageBuffers);
                    int clientHeight1 = bgl_size_h / 2;
                    int clientHeight2 = bgl_size_h - clientHeight1;
                    int clientSize1 = bgl_size_w * clientHeight1 * 4;
                    int clientSize2 = bgl_size_w * clientHeight2 * 4;
    
    
                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                    mGL.glBufferDataARB(GL.GL_PIXEL_PACK_BUFFER_ARB, clientSize1, IntPtr.Zero,
                                    GL.GL_STREAM_READ_ARB);
    
                    mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                    mGL.glBufferDataARB(GL.GL_PIXEL_PACK_BUFFER_ARB, clientSize2, IntPtr.Zero,
                                    GL.GL_STREAM_READ_ARB);
    
                    return true;
                }
            }
            return false;
        }
    

    ... PBO将数据读回内存

                        int clientHeight1 = _bgl_size_h / 2;
                        int clientHeight2 = _bgl_size_h - clientHeight1;
                        int clientSize1 = _bgl_size_w * clientHeight1 * 4;
                        int clientSize2 = _bgl_size_w * clientHeight2 * 4;
                        //mGL.glPushAttrib(GL.GL_VIEWPORT_BIT | GL.GL_COLOR_BUFFER_BIT);
    
                        // Bind two different buffer objects and start the glReadPixels
                        // asynchronously. Each call will return directly after
                        // starting the DMA transfer.
                        mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                        mGL.glReadPixels(0, 0, _bgl_size_w, clientHeight1, imageFormat,
                                        pixelTransferMethod, IntPtr.Zero);
    
                        mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                        mGL.glReadPixels(0, clientHeight1, _bgl_size_w, clientHeight2, imageFormat,
                                        pixelTransferMethod, IntPtr.Zero);
    
                        //mGL.glPopAttrib();
                        mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
    
                        // Process partial images.  Mapping the buffer waits for
                        // outstanding DMA transfers into the buffer to finish.
                        mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                        IntPtr pboMemory1 = mGL.glMapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB,
                                                    GL.GL_READ_ONLY_ARB);
    
                        mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                        IntPtr pboMemory2 = mGL.glMapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB,
                                                    GL.GL_READ_ONLY_ARB);
    
    
                        System.Runtime.InteropServices.Marshal.Copy(pboMemory1, _bgl_rgbaData_out, 0, clientSize1);
                        System.Runtime.InteropServices.Marshal.Copy(pboMemory2, _bgl_rgbaData_out, clientSize1, clientSize2);
    
    
                        // Unmap the image buffers
                        mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[0]);
                        mGL.glUnmapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB);
                        mGL.glBindBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB, _pbo_imageBuffers[1]);
                        mGL.glUnmapBufferARB(GL.GL_PIXEL_PACK_BUFFER_ARB);
    

    FBO初始化

    private static void FBO_Initialize(GL mGL,
            ref int[] bgl_texture,
            ref int[] bgl_framebuffer,
            ref int[] bgl_renderbuffer,
            ref byte[] bgl_rgbaData,
            int bgl_size_w,
            int bgl_size_h)
        {
            // Texture
            mGL.glGenTextures(1, bgl_texture);
            mGL.glBindTexture(GL.GL_TEXTURE_2D, bgl_texture[0]);
    
            mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
            mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
            mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
            mGL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
            IntPtr null_ptr = new IntPtr(0);
            // <null> means reserve texture memory, but texels are undefined
            mGL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, bgl_size_w, bgl_size_h, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, null_ptr);
            //
            mGL.glGenFramebuffersEXT(1, bgl_framebuffer);
            mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, bgl_framebuffer[0]);
    
            mGL.glGenRenderbuffersEXT(1, bgl_renderbuffer);
            mGL.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, bgl_renderbuffer[0]);
            mGL.glRenderbufferStorageEXT(GL.GL_RENDERBUFFER_EXT, GL.GL_DEPTH_COMPONENT24, bgl_size_w, bgl_size_h);
    
    
            mGL.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT,
                GL.GL_TEXTURE_2D, bgl_texture[0], 0);
            mGL.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT,
                GL.GL_RENDERBUFFER_EXT, bgl_renderbuffer[0]);
    
            // Errors?
            int status = mGL.glCheckFramebufferStatusEXT(GL.GL_FRAMEBUFFER_EXT);
            if (status != GL.GL_FRAMEBUFFER_COMPLETE_EXT || mGL.glGetError() != GL.GL_NO_ERROR)
            {
                mGL.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_COLOR_ATTACHMENT0_EXT,
                    GL.GL_TEXTURE_2D, 0, 0);
                mGL.glFramebufferRenderbufferEXT(GL.GL_FRAMEBUFFER_EXT, GL.GL_DEPTH_ATTACHMENT_EXT,
                    GL.GL_RENDERBUFFER_EXT, 0);
    
                mGL.glBindTexture(GL.GL_TEXTURE_2D, 0);
                mGL.glDeleteTextures(1, bgl_texture);
                mGL.glBindRenderbufferEXT(GL.GL_RENDERBUFFER_EXT, 0);
                mGL.glDeleteRenderbuffersEXT(1, bgl_renderbuffer);
                mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
                mGL.glDeleteFramebuffersEXT(1, bgl_framebuffer);
    
                throw new Exception("Bad framebuffer.");
            }
    
            mGL.glDrawBuffer(GL.GL_COLOR_ATTACHMENT0_EXT);
            mGL.glReadBuffer(GL.GL_COLOR_ATTACHMENT0_EXT); // For glReadPixels()
    
            mGL.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, 0);
    
            mGL.glDrawBuffer(GL.GL_BACK);
            mGL.glReadBuffer(GL.GL_BACK);
            mGL.glBindTexture(GL.GL_TEXTURE_2D, 0);
    
            bgl_rgbaData = new byte[bgl_size_w * bgl_size_h * 4];
        }
    

    enter image description here

1 个答案:

答案 0 :(得分:2)

似乎重新安装/更新VGA驱动程序确实解决了这个问题。

真的很奇怪的行为(也可能是官方的笔记本驱动程序是旧的/ buggy /等。并导致问题,所以使用AMD的最新驱动程序更新,对于这个vga芯片系列,似乎影响/解决问题。此外,我不确定前置驱动程序是否设置正确,因此我说重新安装/更新)

谢谢大家的帮助。