这里说的全屏抗锯齿,不是基于着色器的FXAA之类的方式,而是兼容性更好的,基于固定管线的多重采样方式。
先来说一下开发环境,我用的是VC2013+GLEW1.11。
要通过程序设置多重采样,首先需要进入控制面板,确定抗锯齿的设置是“根据应用程序而定” ,当然,这个设置的具体名称,不同的显卡厂商有不同的叫法。
接下来,就是重点了。
Windows下要通过程序设置多重采样,必须使用wglChoosePixelFormatARB这个函数。目前网上基本都是自己去获取这个函数的接口地址,其实根本不用这么麻烦。GLEW已经有这个函数接口了,我们要做的,就是正确地使用而已。正确使用这个函数的关键,就是需要创建一个临时窗体,通过这个窗体,我们可以初始化GLEW,以及获取必须的基础像素格式,然后再使用wglChoosePixelFormatARB这个函数,得到可用的多重采样像素格式,最后,对渲染窗口设置这个像素格式即可。
//----------创建一个临时窗体
HWND secondwnd; WNDCLASS wc; //窗体类结构体 wc.style = CS_HREDRAW | CS_VREDRAW; //窗体风格 wc.lpfnWndProc = WndProc; //窗体处理函数 wc.cbClsExtra = 0; //窗体类是否由扩展 wc.cbWndExtra = 0; //窗体实例是否由扩展 wc.hInstance = NULL; //窗体句柄 wc.hIcon = LoadIcon(0, IDI_APPLICATION); //窗体图标 wc.hCursor = LoadCursor(NULL, IDC_ARROW); //窗体鼠标样式 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //窗体背景颜色 wc.lpszMenuName = NULL; //窗体菜单 wc.lpszClassName = L"BaseWndClass"; //窗体类名 if (!RegisterClass(&wc)) //判断窗体是否注册成功 { MessageBox(L"注册失败"); return; } //创建窗体 secondwnd = CreateWindow(L"BaseWndClass", //窗体类名 L"MyFrom", //窗体标题名 WS_OVERLAPPEDWINDOW, //窗体风格 CW_USEDEFAULT, CW_USEDEFAULT, //窗体坐标 CW_USEDEFAULT, CW_USEDEFAULT, //窗体坐标 NULL, //窗体的父窗体 NULL, //窗体的子菜单 NULL, //窗体句柄 NULL); // 如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL if (secondwnd == 0)//判断创建窗体是否成功 { MessageBox(L"创建窗体失败"); return; } ::ShowWindow(secondwnd, SW_HIDE); //显示窗体 ::UpdateWindow(secondwnd); //绘制窗体; PIXELFORMATDESCRIPTOR pfd = //定义像素格式 { sizeof(PIXELFORMATDESCRIPTOR), // 上述格式描述符的大小 1, // 版本号 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, // 申请 RGBA 格式 32, 0, 0, 0, 0, 0, 0, // 忽略的色彩位 8, // 无Alpha缓存 0, // 忽略Shift Bit 0, // 无累加缓存 0, 0, 0, 0, // 忽略聚集位 32, // 32位 Z-缓存 (深度缓存) 8, // 无蒙板缓存 0, // 无辅助缓存 PFD_MAIN_PLANE, // 主绘图层 0, // Reserved 0, 0, 0 // 忽略层遮罩 }; //----------用这个临时窗体得到一个可用HGLRC HDC secondDC = ::GetDC(secondwnd); int nIndex = ChoosePixelFormat(secondDC, &pfd); //选择刚刚定义的像素格式 if (nIndex == 0) { return; } SetPixelFormat(secondDC, nIndex, &pfd); //设置像素格式 glRC = wglCreateContext(secondDC); wglMakeCurrent(secondDC, glRC); //----------然后初始化GLEW GLenum glerr = glewInit(); if (glerr != GLEW_OK) { MessageBox(L"无法初始化GLEW!"); } else { OutputDebugString(L"成功加载GLEW\n"); } UINT Multisample = 4; //4倍多重采样率 int pixelformat; UINT numformat; float fAttributes[] = { 0, 0 }; int iAtributes[] = { WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB, 24, WGL_ALPHA_BITS_ARB, 8, WGL_DEPTH_BITS_ARB, 32, WGL_STENCIL_BITS_ARB, 8, WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, WGL_SAMPLES_ARB, Multisample, 0, 0 }; //----------取得可用的多重采样像素格式 if (!wglChoosePixelFormatARB(secondDC, iAtributes, fAttributes, 1, &pixelformat, &numformat)) { MessageBox(L"找不到可用的抗锯齿格式"); } //----------删除由临时窗体得到的HGLRC,同时销毁临时窗体 wglMakeCurrent(NULL, NULL); wglDeleteContext(glRC); ::ReleaseDC(secondwnd, secondDC); ::DestroyWindow(secondwnd); //----------用得到的多重采样像素格式,设置渲染窗体 SetPixelFormat(this->GetDC()->m_hDC, pixelformat, &pfd); //设置像素格式 glRC = wglCreateContext(this->GetDC()->m_hDC); wglMakeCurrent(this->GetDC()->m_hDC, glRC);
上面这段代码,就是按照我所说的方式初始化了OpenGL。
这样设置后,你就能通过glEnable/glDisable启用或禁用多重采样了。
希望这点经验能够对和我一样曾困于此问题的朋友有所帮助。