• VC++ MFC单文档应用程序SDI下调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错原因分析及解决办法:glewInit()初始化的错误


    1、问题症状

      在VC++环境下,利用MFC单文档应用程序SDI下开发OpenGL程序,当调用glGenBuffersARB(1, &pbo)方法编译通过但执行时出错,出错代码如下:

     OpenGL程序中的0x00000000 处未处理的异常: 0xC0000005: 读取位置 0x00000000 时发生访问冲突
    void createVBO(GLuint *vbo,int size)
    {
      glGenBuffers(1,vbo);//该行代码出错,呜呜
      glBindBuffer(GL_ARRAY_BUFFER,*vbo);
      glBufferData(GL_ARRAY_BUFFER,size,0,GL_DYNAMIC_DRAW);
      glBindBuffer(GL_ARRAY_BUFFER,0);
      CUT_CHECK_ERROR_GL();
    }
    是一个建立缓冲区函数的代码,程序编译没有错误,但是运行到glGenBuffers(1,vbo)时,出现标题的错误,如下图所示:

    2、原因分析

      关于缓冲区的一些GL接口,是从GL1.5才开始有的,而windows自带的GL只支持到1.1版本。但如果你的显卡支持GL1.5以上的话,glew就很好的帮你完成了扩展工作,既然你用glew,那么就应该在使用GL任何一个接口前首先调用glewInit来初始化这些扩展,否则那些GL接口都不能使用。在你的init方法开头添加加glewInit就可以了。

    3、解决办法

      (1)、Win32工程环境

         先按如下代码初始化

    //设置OpenGL环境
    void SetupGL(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
        glutInitWindowSize (WINDOW_WIDTH, WINDOW_HEIGHT);
        glutCreateWindow(ProgramName);
        glutDisplayFunc(display);
        glutKeyboardFunc(keyboard);
        glutReshapeFunc(reshape);
        glutIdleFunc(idle);
    
        glewInit();//glew初始化
    }    

        然后再调用下面的产生缓冲区标识的代码:

    glGenBuffers(1,vbo);//产生缓冲区标识

        (2)、VC++ MFC单文档应用程序SDI下工程环境

        在VC++ MFC单文档应用程序SDI下工程环境下,需要先调用wglMakeCurrent(m_hDC, tempContext);方法,然后再调用glew初始化代码,最后再调用产生缓冲区标识的代码。如果未在wglMakeCurrent之后调用glewInit方法,则会造成glewInit返回1(成功返回0)。从而导致前面的运行时问题出现。下面给出调用次序:

      CRSQuickLookView::OnCreate--_>GLInit()--->GetSafeHdc()--->ChoosePixelFormat(m_hDC, &pfd)--->SetPixelFormat(m_hDC, PixelFormat, &pfd)--->wglCreateContext(m_hDC)--->wglMakeCurrent(m_hDC, g_p00RC)--->glewInit()--->initGLBuffers()--->glGenBuffers(1,vbo)。其中,GLInit()和initGLBuffers()方法具体定义如下:

    void CRSQuickLookView::GLInit()
    {
        CreateTexturePixel();//产生测试的像素缓冲区数据
        //m_hDC = ::GetDC(m_hWnd);
        CDC* clientDC = new CClientDC(this);
        m_hDC = clientDC->GetSafeHdc();
    
        if (m_hDC  == NULL)
            return;
    
        static PIXELFORMATDESCRIPTOR pfd = {
            sizeof(PIXELFORMATDESCRIPTOR),
            1,
            PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,           //标志
            PFD_TYPE_RGBA,                 //颜色模式
            24,                                   //颜色位数
            0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0,
            32,                                  //深度位数
            0,
            0,
            PFD_MAIN_PLANE,
            0,
            0, 0, 0
        };
        GLuint PixelFormat;
        if ((PixelFormat = ChoosePixelFormat(m_hDC, &pfd)) == 0)
            return;                //选择相应像素格式
        if (!SetPixelFormat(m_hDC, PixelFormat, &pfd))
            return;                               //设置像素格式
        //if ((m_hRC = wglCreateContext(m_hDC)) == NULL)
        if ((g_p00RC = wglCreateContext(m_hDC)) == NULL)
            return;                          //创建着色描述表
        SetupCUDA();//设置CUDA环境,主要完成最强计算能力显卡的选择和设置
        //GLSetupRC();
        //if (!wglMakeCurrent(m_hDC, m_hRC)) 
        if (!wglMakeCurrent(m_hDC, g_p00RC))
            return;                                           //将着色描述表连接到设备描述表
    
        int re=glewInit();
        initGLBuffers();
    }
    void CRSQuickLookView::initGLBuffers()
    {
        // create pixel buffer object to store final image
        glGenBuffers(1, &pbo);
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
        glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * sizeof(GLubyte) * 3, pPixelData, GL_DYNAMIC_DRAW);//GL_STREAM_DRAW_ARB
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
        checkCudaErrors(cudaGLRegisterBufferObject(pbo));
    
        // create texture for display
        glGenTextures(1, &_texture);
        glBindTexture(GL_TEXTURE_2D, _texture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    }

    参考链接:

    1、glewInit初始化的错误glewInit初始化的错误

    2、在mfc下使用opengl中的vbo进行绘制,绘制失败

    3、OpenGL程序中的0x00000000 处未处理的错误: 0xC0000005: 读取位置 0x00000000 时发生访问冲突

    4、glGenBuffersARB 运行时访问冲突

    5、OpenGL程序中与glew相关的未处理异常的解决方案

  • 相关阅读:
    MapReduce中压缩的使用体验
    weblogic 12安装及和Eclipse的整合
    常用正则表达式补充1
    C# 中利用 Conditional 定义条件方法
    金额文本框
    C#中的List<string>泛型类示例
    HTML ID和Name属性的区别
    CSS的position:fixed的使用
    C# 匿名方法和Lambda表达式
    C#设置开机启动程序
  • 原文地址:https://www.cnblogs.com/rainbow70626/p/8976088.html
Copyright © 2020-2023  润新知