Reputation: 167
I'm trying to use some OpenGL in my windows app
To activate gl extention functionality, theese steps should be taken as usual:
get all the needed addresses in this manner
PFNGLCOMPILESHADERPROC glCompileShader; glCompileShader=(PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
Right?
Ok. First I had a simple openGL functionality in my window and I've just made a separate window class with all the subclassing done there and all the functions doing openGL initializing and drawing there. In the same class I've got a long list of function pointers as class data members and so i can use them inside this window class. For step 6 I've created a separate function called load_glext_functions()
So in the end my class looks like this (simplified):
{ public: HBRUSH brush_background; HWND hWnd; HDC hDC, hDC_offscreen; HGLRC hGLRC; RECT client_area; POINT 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);
};
and the load_glext_function() looks like this:
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");
}
just longer.
So as long as I use theese extention functions within a class, everythin is ok. Now if I want to use Object-Oriented style, I would need to create separate classes for texture framebuffer mesh, etc..
and say class Cframebuffer should have it's own init func, where we should have the glGenFramebuffers() which is extention and this list can be continued
class Cframebuffer
{
public:
GLuint fbo_id;
void init()
{
glGenFramebuffers(1,&fbo_id);
}
void delete()
{
glDeleteFramebuffers(fbo_id);
}
};
Now. I want to really put all those extentions in one separate class like this
class Cgl_extentions
{
public:
static PFNGLCREATESHADERPROC glCreateShader;
static PFNGLATTACHSHADERPROC glAttachShader;
static PFNGLSHADERSOURCEPROC glShaderSource;
static PFNGLCOMPILESHADERPROC glCompileShader;
static init();
}
where init looks like this
void Cgl_extentions::init()
{
glCompileShader=(PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
glAttachShader=(PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
glCreateProgram=(PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
glCreateShader=(PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
glEnableVertexAttribArray=(PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress("glEnableVertexAttribArray");
}
then I just include the header with theis extentions class everywhere i want ot use it and just address this functions as static funtions of a class Cgl_extentions::glGenBuffers() ....etc
Right now I've did exactly what I've described, but I'm getting linker errors. And I try to find some mistake in my logic. What did I do wrong?
UPDATED: I was recommended to sign in the symbols of theese functions in the beginning of a cpp file. And it works. But the author of this advise has failed to explain what is happening under the hood of this solution. In fact even an ordinary data member of this class needs this kind of declaration or it starts prompting errors in the linker If i execute with some lines commented here are the exact mistake strings
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)
Sorry, it's in russian but i think for all of you weathered veterans of code this is not a problem.)
Upvotes: 0
Views: 217
Reputation: 1135
Make the GL functions global, at least within your rendering code, or perhaps put them in a GL namespace if you want to C++'ify everything. e.g. GL::compileShader()
and initialise once you have loaded the GL library.
Think of GL functions like any other imported library, just with a non-standard import mechanism. Also check out GLEW, it will save you worrying about things like this so that you can focus on the primary problem you are trying to solve.
I think regardless of your applications size, complexity and how well it is architected, GL function pointers will need some global visibility within your rendering back-end as some GL functions are used by all GL objects types.
If you want to continue down your own path, you'll have to provide more information about the linker error.
Upvotes: 1