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)


相关推荐

  • FinalShell简单的使用

    FinalShell简单的使用今天真的是很丧的一天,早上来到公司写了一会代码,需要用xshell时发现,以前都能打开的xshell突然出问题了。如下截图…于是想着重启看看。我的天,重启之后,网卡没了,接着就是死活连不上网,不管设置什么都连接不上网,驱动也装不上去,反正就是十八般武艺全用上了(博主可能比较菜),都没作用,于是请人,反正弄了半天,给我放个大招,重装系统 。重装系统肯定就好了,可是环境都没了,开始一点…

  • xsync同步脚本的使用

    xsync同步脚本的使用xsync同步脚本的使用1.简介在集群机器配置时,经常需要将一个文件或目录copy到同样的多台集群上,如果一个一个机器去复制,比较麻烦。如果有一个办法,通过一条命令就可以实现这个目的,就简单多了。xsync就是这样一个同步脚本。xsync其实是对rsync脚本的二次封装,脚本内容可以根据自己需要进行修改。2.配置集群hostname2.1配置hostname文件在每台机器执行命令c…

  • 2020-java中级面试题

    2020-java中级面试题No. JD技术分类 问题 参考答案 判断标准 反馈 1 基础知识 HashMap和TreeMap区别 HashMap:①数组加链表方式存储key/value,②线程非安全,③允许null作为key和value,④key不可以重复,value允许重复,⑤不保证元素迭代顺序是按照插入时的顺序; TreeMap:①基于红黑树,②线程非安全,③不允许null作为key,④key不可以重复,value允许重复,⑤存入TreeMap的元素应当实现Compa..

    2022年10月12日
  • m3u8格式视频源列表[通俗易懂]

    m3u8格式视频源列表[通俗易懂]平时,需要测试m3u8格式视频的播放,会使用一些可用的播放源,整理在这里:constsourceList=[{name:’cctv1′,src:’http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8′},{name:’cctv2′,src:’http://ivi.bupt.edu.cn/hls/cc…

  • 基于近邻的协同过滤算法

    基于近邻的协同过滤算法这节课我们来学习K近邻在推荐系统中的应用,你将完成本课程的第一个实战项目:基于KNN的电影推荐系统!为了使你能够顺利地完成实战内容,我们先了解一下推荐系统中的基础知识。基于近邻用户的协同过滤假定有一个场景:某个周日的下午,你感觉很无聊,然后从电脑上打开了一个视频网站,想看下最近有什么好看的电影。然而你发现网站上的热门电影基本都看过,其他的电影又太多,不知道该看什么。想使用搜索框去查一下,但是又不知道该搜什么关键词,这个时候你的内心很焦灼,总不能挨个去尝试吧,那时间成本也太大了…仔细想想还是有办法的,那

  • 无锡梅里旅游策划方案——中国第一锡宫!

    无锡梅里旅游策划方案——中国第一锡宫!无锡梅里旅游策划方案——中国第一锡宫!熊大寻旅游策划公司/文无锡梅里古都”,位于无锡新区梅村,是吴文化的发祥地。梅村古名梅里,早在三千二百多年前,西周周太王长子泰伯,为达成父王想立三子季历的愿望,偕二弟仲雍托辞采药,夜奔江南,拴马于枯树桩。到清早,见枯枝上梅花朵朵,喜出望外,顿悟此地当为宝地。于是为其取“梅里”之名,定居于此。勾吴之国,由此发端。因泰伯三让两家天下,孔子称其为“至德”,司马迁的…

发表回复

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

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