zoukankan      html  css  js  c++  java
  • OpenGL Loading

    什么是 OpenGL loading?

    OpenGL是一份API规范,并不是一个库。记住这点非常重要!它意味着每一个API背后的具体实现都依赖于你的GPU硬件、操作系统以及显卡驱动。

    OpenGL规范定义了很多不同的函数,并且规范会定期进行更新,你的显卡驱动可能不会支持全部的函数。你的显卡和显卡驱动的能力决定了你能使用的API规范的子集。这也是不把所有的OpenGL函数静态定义在一个头文件中供你使用的原因。而且,将所有函数静态链接成一个库也是不可能的,因为你的应用运行的目标机器上会有各种各样不同的OpenGL实现。

    Windows机器上,OpenGL是以dll的方式实现的。在64位Windows操作系统上,64位的dll库位于 C:Windowssystem32opengl32.dll,这个dll是显卡驱动的一部分,是随着显卡驱动一起发布的。

    再次强调,大部分的OpenGL函数是不能被定义在某个标准的头文件中,然后静态链接进你的应用程序的。这也是为什么OpenGL函数不能直接被调用,而需要显式的声明和加载。

     

    什么是 GLEW?

    GLEW(OpenGL Extension Wrangler)是一个跨平台的用于OpenGL函数声明和加载的库,它同样具备在运行时检查目标机器是否支持某个OpenGL profile(一个profile就是一份指定配置支持的特定的OpenGL函数集)的能力。

    GLEW非常的简单,尤其是针对刚开始接触OpenGL的新手。它把所有的脏活累活都替你做了,你可以在你的系统上自由的调用所有支持的有效OpenGL函数。

    StackOverflow上,所有关于OpenGL loading的问题下,都有人建议你使用OpenGL Loading Library,停止自己定制OpenGL loading去使用GLEW。甚至OpenGL官方的wiki都强烈建议你使用OpenGL loading library。

    但是像GLEW这样的OpenGL loading library有它们自己的缺点,下面就以GLEW为例,来详细讲下这些缺点

     

    为什么你最好不使用GLEW?

    你可以用以下两种方式使用GLEW库:

    1. Dynamically linking动态链接:一个OpenGL应用或者引擎发布后,我们希望用户可以很方便地在他们的机器上进行构建,GLEW使用动态链接的话,我们要么为它要单独建立一个编译工程,要么我们自己要针对不同的目标机器,提前编译好各种不同机器上的dll或so库,这样可以说很麻烦
    2. Shipping the source连同代码一起发布:将GLEW库同OpenGL应用静态编译在一起,这种方式可以完美避开以上方式的缺点,唯一的缺点是GLEW库的代码量很大,它的存在增加了代码的复杂度,同时增加了代码的编译时间。GLEW如此庞大的原因是它维护了所有的OpenGL函数,而我们的应用可能只需要其中很小的一个子集,比如我们只需要modern opengl,也就是其core profile。

     

    如何定制自己的OpenGL Loader?

    github上有很多自定义的OpenGL loader,其中不乏短小精干,非常好用的库,比如https://gist.github.com/rygorous/16796a0c876cf8a5f542caddb55bce8a,在这个的基础上,可以增加一些跨平台的宏定义。

        #if defined(__linux__)
        #include <dlfcn.h>
        #define GLDECL                // Empty define
        #define PAPAYA_GL_LIST_WIN32  // Empty define
        #endif // __linux__
    
        #if defined(_WIN32)
        #include <windows.h>
        #define GLDECL WINAPI
    
        #define GL_ARRAY_BUFFER         0x8892
        #define GL_ARRAY_BUFFER_BINDING 0x8894
        ...
    
        typedef char GLchar;
        typedef ptrdiff_t GLintptr;
        typedef ptrdiff_t GLsizeiptr;
    
        #define PAPAYA_GL_LIST_WIN32 
            /* ret, name, params */ 
            GLE(void, BlendEquation, GLenum mode) 
            GLE(void, ActiveTexture, GLenum texture) 
            /* end */
    
        #endif // _WIN32

    上面代码我们首先包含不同平台的动态库调用的头文件。然后定义了windows平台下的函数调用规范的宏GLDECL。我们还需要包含GL/gl.h的头文件,但是这个文件在Linux和Windows上是不同的。Windows SDK包含的gl.h版本是非常老的(OpenGL 1.1),所以它并没有包含所有的OpenGL typedef,常量以及函数声明,但是Linux平台上一般是最新的。所以在Windows系统上需要手动添加这些定义。你可以直接包含这个文件https://www.khronos.org/registry/OpenGL/api/GL/glext.h,它包含这些常量和函数的定义。

    最后就是定义你需要的函数了,代码如下:

    #define BINKGL_LIST 
        /*  ret, name, params */ 
        GLE(void,      LinkProgram,         GLuint program) 
        GLE(void,      GetProgramiv,        GLuint program, GLenum pname, GLint *params) 
        GLE(GLuint,    CreateShader,        GLenum type) 
        GLE(void,      ShaderSource,        GLuint shader, GLsizei count, const GLchar* const *string, const GLint *length) 
        GLE(void,      CompileShader,       GLuint shader) 
        GLE(void,      GetShaderiv,         GLuint shader, GLenum pname, GLint *params) 
        GLE(void,      GetShaderInfoLog,    GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) 
        GLE(void,      DeleteShader,        GLuint shader) 
        GLE(GLuint,    CreateProgram,       void) 
        GLE(void,      AttachShader,        GLuint program, GLuint shader) 
        GLE(void,      DetachShader,        GLuint program, GLuint shader) 
        GLE(void,      UseProgram,          GLuint program) 
        GLE(void,      DeleteProgram,       GLuint program) 
        GLE(void,      GenVertexArrays,     GLsizei n, GLuint *arrays) 
        GLE(void,      BindVertexArray,     GLuint array) 
        GLE(void,      BufferData,          GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) 
        GLE(void,      GenBuffers,              GLsizei n, GLuint *buffers) 
        GLE(void,      BindBuffer,              GLenum target, GLuint buffer) 
        GLE(void,      DeleteBuffers,           GLsizei n, const GLuint *buffers) 
        GLE(void,      TexParameteri,           GLenum target, GLenum pname, GLint param) 
        GLE(void,      ActiveTexture,           GLenum texture) 
        GLE(void,      BindAttribLocation,      GLuint program, GLuint index, const GLchar *name) 
        GLE(GLint,     GetUniformLocation,      GLuint program, const GLchar *name) 
        GLE(void,      Uniform4f,               GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) 
        GLE(void,      Uniform4fv,    GLint location, GLsizei count, const GLfloat *value) 
        GLE(void,      DeleteVertexArrays,      GLsizei n, const GLuint *arrays) 
        GLE(void,      EnableVertexAttribArray, GLuint index) 
        GLE(void,      VertexAttribPointer,     GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer) 
        GLE(void,      Uniform1i,               GLint location, GLint v0) 
        /* end */
    
    #define GLE(ret, name, ...) typedef ret GLDECL name##proc(__VA_ARGS__); static name##proc * gl##name;
    BINKGL_LIST
    #undef GLE
    
    static void *GLhandle;
    
    bool gl_lite_init()
    {
    #if defined(__linux__)
    
        void* libGL = dlopen("libGL.so", RTLD_LAZY);
        if (!libGL) {
            printf("ERROR: libGL.so couldn't be loaded
    ");
            return false;
        }
    
        #define GLE(ret, name, ...)                                                    
                gl##name = (name##proc *) dlsym(libGL, "gl" #name);                    
                if (!gl##name) {                                                       
                    printf("Function gl" #name " couldn't be loaded from libGL.so
    "); 
                    return false;                                                      
                }
            BINKGL_LIST
        #undef GLE
    
    #elif defined(_WIN32)
    
        HINSTANCE dll = LoadLibraryA("opengl32.dll");
        typedef PROC WINAPI wglGetProcAddressproc(LPCSTR lpszProc);
        if (!dll) {
            OutputDebugStringA("opengl32.dll not found.
    ");
            return false;
        }
        wglGetProcAddressproc* wglGetProcAddress =
            (wglGetProcAddressproc*)GetProcAddress(dll, "wglGetProcAddress");
    
        #define GLE(ret, name, ...)                                                                    
                gl##name = (name##proc *)wglGetProcAddress("gl" #name);                                
                if (!gl##name) {                                                                       
                    OutputDebugStringA("Function gl" #name " couldn't be loaded from opengl32.dll
    "); 
                    return false;                                                                      
                }
            BINKGL_LIST
        #undef GLE
    
    #else
        #error "GL loading for this platform is not implemented yet."
    #endif
    
        return true;
    }
  • 相关阅读:
    Django实现注册,往邮箱发送验证链接
    初来乍到
    (spring-第5回【IoC基础篇】)spring容器从加载配置文件到实例化bean的内部工作机制
    (spring-第4回【IoC基础篇】)spring基于注解的配置
    (spring-第3回【IoC基础篇】)spring的依赖注入-属性、构造函数、工厂方法等的注入(基于XML)
    (spring-第2回【IoC基础篇】)Spring的Schema,基于XML的配置
    (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期
    Python的小数据池和编码解码
    Python数据类型之字典
    Python的基本数据类型(列表,元组)
  • 原文地址:https://www.cnblogs.com/hellobb/p/10315361.html
Copyright © 2011-2022 走看看