关于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:
新手一枚,虚心接受建议,大神勿喷。
注:上面代码大家可以当成伪码来看。
兄弟有没有在linux上做openGL然后交叉编译到arm开发板的经验 新手学习opengl要用到嵌入式上痛苦不堪
页:
[1]