opengl扩展函数在一个单独的类中

时间:2014-12-24 10:00:33

标签: c++ oop opengl syntax linker

我试图在我的Windows应用中使用一些OpenGL

要激活gl延伸功能,应该照常执行这些步骤:

  1. 注册一个窗口类然后创建它
  2. 设置其像素格式
  3. 窗口的GetDC()
  4. wglCreateContext
  5. wglMakeCurrent
  6. 以这种方式获取所有需要的地址

    PFNGLCOMPILESHADERPROC glCompileShader; glCompileShader =(PFNGLCOMPILESHADERPROC)wglGetProcAddress(" glCompileShader&#34);

  7. ReleaseDC()
  8. 右?

    确定。首先,我在窗口中有一个简单的openGL功能,而且我刚刚创建了一个单独的窗口类 在那里完成所有子类化以及所有在openGL初始化和绘制的函数。 在同一个类中,我有一长串函数指针作为类数据成员,所以我可以在这个窗口类中使用它们。对于第6步,我创建了一个名为load_glext_functions()的单独函数

    所以最后我的课看起来像这样(简化):

    { 上市:     HBRUSH         brush_background;     HWND         的hWnd;     HDC         的hDC,         hDC_offscreen;     HGLRC         hGLRC;     RECT         client_area;     点         PT;     GLfloat         mesh_color [3],         point_color [3];

    GLuint 
        program_id_default,
        program_id_lights,
        program_id_grid,
        program_id_wireframe,
    
        texture_id_fbo_color_ms,
        texture_id_fbo_objectid_ms,
        texture_id_fbo_objectid,
        texture_id_fbo_depth_ms,
        texture_id_fbo_depth,
        texture_id_default_white;
    
    bool
        wireframe_mode,
        alt_pressed;
    
    //GLEXT_PROCEDURES
    PFNGLCREATESHADERPROC glCreateShader;
    PFNGLATTACHSHADERPROC glAttachShader;
    PFNGLSHADERSOURCEPROC glShaderSource;
    PFNGLCOMPILESHADERPROC glCompileShader;
    PFNGLDELETESHADERPROC glDeleteShader;
    PFNGLGETSHADERIVPROC glGetShaderiv;
    PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
    PFNGLCREATEPROGRAMPROC glCreateProgram;
    PFNGLUSEPROGRAMPROC glUseProgram;
    PFNGLGETPROGRAMIVPROC glGetProgramiv;
    PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
    
    //METHODS
    Cnerv_window_gl();
    ~Cnerv_window_gl();
    bool init(HINSTANCE hInstance,HWND hParent);
    void load_glext_functions();
    void draw_mesh(Snerv_viewport_object _display_object);
    bool draw_scene();
    void draw_viewport();
    
    void create_texture(Cnerv_texture *_texture_handle);
    void add_mesh_to_GPU(Cnerv_mesh *mesh_data);
    void update_vbo(Cnerv_mesh *_mesh);
    void update_texture(Cnerv_texture *_texture_handle);
    
    void init_framebuffer();
    void paint();
    bool setPFD();
    
    LRESULT CALLBACK wProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    static LRESULT CALLBACK wProc_init_gl(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    

    };

    并且load_glext_function()如下所示:

    void Cnerv_window_gl::load_glext_functions()
    {
        glCompileShader=(PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
        glAttachShader=(PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
        glCreateProgram=(PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
        glCreateShader=(PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
        glEnableVertexAttribArray=(PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
    }
    

    再长一点。

    因此,只要我在一个类中使用theese extention函数,就可以了。 现在,如果我想使用面向对象的样式,我需要为其创建单独的类 质地 帧缓冲区 啮合, 等。

    并说类Cframebuffer应该拥有它自己的init func,我们应该有glGenFramebuffers()这是扩展名,这个列表可以继续

    class Cframebuffer
    {
    public:
         GLuint fbo_id;
         void init()
         {
             glGenFramebuffers(1,&fbo_id);
         }
         void delete()
         {
             glDeleteFramebuffers(fbo_id);
         }
    };
    

    现在。我想把所有这些扩展放在一个单独的类中 像这样

    class Cgl_extentions
    {
    public:
        static PFNGLCREATESHADERPROC glCreateShader;
        static PFNGLATTACHSHADERPROC glAttachShader;
        static PFNGLSHADERSOURCEPROC glShaderSource;
        static PFNGLCOMPILESHADERPROC glCompileShader;
    
        static init();
    }
    

    其中init看起来像这样

    void Cgl_extentions::init()
    {
        glCompileShader=(PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
        glAttachShader=(PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
        glCreateProgram=(PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
        glCreateShader=(PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
        glEnableVertexAttribArray=(PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
    }
    

    然后我只是在我希望不使用它的地方包含带有扩展类的标题,并将此函数作为类的静态函数来解决 Cgl_extentions :: glGenBuffers().... etc

    现在我已经完成了我所描述的内容,但我收到了链接器错误。我试图在我的逻辑中发现一些错误。我做错了什么?

    更新:我建议在cpp文件的开头登录theese函数的符号。 它有效。但是这个建议的作者未能解释这个解决方案的内容。 事实上,即使是这个类的普通数据成员也需要这种声明,或者它开始在链接器中提示错误 如果我执行一些注释这里的行是确切的错误字符串

    1>Cnerv_GL.obj : error LNK2001: неразрешенный внешний символ ""public: static unsigned int (__cdecl* Cnerv_GL::glCreateShader)(unsigned int)" (?glCreateShader@Cnerv_GL@@2P6AII@ZEA)"
    1>Cnerv_window_gl.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: static unsigned int (__cdecl* Cnerv_GL::glCreateShader)(unsigned int)" (?glCreateShader@Cnerv_GL@@2P6AII@ZEA) в функции "public: bool __cdecl Cnerv_window_gl::init(struct HINSTANCE__ *,struct HWND__ *)" (?init@Cnerv_window_gl@@QEAA_NPEAUHINSTANCE__@@PEAUHWND__@@@Z)
    1>Cnerv_GL.obj : error LNK2001: неразрешенный внешний символ ""public: static void (__cdecl* Cnerv_GL::glAttachShader)(unsigned int,unsigned int)" (?glAttachShader@Cnerv_GL@@2P6AXII@ZEA)"
    1>Cnerv_window_gl.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: static void (__cdecl* Cnerv_GL::glAttachShader)(unsigned int,unsigned int)" (?glAttachShader@Cnerv_GL@@2P6AXII@ZEA) в функции "public: static __int64 __cdecl Cnerv_window_gl::wProc_init_gl(struct HWND__ *,unsigned int,unsigned __int64,__int64)" (?wProc_init_gl@Cnerv_window_gl@@SA_JPEAUHWND__@@I_K_J@Z)
    

    对不起,它是俄语的,但我认为对于所有经验丰富的代码老手来说,这不是问题。) enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

使GL函数全局化,至少在渲染代码中,或者如果你想要C ++'ify的话,可以将它们放在GL命名空间中。例如GL::compileShader()并在加载GL库后初始化。

将GL函数视为任何其他导入库,只需使用非标准导入机制。还可以查看GLEW,这样可以避免担心这样的问题,这样您就可以专注于您要解决的主要问题。

我认为无论您的应用程序大小,复杂程度以及它的架构如何,GL函数指针都需要在渲染后端中具有一些全局可见性,因为所有GL对象类型都使用了一些GL函数。

如果您想继续沿着自己的路径行进,则必须提供有关链接器错误的更多信息。