使用OpenGL在电脑屏幕上绘图

       学过OpenGL的人都知道,要想利用OpenGL函数进行绘图,就要创建一个显示窗口。每次绘图,第一件事恐怕就是创建窗口了。肯定也有人跟我一样想过:能不能不在那个黑乎乎的窗口上绘图,而是直接绘制在电脑屏幕上,就像桌面上那些图标一样。我曾翻遍了所有的OpenGL函数,没有哪个函数支持这种做法。我想大概是不行的吧,就把在屏幕上绘图的想法给搁置了。直到有一天,我学习了GDI,尝试进行截屏,当时在想,既然可以读取像素缓冲数据,那么肯定也可以设置像素缓冲,GDI和OpenGL绘图的原理不都是对窗口的像素缓冲进行写操作吗?于是我深入了解GDI、OpenGL、操作系统、窗口之间的关系,终于恍然大悟!OpenGL只提供绘图的方法,但不能创建窗口,创建窗口是操作系统的事。任何可见的界面,都是窗口,包括控制台窗口、应用软件界面、文本框、按钮、菜单栏。。。。当然还有最终极的窗口-----电脑屏幕。既然是窗口,那么他们都有共同的特征,就是都具有像素缓冲区,也就是说,可以进行绘图。在电脑屏幕上使用OpenGL绘图是可行的,关键是如何操作,下面就来说明一下如何在屏幕上绘图。

一、创建OpenGL渲染环境(Render Context)

           要使用OpenGL 绘图,不仅需要有窗口,还需要有渲染环境。电脑屏幕就是窗口,它一直都在那里,因此不需要创建窗口,为窗口创建OpenGL渲染环境才是绘图的关键。在windows系统中,创建渲染环境需要用到几个win API函数,其操作步骤就是:获取窗口设备环境(DC,device context),选择像素格式,设置像素格式,创建渲染环境(RC,render context)。用到的win API和wgl函数如下:

(1)获取窗口设备环境(DC),hWnd是窗口句柄,如果为NULL,则表示获取屏幕的DC。详见MSDN:GetDC

HDC GetDC(HWND hWnd);

(2)为指定的设备环境(DC)选择合适的像素格式,hdc参数是DC句柄,ppfd像素格式描述器。如果找到符合指定DC的像素格式,则返回像非零的素格式索引号,否则返回0。详见MSDN ChoosePixelFormat

int ChoosePixelFormat(HDC  hdc, CONST PIXELFORMATDESCRIPTOR *  ppfd );

像素格式描述器是一个结构体,其定义如下:

/* Pixel format descriptor */
typedef struct tagPIXELFORMATDESCRIPTOR
{
    WORD  nSize;
    WORD  nVersion;
    DWORD dwFlags;
    BYTE  iPixelType;
    BYTE  cColorBits;
    BYTE  cRedBits;
    BYTE  cRedShift;
    BYTE  cGreenBits;
    BYTE  cGreenShift;
    BYTE  cBlueBits;
    BYTE  cBlueShift;
    BYTE  cAlphaBits;
    BYTE  cAlphaShift;
    BYTE  cAccumBits;
    BYTE  cAccumRedBits;
    BYTE  cAccumGreenBits;
    BYTE  cAccumBlueBits;
    BYTE  cAccumAlphaBits;
    BYTE  cDepthBits;
    BYTE  cStencilBits;
    BYTE  cAuxBuffers;
    BYTE  iLayerType;
    BYTE  bReserved;
    DWORD dwLayerMask;
    DWORD dwVisibleMask;
    DWORD dwDamageMask;
} PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, FAR *LPPIXELFORMATDESCRIPTOR;

像素书格式描述器中各成员的意义及取值范围,在网上或者微软的MSDN中都有详细的说明。

(3)为指定的设备环境(DC)设置像素格式。第二个参数iPixelFormat通过ChoosePixelFormat函数获取。详见MSDN:SetPixelFormat

BOOL SetPixelFormat(HDC  hdc,int  iPixelFormat,CONST PIXELFORMATDESCRIPTOR *  ppfd );

(4)创建渲染环境(create render context)。创建OpenGL渲染环境需要用到一个wgl函数,该函数包含在gl\GL.h头文件中。详见MSDN:wglCreateContext

HGLRC wglCreateContext(HDC  hdc);

二、编程实例

            本程序实例是使用VS编写的。考虑到例子很简单,仅仅用到1.1版本的OpenGL函数,这里就不进行OpenGL编程环境配置,只是利用VS自带的OpenGL库。需要引用的头文件有两个,win API需要包含Windows.h,wgl函数和OpenGL函数需要包含gl\GL.h头文件。由于不需要创建窗口,创建工程可以是win32,为了方便,我采用了自己最熟悉的控制台工程。实例代码如下:

#include<Windows.h>
#include<gl\GL.h>

int main()
{
	PIXELFORMATDESCRIPTOR pfd;
	pfd.nSize = 40;
	pfd.nVersion = 1;
    //支持绘制到窗口、支持OPENGL、支持GDI
	pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI;
	pfd.iPixelType = PFD_TYPE_RGBA;
	pfd.cColorBits = 0;
	pfd.cRedBits = 0;
	pfd.cRedShift = 0;
	pfd.cGreenBits = 0;
	pfd.cGreenShift = 0;
	pfd.cBlueBits = 0;
	pfd.cBlueShift = 0;
	pfd.cAlphaBits = 0;
	pfd.cAlphaShift = 0;
	pfd.cAccumBits = 0;
	pfd.cAccumRedBits = 0;
	pfd.cAccumGreenBits = 0;
	pfd.cAccumBlueBits = 0;
	pfd.cAccumAlphaBits = 0;
	pfd.cDepthBits = 0;
	pfd.cStencilBits = 0;
	pfd.cAuxBuffers = 0;
	pfd.iLayerType = PFD_MAIN_PLANE;
	pfd.bReserved = 0;
	pfd.dwLayerMask = 0;
	pfd.dwVisibleMask = 0;
	pfd.dwDamageMask = 0;
	
    //获取屏幕的设备环境
	HDC hdc = GetDC(NULL);
    //选择像素格式
	int pixelFormat = ChoosePixelFormat(hdc, &pfd);
    //设置像素格式
	SetPixelFormat(hdc, pixelFormat, &pfd);
    //创建OpenGL渲染环境
	HGLRC hglrc = wglCreateContext(hdc);
	//为当前线程指定设备环境和渲染环境
	wglMakeCurrent(hdc, hglrc);
	int i = 0;
	while (i<1000)
	{

		i++;
		glViewport(0, 0, 800, 800);
		//glClear(GL_COLOR_BUFFER_BIT);
		glColor3f(1.0f, 0.0f, 0.0f);
		glBegin(GL_TRIANGLES);
		glVertex2f(-0.5f, -0.5f);
		glVertex2f(0.0f, 0.5f);
		glVertex2f(0.5f, -0.5f);
		glEnd();
		glFlush();
	}
	return 0;
}

运行以上代码,可以看到屏幕上显示了一个红色的三角形:

三 需要注意的事项

        1.设置像素格式时,其他的可以采用默认,全部设为0,但这一项一定要对pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_SUPPORT_GDI;要想绘图到屏幕,一定要选支持OpenGL和支持GDI,GDI和双缓冲是不相容的,因此选择了PFD_SUPPORT_GDI,就不能选PFD_DOUBLEBUFFER。换句话说,如果想要绘图在屏幕上,你就不能采用双缓冲。

       2.采用VS自带的OpenGL库时,一定要在项目属性的连接器中增加opengl32.lib附加依赖项,否则编译会出现连接错误“无法解析外部引用"之类的错误。

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shifenglv

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值