1) WGL_EXT_swap_control 扩展来实现垂直同步比较简单:
//in wglext.h
#ifndef WGL_EXT_swap_control
#define WGL_EXT_swap_control 1
#ifdef WGL_WGLEXT_PROTOTYPES
extern BOOL WINAPI wglSwapIntervalEXT (int);
extern int WINAPI wglGetSwapIntervalEXT (void);
#endif /* WGL_WGLEXT_PROTOTYPES */
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
#endif
//our source code
#include <gl/wglext.h>
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT ;
PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT ;
//after opengl render context being created
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress( "wglSwapIntervalEXT") ;
wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) wglGetProcAddress( "wglGetSwapIntervalEXT") ;
wglSwapIntervalEXT(1);
int vsync_count = wglGetSwapIntervalEXT();//如果vsync_count 和wglSwapIntervalEXT设置的数量不同,将没有vsync效果.
//in opengl extensions
http://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
Overview
This extension allows an application to specify a minimum periodicity
of color buffer swaps, measured in video frame periods.
这个扩展允许OPENGL应用程序指定一个翻转颜色缓存的最小周期,这个最小周期是以视频刷新周期度量的
A video frame period is the time required by the monitor to display a
full frame of video data. In the case of an interlaced monitor,
this is typically the time required to display both the even and odd
fields of a frame of video data.
视频刷新周期就是视频监视器显示完整的一帧图像所需要的数据所需要的时间。对于隔行扫描方式的监视器,这个时间就是是奇数场和偶数场的总共时间。
另外,网上有说所有的N卡都支持这个扩展,而A卡和3dlabs不支持这个扩展,,,这个说法我没有考证过,但是的确WGL_EXT_swap_control 属于“厂商扩展”,而不是“ARB扩展”。
难保有的显卡不支持这项功能;另一个更安全的方法是使用DirectDraw...不过对于我们用OPENGL的来说,好像不太喜欢ms的DirectX系列,,,但这的确是一个不错的方法:
1) 使用DirectDraw 来实现垂直同步:
#include <ddraw.h>
#pragma comment(lib,"ddraw.lib")
//before create opengl render context
HRESULT hr = DirectDrawCreateEx(NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL);
DDSURFACEDESC2 ddsd;
DDSCAPS2 ddscaps;
m_pDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL );
memset(&ddsd, 0, sizeof(ddsd)); // Set all fields of struct to 0 and set .dwSize to
ddsd.dwSize = sizeof(ddsd); // Sizeof the variable - these two steps required for most DDraw structs
ddsd.dwFlags = DDSD_CAPS; // Set flags for variables we're using...
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; // Set the variables we said we would in dwFlags
hr = m_pDD->CreateSurface(&ddsd, &m_pDDSPrimary, NULL);
//on draw
m_pDD->WaitForVerticalBlank( DDWAITVB_BLOCKBEGIN, NULL);
SwapBuffers( m_hdc );
//on destroy
if( m_pDDSPrimary )
m_pDDSPrimary->Release();
m_pDDSPrimary = NULL;
if( m_pDD )
m_pDD->Release();
m_pDD = NULL;
这个方法不仅支持垂直同步,而且可以让opengl全屏幕程序独占屏幕。