NeHe OpenGL教程 学习笔记1
如果你
和我一样刚刚学习OpenGL,跟着教程走了一遍但还是感觉对一些东西的理解很模糊,你可以继续往下看,我们一起来探讨。如果不是,很抱歉浪费了您的时间。
PS:看了快三个星期的OpenGL了,NeHe的教程看似很简单(因为你只要照着敲就能做出一些很有意思的小demo出来),不过有很多地方需要自己去弄懂和理解的,于是就先把自己的理解写下来。所以,纯属个人简介,如有错误,欢迎指正。
Lesson 1 窗口的建立
1描述
创建一个window窗口,以此作为windows的载体。
Nehe的窗口框架搭建的非常好,理解的难点随之出现。这一课有许多关于OpenGL视图环境的设置函数,这里暂且略过(因为我现在还说不清),主要描述一下windows窗口的创建以及浅谈一些消息机制吧。
2流程
1.定义一个WNDCLASS窗口结构体(这个变量名貌似取得不是很好啊)
WNDCLASSwc;// 窗口类结构
wc.style= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;// 移动时重画,并为窗口取得DCwc.lpfnWndProc= (WNDPROC) WndProc;// WndProc处理消息wc.cbClsExtra= 0;// 无额外窗口数据wc.cbWndExtra= 0;// 无额外窗口数据wc.hInstance= hInstance;// 设置实例wc.hIcon= LoadIcon(NULL, IDI_WINLOGO);// 装入缺省图标wc.hCursor= LoadCursor(NULL, IDC_ARROW);// 装入鼠标指针wc.hbrBackground= NULL;// GL不需要背景wc.lpszMenuName= NULL;// 不需要菜单wc.lpszClassName= "OpenG";// 设定类名字
if (!RegisterClass(&wc))// 尝试注册窗口类{MessageBox(NULL,"注册窗口失败","错误",MB_OK|MB_ICONEXCLAMATION);return FALSE;// 退出并返回FALSE}hWnd=CreateWindowEx(dwExStyle,// 扩展窗体风格TEXT("OpenGL"),// 类名字(LPCWSTR)title,// 窗口标题dwStyle |// 必须的窗体风格属性WS_CLIPSIBLINGS |// 必须的窗体风格属性WS_CLIPCHILDREN,// 必须的窗体风格属性0, 0,// 窗口位置WindowRect.right-WindowRect.left,// 计算调整好的窗口宽度WindowRect.bottom-WindowRect.top,// 计算调整好的窗口高度NULL,// 无父窗口NULL,// 无菜单hInstance,// 实例NULL))ShowWindow(hWnd,SW_SHOW);// 显示窗口
staticPIXELFORMATDESCRIPTOR pfd=// /pfd 告诉窗口我们所希望的东东,即窗口使用的像素格式{sizeof(PIXELFORMATDESCRIPTOR),// 上述格式描述符的大小1,// 版本号PFD_DRAW_TO_WINDOW |// 格式支持窗口PFD_SUPPORT_OPENGL |// 格式必须支持OpenGLPFD_DOUBLEBUFFER,// 必须支持双缓冲PFD_TYPE_RGBA,// 申请 RGBA 格式bits,// 选定色彩深度0, 0, 0, 0, 0, 0,// 忽略的色彩位0,// 无Alpha缓存0,// 忽略Shift Bit0,// 无累加缓存0, 0, 0, 0,// 忽略聚集位16,// 16位 Z-缓存 (深度缓存)0,// 无蒙板缓存0,// 无辅助缓存PFD_MAIN_PLANE,// 主绘图层0,// Reserved0, 0, 0// 忽略层遮罩}; if (!(hDC=GetDC(hWnd)))// 取得设备描述表了么?{KillGLWindow();// 重置显示区MessageBox(NULL,"不能创建一种相匹配的像素格式","错误",MB_OK|MB_ICONEXCLAMATION);return FALSE;// 返回 FALSE}if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))// Windows 找到相应的象素格式了吗?{KillGLWindow();// 重置显示区MessageBox(NULL,TEXT("不能创建一种相匹配的像素格式"),TEXT("错误"),MB_OK|MB_ICONEXCLAMATION);return FALSE;// 返回 FALSE}if(!SetPixelFormat(hDC,PixelFormat,&pfd))// 能够设置象素格式么?{KillGLWindow();// 重置显示区MessageBox(NULL,TEXT("不能设置像素格式"),TEXT("错误"),MB_OK|MB_ICONEXCLAMATION);return FALSE;// 返回 FALSE}if (!(hRC=wglCreateContext(hDC)))// 能否取得OpenGL渲染描述表?{KillGLWindow();// 重置显示区MessageBox(NULL,TEXT("不能创建OpenGL渲染描述表"),TEXT("错误"),MB_OK|MB_ICONEXCLAMATION);return FALSE;// 返回 FALSE}if(!wglMakeCurrent(hDC,hRC))// 尝试激活着色描述表{KillGLWindow();// 重置显示区MessageBox(NULL,TEXT("不能激活当前的OpenGL渲然描述表"),TEXT("错误"),MB_OK|MB_ICONEXCLAMATION);return FALSE;// 返回 FALSE}int InitGL(GLvoid){glShadeModel(GL_SMOOTH);//阴影模式glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//背景色//深度缓存设置和测试glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LEQUAL);//让系统修正透视glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);buildFont();return TRUE;}while(!done)// 保持循环直到 done=TRUE{if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))// 有消息在等待吗?{if (msg.message==WM_QUIT)// 收到退出消息?{done=TRUE;// 是,则done=TRUE}else// 不是,处理窗口消息{TranslateMessage(&msg);// 翻译消息DispatchMessage(&msg);// 发送消息}}else// 如果没有消息{// 绘制场景。监视ESC键和来自DrawGLScene()的退出消息if (active)// 程序激活的么?{if (keys[VK_ESCAPE])// ESC 按下了么?{done=TRUE;// ESC 发出退出信号}else// 不是退出的时候,刷新屏幕{DrawGLScene();// 绘制场景SwapBuffers(hDC);// 交换缓存 (双缓存)}}if (keys[VK_F1])// F1键按下了么?{keys[VK_F1]=FALSE;// 若是,使对应的Key数组中的值为 FALSEKillGLWindow();// 销毁当前的窗口fullscreen=!fullscreen;// 切换 全屏 / 窗口 模式// 重建 OpenGL 窗口if (!CreateGLWindow(TEXT("NeHe's OpenGL 程序框架"),640,480,16,fullscreen)){return 0;// 如果窗口未能创建,程序退出}}}}TranslateMessage(&msg);// 翻译消息DispatchMessage(&msg);// 发送消息
LRESULT CALLBACK WndProc(HWNDhWnd,// 窗口的句柄UINTuMsg,// 窗口的消息WPARAMwParam,// 附加的消息内容LPARAMlParam)// 附加的消息内容{switch (uMsg)// 检查Windows消息{case WM_ACTIVATE:// 监视窗口激活消息{if (!HIWORD(wParam))// 检查最小化状态{active=TRUE;// 程序处于激活状态}else{active=FALSE;// 程序不再激活}return 0;// 返回消息循环} //各种消息类别的处理....省略}// 向 DefWindowProc传递所有未处理的消息。return DefWindowProc(hWnd,uMsg,wParam,lParam);}