denislov 发表于 2020-4-4 12:24

关于opengl的使用

大家都知道,在使用opengl的时候,会链接opengl的动态库,在Windows上是opengl32.dll,在android上是libGLESv2.so,在linux上有X11/libGL.so ,也有libGLESv2.so。
在使用opengl的时候,有一个接口规范问题,GLAD是继GL3W,GLEW之后,当前最新的用来访问OpenGL规范接口的第三方库。官方网址为https://glad.dav1d.de/。
glad是一个在线服务,在选择config的时候,language选择c/c++,Specification选择opengl,然后下面的api可以选择gl和gles一起选,至于版本,看你需求。选择gles可以在android上面使用。


glad在使用的时候最重要的就是初始化,初始化glad库的接口如下:
int gladLoadGLLoader(GLADloadproc load):
任何的OpenGL接口调用都必须在初始化GLAD库后才可以正常访问。如果成功的话,该接口将返回GL_TRUE,否则就会返回GL_FALSE。
其中GLADloadproc函数声明如下:
void* (*GLADloadproc)(const char* name)


所以现在我们要自己实现自己的GLADloadproc函数,其实就是一个返回void*,参数为const char*name 的函数,然后把我们实现的这个函数的地址传过去供glad初始化opengl函数使用。


至于windows,其实glad有一个gladLoadGL函数可以直接在widnows初始化opengl,我贴一下里面的实现:

static
int open_gl(void) {
#ifndef IS_UWP
    libGL = LoadLibraryW(L"opengl32.dll"); // libGL是一个静态变量
    if(libGL != NULL) {
      void (* tmp)(void);
      tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress"); //在windows上就是这个wglGetProcAddress函数来加载opengl函数
      gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp;
      return gladGetProcAddressPtr != NULL;
    }
#endif

    return 0;
}
    }
当然,glad里面也有在mac和linux上的加载函数,大家可以自己去看glad.c的源码。
在这里我们可以试着实现 自己 的loadGL函数,在android和linux都是通过dlopen来加载一个动态库,dlopen返回一个动态库的句柄。所以说我们先要准备好要加载的动态库名字

static std::vector<void*>gl_dll_handles;//用来存储动态库的句柄。在android上我们可能加载两个libGLESv2.so,libGLESv3.所以这里我们声明为一个vector。

然后就是初始化我们的gl_dll_handles.
bool init() {
    void *dll_handle = NULL;
#if defined //如果是windows,这里大家自己可以通过预处理实现
    dll_handle = LoadLibraryW(L"opengl32.dll");
    if (dll_handle != NULL) {
      gl_dll_handles.push_back(dll_handle);
    }
    if (dll_handle != NULL) {
      void (*tmp)(void);
      tmp = (void (*)(void)) ::GetProcAddress(static_cast<HMODULE>(dll_handle), "wglGetProcAddress");
      gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp; //gladGetProcAddressPtr 函数会在windows上面使用
      return gladGetProcAddressPtr != NULL;
    }
#elif defined //如果是android的
    dll_handle = ::dlopen("libGLESv3.so", RTLD_LAZY);
    if (dll_handle != NULL)
    {
      gl_dll_handles.push_back(dll_handle);
    }
    else
    {
      dll_handle = ::dlopen("libGLESv2.so", RTLD_LAZY);
      if (dll_handle != NULL)
      {
            gl_dll_handles.push_back(dll_handle);
      }
    }
#endif
    return true;
}
加载动态库对应的就有卸载动态库,大家可以自己实现,在windows上通过FreeLibrary,在linux和android上用dlclose。
然后最重要的就是我们自己要实现在GLADloadproc;
void *getProcAddress(const char *name) {
    void *ret = NULL;

#if !defined(__APPLE__) && !defined(__HAIKU__)
    if (gladGetProcAddressPtr != NULL) { // 如果在windows上,这个函数指针就不为null,可以直接用来初始化windows上的opengl函数
      ret = gladGetProcAddressPtr(name);
    }
#endif
#if defined //如果在windows上面,上面的那个gladGetProcAddressPtr 不管用,然后就用这个,但这个貌似不管用,不知道为啥
    if (ret == NULL)
      for (void *handle: gl_dll_handles) {
            ret = (void *) (::GetProcAddress(static_cast<HMODULE>(handle), name));
            if (ret != NULL)
                break;
      }

#elif defined //如果是android
    if (ret == NULL)
      for (void *handle: gl_dll_handles) {
            ret = (void *) dlsym(handle, name);
            if (ret != NULL)
                break;
      }
#endif
    return ret;
}


然后我们在把自己实现的getProcAddress的地址给glad就行了,在android上面就可用gladLoadGLESLoader(getProcAddress)
在android上面大家可以用c4droid测试一下。用sdl开窗,创建opengl环境,然后用我们的glad和自己实现的getProcAddress来初始化opengl的函数,亲测还行:shutup:

新手一枚,虚心接受建议,大神勿喷。
注:上面代码大家可以当成伪码来看。




acq1255 发表于 2020-4-8 13:09

兄弟有没有在linux上做openGL然后交叉编译到arm开发板的经验   新手学习opengl要用到嵌入式上痛苦不堪
页: [1]
查看完整版本: 关于opengl的使用