windows/mfc程序中使用OpenGL的多重采样功能

windows/mfc程序中使用OpenGL的多重采样功能windows程序中使用OpenGL的多重采样功能学过opengl基础的人都知道,glEnable(GL_POLYGON_SMOOTH)/glEnable(GL_LINE_SMOOTH)/glEnable(GL_POLYGON_SMOOTH)keyi欢迎使用Markdown编辑器你好!这是你第一次使用Markdown编辑器所展示的欢迎页。如果你想学习如何使用Markdown编辑器,…

大家好,又见面了,我是你们的朋友全栈君。

windows/mfc程序中使用OpenGL的多重采样功能

学过opengl基础的人都知道,打开混合功能并调用glEnable(GL_POINT_SMOOTH)/glEnable(GL_LINE_SMOOTH)可以实现模型点/线的反走样功能,非常简单且效果不错。
未使用反走样 使用了线的反走样
但是对于实心多边形的支持却没有那么简单,单纯的调用 glEnable(GL_POLYGON_SMOOTH)发现并没有效果。
多边形的锯齿化
OpenGL对于多边形的反走样有另一个多重采样的特性支持——glEnable(GL_MULTISAMPLE)
但是当调用后发现还是不起作用,查阅资料后才发现在Windows程序中要想使用OpenGL的多重采样,需要额外的一些操作。

一般情况下MFC程序创建OpenGL环境

普通的Windows OpenGL程序在OnCreat()函数中完成环境初始化比较简单

int OnCreate(LPCREATESTRUCT lpCreateStruct)
{ 

CWnd::OnCreate(lpCreateStruct);
PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL
| PFD_DOUBLEBUFFER/* PFD_SUPPORT_GDI*/ | PFD_STEREO_DONTCARE;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cRedBits = 8;
pfd.cRedShift = 16;
pfd.cGreenBits = 8;
pfd.cGreenShift = 8;
pfd.cBlueBits = 8;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 64;
pfd.cAccumRedBits = 16;
pfd.cAccumGreenBits = 16;
pfd.cAccumBlueBits = 16;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 32;
pfd.cStencilBits = 8;
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask = 0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
CDC* wnd_dc = GetDC();
if (!wnd_dc) return -1;
HDC dc_handle = wnd_dc->GetSafeHdc();
int choosed_pixel_format = ChoosePixelFormat(dc_handle, &pfd);
if (0 == choosed_pixel_format)
{ 

choosed_pixel_format = 1;
if (0 == DescribePixelFormat(dc_handle, choosed_pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
{ 

ReleaseDC(wnd_dc);
return -1;
}
}
if (FALSE == SetPixelFormat(dc_handle, choosed_pixel_format, &pfd))
{ 

ReleaseDC(wnd_dc);
return -1;
}
HGLRC render_context = wglCreateContext(dc_handle);
if (dc_handle && render_context && TRUE == wglMakeCurrent(dc_handle, render_context))
{ 

GLenum err = glewInit();
}
return 0}

如何使用OpenGL的多重采样

上面方式最主要的问题是PIXELFORMATDESCRIPTOR的数据结构是固定的,没有对多重采样的支持,要想使用此特性可以使用wglew库的wglChoosePixelFormatARB函数替换ChoosePixelFormat,但是使用wglChoosePixelFormatARB函数必须先调用glewInit()来初始化glew库,要初始化glew库则必须先得到窗口的渲染上下文,于是就必须先有一个临时窗口,但不能是真正的窗口。具体过程如下:

int OnCreate(LPCREATESTRUCT lpCreateStruct)
{ 

CWnd::OnCreate(lpCreateStruct);
CWnd tempWnd;    
tempWnd.Create(_T("STATIC"), _T("TMP"), WS_CHILD | WS_VISIBLE, CRect(), AfxGetMainWnd(), NULL);
HDC tempHdc = tempWnd.GetDC()->GetSafeHdc();
PIXELFORMATDESCRIPTOR pfd;
if (!SetPixelFormat(tempHdc, 1, &pfd))		//每个窗口只能设置一次 
return -1;
HGLRC temphRC = wglCreateContext(tempHdc);  //创建一个临时的环境为了初始化glew
wglMakeCurrent(tempHdc, temphRC);      
GLenum err = glewInit();                    //初始化glew库,一个程序中初始化一次就可以,不需要每个opengl环境都初始化
if (GLEW_OK != err) return -1;
wglMakeCurrent(NULL, NULL);
wglDeleteContext(temphRC);
tempWnd.DestroyWindow();    
float fPixAttribs[] = { 
 0, 0 };
int iPixAttribs[] = { 
 WGL_SUPPORT_OPENGL_ARB, GL_TRUE, // Must support OGL rendering
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, // pf that can run a window 
WGL_ACCELERATION_ARB,
WGL_FULL_ACCELERATION_ARB, // must be HW accelerated
WGL_COLOR_BITS_ARB, 32, // 8 bits of each R, G and B
WGL_DEPTH_BITS_ARB, 24, // 24 bits of depth precision for window
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, // Double buffered context
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, // pf should be RGBA type
WGL_STENCIL_BITS_ARB, 8,//开启模板缓冲区,模板缓冲区位数=8
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, // MSAA on,开启多重采样
WGL_SAMPLES_ARB, 4, // 4x MSAA ,多重采样样本数量为4
0 }; // NULL termination 
CDC* wnd_dc = GetDC();
if (!wnd_dc) return -1;
HDC dc_handle = wnd_dc->GetSafeHdc();
if (!wnd_dc) return -1;
int nPixelFormat = -1;
int nPixCount = 0;
wglChoosePixelFormatARB(dc_handle, iPixAttribs, fPixAttribs, 1, &nPixelFormat, (UINT*)&nPixCount);//新的查询像素格式的函数 
if (nPixelFormat == -1)    //多重采样时,如果硬件不支持就使用下面的代码关闭多重采样 
{ 
 // Try again without MSAA 
iPixAttribs[19] = 1;
wglChoosePixelFormatARB(dc_handle, iPixAttribs, fPixAttribs, 1, &nPixelFormat, (UINT*)&nPixCount);
} // Got a format, now set it as the current one
PIXELFORMATDESCRIPTOR pfd;
if (!SetPixelFormat(dc_handle, nPixelFormat, &pfd))
return -1;
GLint attribs[] = { 
 WGL_CONTEXT_MAJOR_VERSION_ARB, 4,//主版本4
WGL_CONTEXT_MINOR_VERSION_ARB, 3,//次版本号3
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
0 };
render_context = wglCreateContextAttribsARB(dc_handle, 0, attribs);
if (m_gl_rendering_context == NULL)
{ 

TRACE0("!!! Could not create an OpenGL 4.3 context.\n");
attribs[1] = 1;
attribs[3] = 3;
render_context = wglCreateContextAttribsARB(dc_handle, 0, attribs);
if (render_context == NULL)
{ 

TRACE0("!!! Could not create an OpenGL 1.3 context.\n");
return -1;
}
}
if(!wglMakeCurrent(dc_handle, render_context))
return -1;
}

如此初始化后,再调用 glEnable(GL_MULTISAMPLE)多重采样就起作用啦,效果非常明显:

打开GL_MULTISAMPLE前
打开GL_MULTISAMPLE后

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/143672.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 操作系统概念第六章部分作业题答案

    操作系统概念第六章部分作业题答案题目一:如果将peterson算法中的flag[i]=true与turn=j两条语句交换顺序,会导致求解临界区问题所需三个要求(互斥、有空让进、有限等待)中的哪些要求得不到满足?请举例并分析说明得不到满足的情况解答:假设两个进程i和j:进程i的进入区代码是这样的flag[i]=TRUE;turn=j;while(flag[j]==TRUE&&…

  • 频次最高的38道selenium面试题及答案(上)「建议收藏」

    频次最高的38道selenium面试题及答案(上)「建议收藏」1、selenium的原理是什么?selenium的原理涉及到3个部分,分别是:浏览器 driver:一般我们都会下载driver client:也就是我们写的代码client其实并不知道浏览器是怎么工作的,但是driver知道,在selenium启动以后,driver其实充当了服务器的角色,跟client和浏览器通信,client根据webdriver协议发送请求给driver,driver解析请求,并在浏览器上执行相应的操作,并把执行结果返回给client。这就是seleniu…

  • HDU 2254 奥运(数论+矩阵)

    HDU 2254 奥运(数论+矩阵)

  • ASP.NET中DropDownList 的使用

    ASP.NET中DropDownList 的使用1.如何避免DropDownList下拉框中重复值出现?AppendDataBoundItems:为是否填加重复值。真为添加,假为不填加 将DropDownList控件中AppendDataBoundItems属性设置为“False”即可。 2.如何给DropDownList添加项?//1.PreRender事件,在呈现该页前激发protectedvoidDropDow…

    2022年10月17日
  • 访问页面升级访问_BPC页面访问缓慢无报错

    访问页面升级访问_BPC页面访问缓慢无报错概述引起BPC的页面访问缓慢的原因有很多,可能是由于网络慢、可能是由于BPC进程太忙、也可能是由于mongo数据库性能吃紧,所以对于页面访问缓慢需要根据具体情况实施解决方案注意:本文分析的页面访问缓慢,仅是慢,但不报错知识点根据前台页面表现来大致区分一下问题的归属:仅查询数据的页面访问缓慢点击链接跳转时,在当前页面停留较长时间可能是web处理不过来可能是网络慢或忙点击链接跳转时,页面白屏…

  • 关于java类加载正确的是_java运行无法加载主类

    关于java类加载正确的是_java运行无法加载主类注意我们当在另一个类中引用其他类的final静态值的时候,编译器把其他类的final符号引用存储在自己类的常量池中了

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号