(译)SimpleGLXWindow类
来源:互联网 发布:c语言初学者看什么书 编辑:程序博客网 时间:2024/06/08 03:26
介绍
在OpenGL游戏编程 - 第二版发布之后,很明显,最后一章中使用的SimpleGLXWindow类没有记载在书中!所以,对于那些喜欢快速开始的Linux用户来说,下面就是了!
类结构
SimpleGLXWindow的类结构与Win32版本非常相似。像Win32版本一样,它继承了BOGLGPWindow基类,因此实现了相同的虚拟方法。这里是类定义的参考:
class SimpleGLXWindow : public BOGLGPWindow{public: SimpleGLXWindow(); //default constructor virtual ~SimpleGLXWindow(); bool create(int width, int height, int bpp, bool fullscreen); void destroy(); void processEvents(); void attachExample(Example* example); bool isRunning(); //Is the window running? void swapBuffers() { glXSwapBuffers(m_display, m_XWindow); } float getElapsedSeconds(); KeyboardInterface* getKeyboard() const { return m_keyboard; } MouseInterface* getMouse() const { return m_mouse; }private: Example* m_example; //A link to the example program bool m_isRunning; //Is the window still running? Example* getAttachedExample() { return m_example; } unsigned int m_lastTime; Display* m_display; Window m_XWindow; GLXContext m_glContext; XF86VidModeModeInfo m_XF86DeskMode; XSetWindowAttributes m_XSetAttr; int m_screenID; bool m_isFullscreen; unsigned int m_width; unsigned int m_height; unsigned int m_bpp; bool m_GL3Supported; KeyboardInterface* m_keyboard; MouseInterface* m_mouse;};
窗口创建
窗口类最重要最复杂的部分是创建OpenGL窗口的代码。我们要做的第一件事就是使用XOpenDisplay获取默认显示的句柄,通过传递一个零(或NULL),这将获取DISPLAY环境变量中设置的任何显示(通常是用来查看桌面的那个) !)。
m_display = XOpenDisplay(0); //Open default displayif (m_display == NULL){ std::cerr << "Could not open the display" << std::endl; return false;}
所以,我们已经抓住了默认显示,如果有错误,我们已经记录了它,并返回false以指示窗口创建失败。接下来,我们得到一个标识显示器默认屏幕的句柄:
m_screenID = DefaultScreen(m_display); //Get the default screen id ```现在,我们列出可用的显示模式,看看是否符合我们的要求。如果不是的话,我们会退出一个错误:
XF86VidModeModeInfo **modes;
if (!XF86VidModeGetAllModeLines(m_display, m_screenID, &modeNum, &modes))
{
std::cerr << “Could not query the video modes” << std::endl;
return false;
}
int bestMode = -1;
for (int i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == width) &&
(modes[i]->vdisplay == height))
{
bestMode = i;
}
}
if (bestMode == -1)
{
std::cerr << “Could not find a suitable graphics mode” << std::endl;
return false;
}
“`
在我们存储了最佳匹配的显示模式之后,我们要求一个具有16位深度缓冲区的双缓冲窗口:
int doubleBufferedAttribList [] = { GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None};XVisualInfo* vi = NULL;//Attempt to create a double buffered windowvi = glXChooseVisual(m_display, m_screenID, doubleBufferedAttribList);if (vi == NULL){ std::cerr << "Could not create a double buffered window" << std::endl; return false;} ```下一步是创建一个OpenGL 2.1上下文,所以我们可以请求一个GL3。这些是我们必须采取的与Windows相同的步骤:
//Create a GL 2.1 context
GLXContext gl2Context = glXCreateContext(m_display, vi, 0, GL_TRUE);
if (gl2Context == NULL)
{
std::cerr << “Could not create a GL 2.1 context, please check your graphics drivers” << std::endl;
return false;
}
//Get a pointer to the GL 3.0 context creation
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((GLubyte*)”glXCreateContextAttribsARB”);
if (glXCreateContextAttribs == NULL)
{
std::cerr << “OpenGL 3.0 is not supported, falling back to 2.1” << std::endl;
m_glContext = gl2Context;
m_GL3Supported = false;
}
else
{
//Create a GL 3.0 context
int attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3,//we want a 3.0 context GLX_CONTEXT_MINOR_VERSION_ARB, 0, 0 //zero indicates the end of the array};m_glContext = glXCreateContextAttribs(m_display, framebufferConfig, 0, true, &attribs[0]);glXDestroyContext(m_display, gl2Context); //We can destroy the GL 2.0 context once the 3.0 one has bene createdm_GL3Supported = true;
}
“`
如果不支持OpenGL 3.0,我们设置一个标志,以便我们可以使用后备2.1着色器。
现在我们有足够的信息来实际创建窗口。记得我们存储了我们能找到的最好的显示模式吗?在设置了一些窗口配置设置后,我们使用下面的代码:
Colormap cmap = XCreateColormap(m_display, RootWindow(m_display, vi->screen),vi->visual, AllocNone);m_XSetAttr.colormap = cmap;m_XSetAttr.border_pixel = 0;m_XSetAttr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | StructureNotifyMask;m_XSetAttr.override_redirect = False;unsigned long windowAttributes = CWBorderPixel | CWColormap | CWEventMask;if (fullscreen){ windowAttributes = CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; XF86VidModeSwitchToMode(m_display, m_screenID, modes[bestMode]); XF86VidModeSetViewPort(m_display, m_screenID, 0, 0); m_XSetAttr.override_redirect = True;}m_XWindow = XCreateWindow(m_display, RootWindow(m_display, vi->screen), 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &m_XSetAttr); ```最后,我们设置窗口标题,如果我们是全屏,我们抓住光标:
if (fullscreen)
{
XWarpPointer(m_display, None, m_XWindow, 0, 0, 0, 0, 0, 0);
XMapRaised(m_display, m_XWindow);
XGrabKeyboard(m_display, m_XWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(m_display, m_XWindow, True, ButtonPressMask,
GrabModeAsync, GrabModeAsync, m_XWindow, None, CurrentTime);
m_isFullscreen = true;
}
else
{
Atom wmDelete = XInternAtom(m_display, “WM_DELETE_WINDOW”, True);
XSetWMProtocols(m_display, m_XWindow, &wmDelete, 1);
XSetStandardProperties(m_display, m_XWindow, title.c_str(), None, NULL, NULL, 0, NULL);
XMapRaised(m_display, m_XWindow);
}
XFree(modes);
上面的最后一行释放了我们之前搜索的显示模式的内存。破坏窗口这很简单,代码如下:
void SimpleGLXWindow::destroy()
{
m_mouse->showCursor(true);
if (m_glContext)
{
glXMakeCurrent(m_display, None, NULL);
glXDestroyContext(m_display, m_glContext);
m_glContext = NULL;
}
if (m_isFullscreen){ XF86VidModeSwitchToMode(m_display, m_screenID, &m_XF86DeskMode); XF86VidModeSetViewPort(m_display, m_screenID, 0, 0);}XCloseDisplay(m_display);
}
“`
基本上,我们确保光标是可见的,然后我们销毁OpenGL上下文,最后在完成时切换显示模式。我们在显示器上释放我们的手柄,窗户被完全破坏。
如果您还有其他问题,无论是关于本文还是本书,或者在论坛上告诉我,或者在Twitters上戳我。
- (译)SimpleGLXWindow类
- 【译】QSerialPort类
- WebFrame类参考(译)
- (译)Objective-C 类属性
- MFC 预编译指令(类演示)
- gcc -E 预编译模板类
- JAVA中的Scanner类(IO)[JAVA][译]
- 防止类继承,摘自Bjarne的faq(紫云英译)
- LibGdx文档译读(十二) InputEventQueue类
- LibGdx文档译读(十三) AssetManager类
- LibGdx文档译读(十七) FileHandle类
- [译]Python提高:Python类和面向对象编程
- java中的反射 2.3——类:发现类成员@译自Oracle官方文档
- java中的反射 2.1——类:获取类对象@译自Oracle官方文档
- Head First C# 中文版 图文皆译 第七章 接口和抽象类 page251
- Head First C# 中文版 图文皆译 第七章 接口和抽象类 page252
- Head First C# 中文版 图文皆译 第七章 接口和抽象类 page253
- Head First C# 中文版 图文皆译 第七章 接口和抽象类 page254
- 算法的封装与切换——策略模式(三)
- 移动光标到相应的文本(比如项目中,插入了图片之后,即在插入的地方显示光标)
- case表达式和decode函数
- iPtables规则保存及加载等操作
- 真或假
- (译)SimpleGLXWindow类
- screen使用方法
- 十进制与二进制之间的联系
- .Net网站架构设计(五) 消息中间件
- 带你搞懂朴素贝叶斯分类算法
- EOJ 3441-唐纳德与子串 (Easy)
- ABAP表抛FTP通用程序
- 人工智障学习笔记——机器学习(11)PCA降维
- android 自定义相机返回图片URL,高清