Opengl ES2.0 Programming Guide 书中附带的exmaple,创建了一个Windows窗口,通过几个简单的回调函数传递事件,交互起来实在太繁琐了。所以改用SDL2显示GLES2,SDL的事件更加便于交互。
当然了 Webgl Programming Guide 讲述了如何在浏览器中使用GLES2,调试分享起来也非常便捷,并且没有了繁琐的环境搭建过程,也不失为一种好的方法。
这里可以找到示例代码
bug: msys2安装的angle无法使用glDrawElements函数
如果使用Linux,你可以在包管理中轻而易举地找到关于GLES的开发包。但是Windows上哪里找呢? Angle是由谷歌发起的项目,在各个平台上实现了GLES2甚至GLES3,被大名鼎鼎的Chrome和Qt也使用,Webgl也是基于他实现的!
如果有能连接Google的网络环境,可以自己编译。简便的方法是安装msys2,在包管理中安装angle,不要忘了,一起安装SDL2和编译器
pacman -Ss angle # 你可以在pacman中搜索到angleproject
···
mingw32/mingw-w64-i686-angleproject-git 2.1.r6846-1
ANGLE project built from git source (mingw-w64)
···
mingw64/mingw-w64-x86_64-angleproject-git 2.1.r6846-1 [installed]
ANGLE project built from git source (mingw-w64)
···
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-angleproject-git mingw-w64-x86_64-SDL2 mingw-w64-x86_64-pkg-config
Angle包含了GLESv2和EGL,EGL用来管理GLES的上下文环境,如同WGL(Windows)、GLX(X Window, Linux)…一样。 GLES是与平台无关的图形库,如开头所说的Windows窗口,需要通过EGL与GLES关联起来才可以显示。但是GLES的EGL与WGL,GLX这些管理GL上下文的库是不相通用的,所以EGL在不同平台都有相应的实现。
根据不同平台,SDL自动选择WGL、GLX…来创建OpenGL上下文环境,并关联到SDL窗口。 如果一开始在Windows平台上创建GLES Context是不行的,即便是你添加了一下代码,也是毫无反应的。
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
我一开始在网上找了一大圈,发现很多类似问题。SDL2的release note上却说,SDL2的某次更新支持了在Windows上通过Angle来调用GLES API。这是因为msys2中的SDL2在编译时根据platform和config选择了WGL管理GL上下文环境,而不是EGL,因而无论如何配置都不能起作用。
// SDL_windowsvideo.c
#if SDL_VIDEO_OPENGL_WGL
device->GL_LoadLibrary = WIN_GL_LoadLibrary;
···
#elif SDL_VIDEO_OPENGL_EGL
/* Use EGL based functions */
device->GL_LoadLibrary = WIN_GLES_LoadLibrary;
···
#endif
对应的函数在 SDL_windowsopengles.c 中均有实现,只是没有被加载。
但这并不意味着你需要重新编译,你只需要获取SDL在Windows上的的窗口句柄,自己初始化EGL,使用 eglSwapBuffers 进行绘图更新就可以了。
#include
#include
#include
#include
int Init_Angle_EGL(SDL_Window *win, EGL_Swap *swap)
{
EGLint configAttribList[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_STENCIL_SIZE, 8,
EGL_SAMPLE_BUFFERS, 1,
EGL_NONE};
EGLint surfaceAttribList[] =
{
EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE,
EGL_NONE, EGL_NONE};
EGLint numConfigs;
EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display;
EGLContext context;
EGLSurface surface;
EGLConfig config;
EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE};
SDL_SysWMinfo info;
SDL_VERSION(&info.version); // initialize info structure with SDL version info
SDL_bool get_win_info = SDL_GetWindowWMInfo(win, &info);
SDL_assert_release(get_win_info);
EGLNativeWindowType hWnd = info.info.win.window;
// Get Display
display = eglGetDisplay(GetDC(hWnd)); // EGL_DEFAULT_DISPLAY
if (display == EGL_NO_DISPLAY)
{
return EGL_FALSE;
}
// Initialize EGL
if (!eglInitialize(display, &majorVersion, &minorVersion))
{
return EGL_FALSE;
}
// Get configs
if (!eglGetConfigs(display, NULL, 0, &numConfigs))
{
return EGL_FALSE;
}
// Choose config
if (!eglChooseConfig(display, configAttribList, &config, 1, &numConfigs))
{
return EGL_FALSE;
}
// Create a surface
surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, surfaceAttribList);
if (surface == EGL_NO_SURFACE)
{
return EGL_FALSE;
}
// Create a GL context
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
if (context == EGL_NO_CONTEXT)
{
return EGL_FALSE;
}
// Make the context current
if (!eglMakeCurrent(display, surface, surface, context))
{
return EGL_FALSE;
}
printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
printf("GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
swap->display = display;
swap->surface = surface;
return EGL_TRUE;
}
int main(int argc, char *argv[])
{
...
SDL_Window *win = SDL_CreateWindow(...);
Init_Angle_EGL(win, &swap);
...
while (run)
{
...
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(swap.display, swap.surface);
}
...
return 0;
}
你可以看到关于Angle的一些信息
GL_RENDERER: ANGLE (Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0)
GL_VERSION: OpenGL ES 2.0 (ANGLE 2.1.0.unknown hash)
GL_SHADING_LANGUAGE_VERSION: OpenGL ES GLSL ES 1.00 (ANGLE 2.1.0.unknown hash)