opengl离屏渲染(不需要和窗口绑定,仅当作一个可以渲染一张图片的API使用)+ opencv显示
具体过程参考的是这篇BLOG:
http://wiki.woodpecker.org.cn/moin/lilin/swig-glBmpContext
这一片BLOG的代码有个 BOOL SaveBmp(HBITMAP hBitmap, string FileName) 的函数,功能为保存成BMP格式的图片,我的代码中也就省去了这部分,用opencv来处理,这样使得熟悉opencv的人也能比较好了解吧,毕竟Windows的API一些结构体确实看起来比较生涩难懂。
#include <windows.h>
#include <iostream>
#include <gl/gl.h>
#include <gl/glu.h>
#include <string>
#include <time.h> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp> using namespace std;
using namespace cv; void mGLRender()
{
glClearColor(0.9f,0.9f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, 1.0, 1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
glBegin(GL_TRIANGLES);
glColor3d(1, 0, 0);
glVertex3d(0, 1, 0);
glColor3d(0, 1, 0);
glVertex3d(-1, -1, 0);
glColor3d(0, 0, 1);
glVertex3d(1, -1, 0);
glEnd();
glFlush(); // remember to flush GL output!
} void mGLRender1()
{
glClearColor(0.3f,0.3f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, 1.0, 1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
glBegin(GL_TRIANGLES);
glColor3d(1, 0, 0);
glVertex3d(0, 1, 0);
glColor3d(0, 1, 0);
glVertex3d(-1, -1, 0);
glColor3d(0, 0, 1);
glVertex3d(1, -1, 0);
glEnd();
glFlush(); // remember to flush GL output!
} int main(int argc, char* argv[])
{
clock_t clockBegin, clockEnd;
const int WIDTH = 400;
const int HEIGHT = 400; // Create a memory DC compatible with the screen
HDC hdc = CreateCompatibleDC(0);
if (hdc == 0) cout<<"Could not create memory device context"; // Create a bitmap compatible with the DC
// must use CreateDIBSection(), and this means all pixel ops must be synchronised
// using calls to GdiFlush() (see CreateDIBSection() docs)
BITMAPINFO bmi = {
{ sizeof(BITMAPINFOHEADER), WIDTH, HEIGHT, 1, 32, BI_RGB, 0, 0, 0, 0, 0 },
{ 0 }
};
unsigned char *pbits; // pointer to bitmap bits
HBITMAP hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void **) &pbits,
0, 0);
if (hbm == 0) cout<<"Could not create bitmap"; //HDC hdcScreen = GetDC(0);
//HBITMAP hbm = CreateCompatibleBitmap(hdcScreen,WIDTH,HEIGHT); // Select the bitmap into the DC
HGDIOBJ r = SelectObject(hdc, hbm);
if (r == 0) cout<<"Could not select bitmap into DC"; // Choose the pixel format
PIXELFORMATDESCRIPTOR pfd = {
sizeof (PIXELFORMATDESCRIPTOR), // struct size
1, // Version number
PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL, // use OpenGL drawing to BM
PFD_TYPE_RGBA, // RGBA pixel values
32, // color bits
0, 0, 0, // RGB bits shift sizes...
0, 0, 0, // Don't care about them
0, 0, // No alpha buffer info
0, 0, 0, 0, 0, // No accumulation buffer
32, // depth buffer bits
0, // No stencil buffer
0, // No auxiliary buffers
PFD_MAIN_PLANE, // Layer type
0, // Reserved (must be 0)
0, // No layer mask
0, // No visible mask
0, // No damage mask
};
int pfid = ChoosePixelFormat(hdc, &pfd);
if (pfid == 0) cout<<"Pixel format selection failed"; // Set the pixel format
// - must be done *after* the bitmap is selected into DC
BOOL b = SetPixelFormat(hdc, pfid, &pfd);
if (!b) cout<<"Pixel format set failed"; // Create the OpenGL resource context (RC) and make it current to the thread
HGLRC hglrc = wglCreateContext(hdc);
if (hglrc == 0) cout<<"OpenGL resource context creation failed";
wglMakeCurrent(hdc, hglrc); // Draw using GL - remember to sync with GdiFlush()
clockBegin = clock();
GdiFlush();
mGLRender();
//SaveBmp(hbm,"output.bmp");
clockEnd = clock();
printf("%d\n", clockEnd - clockBegin); clockBegin = clock();
GdiFlush();
mGLRender1();
//SaveBmp(hbm,"output1.bmp");
clockEnd = clock();
printf("%d\n", clockEnd - clockBegin);
/*
Examining the bitmap bits (pbits) at this point with a debugger will reveal
that the colored triangle has been drawn.
*/ //opencv show img
Mat img(HEIGHT,WIDTH,CV_8UC4,(void *)pbits);
imshow("img",img);
waitKey();
destroyWindow("img"); // Clean up
wglDeleteContext(hglrc); // Delete RC
SelectObject(hdc, r); // Remove bitmap from DC
DeleteObject(hbm); // Delete bitmap
DeleteDC(hdc); // Delete DC system("pause"); return 0;
}
以上的代码可以直接编译运行,记得加上opengl32.lib和glu32.lib(还有加上opencv的配置,如果不需要的话可以直接注释掉和OpenCV有关的代码,原始代码可以参考文章开头给出的blog)
还有值得注意的是pbits指向的是从图像左下角开始,由下至上的像素点的排列,和opencv的由上至下刚好相反,所以opencv显示的图片是水平镜像的。
简单得说吧,要进行离屏渲染,win32下需要做下面的几个步骤:
1.创建一个内存 DC
2.创建一个位图
3.把位图选入DC
4.设置DC的像元格式
5.通过DC创建OpenGL的渲染上下文RC
6.开始渲染.
其中有个GdiFlush()的函数,其作用是提供一个mutex的机制,给GDI objects提供一个保护机制,因为opengl在执行glFlush()绘制的时候,是可以没有等待绘制完就返回的(可以百度glFlush和glFinish的区别),如果这时候访问了GDI object可能会访问的是一个未完成的结果,或者产生读写冲突。
MSDN的解释是这样的:
An application should call GdiFlush before a thread goes away if there is a possibility that there are pending function calls in the graphics batch queue. The system does not execute such batched functions when a thread goes away.
A multithreaded application that serializes access to GDI objects with a mutex must ensure flushing the GDI batch queue by calling GdiFlush as each thread releases ownership of the GDI object. This prevents collisions of the GDI objects (device contexts, metafiles, and so on).
但是目前为止,还没发现过使用glFlush和glFinish的差异(难道是现在的显卡都太快了,绘制自己写的场景用的时间很短),如果大家有什么见解欢迎讨论哈。
opengl离屏渲染(不需要和窗口绑定,仅当作一个可以渲染一张图片的API使用)+ opencv显示的更多相关文章
- 深度剖析OpenGL ES中的多线程和多窗口渲染技术
由 创新网小编 于 星期五, 2014-04-11 14:56 发表 移动设备中的CPU和GPU已经变得很强大,到处都是配备一个或多个高分辨率屏幕的设备,需要使用带有图形驱动器的复杂交互也日益增加.在 ...
- 基于OpenGL编写一个简易的2D渲染框架-01 创建窗口
最近正在学习OpenGL,我认为学习的最快方法就是做一个小项目了. 如果对OpenGL感兴趣的话,这里推荐一个很好的学习网站 https://learnopengl-cn.github.io/ 我用的 ...
- CSharpGL(35)用ViewPort实现类似3DMax那样的把一个场景渲染到4个视口
CSharpGL(35)用ViewPort实现类似3DMax那样的把一个场景渲染到4个视口 开始 像下面这样的四个视口的功能是很常用的,所以我花了几天时间在CSharpGL中集成了这个功能. 在CSh ...
- CSharpGL(34)以从零编写一个KleinBottle渲染器为例学习如何使用CSharpGL
CSharpGL(34)以从零编写一个KleinBottle渲染器为例学习如何使用CSharpGL +BIT祝威+悄悄在此留下版了个权的信息说: 开始 本文用step by step的方式,讲述如何使 ...
- Python pyQt4/pyQt5 学习笔记1(空白窗口,按钮,控件事件,控件提示,窗体显示到屏幕中间,messagebox)
PyQt4是用来编写有图形界面程序(GUI applications)的一个工具包.PyQt4作为一个Python模块来使用,它有440个类和超过6000种函数和方法.同时它也是一个可以在几乎所有主流 ...
- HashTab---Windows资源管理器的文件属性窗口中添加了一个叫做”文件校验”的标签
HashTab 是一个优秀的 Windows 外壳扩展程序,它在 Windows 资源管理器的文件属性窗口中添加了一个叫做”文件校验”的标签.该标签可以帮助你方便地计算文件的 MD5.SHA1 与 C ...
- WPF中使用WindowChrome美化窗口过程中的一个小问题
WPF中使用WindowChrome美化窗口,在园子里有几篇不错的文章,我也是参考练习过程中发现的问题,并记录下来. 在看过几篇教程后,给出的窗口很多出现这样一个问题,如果设置了窗口标题栏的高度大于默 ...
- ASP.NET#在设计窗口上添加了一个SqlDataSource控件后,没有显示出来?
在设计窗口上添加了一个SqlDataSource控件后,没有显示出来,但后台代码是有的 处理的办法:菜单栏->视图->可视辅助->ASP.NET非可视控件 (我用的是VS2012)
- python调用大漠插件教程03窗口绑定实例
怎样利用注册好的大漠对象来绑定窗口? 直接上代码,根据代码分析 from win32com.client import Dispatch import os from win32gui import ...
随机推荐
- 利用EntityFramework获得双色球数据库
原文 利用EntityFramework获得双色球数据库 双色球想必大家都很熟悉了,尽管屡买屡不中,但还是会买.以前就想过利用双色球的走势图得到双色球的数据库,至于得到数据库干什么倒没想过,不过对以往 ...
- monoTouch for android visual studio c#开发
本人 c# 程序员,第一次配置环境 按照此流程安装 http://www.wuleba.com/18892.html 本次下载的 8 个安装程序,我是安装以上顺序安装的,分别标志为1至8,暂时不 ...
- cocos2d-x plist在拍照
if(!CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("scrollicon_bg.png" ...
- 省钱加油(Fuel Economy)题解
题目 农夫约翰决定去做一个环游国家旅行,为了不让他的奶牛们感到孤单,于是他决定租一辆货车带领他的奶牛们一起去旅行.这辆货车的油箱最多可以承载G 个单位的油,同时为了简化问题,规定每一个单位的油可以行使 ...
- Phpstorm配置phpunit对php进行单元测试
在 phpstorm 中配置 php 项目的单元测试,项目使用 Composer 进行管理,为了避免在项目中直接引入 phpunit 相关代码包,使项目的 vendor 目录变得臃肿,这里采用全局安装 ...
- EA强大的绘图工具---设计数据库表格
关于EA这个优秀的软件是从师哥哪里听来的,自己瞎点了点,感觉也没什么.近期和和智福加上一个师哥合作敲机房收费系统时,想到之前听人说EA非常强大,便随便找了找关于EA使用的帮助手冊.果然惊喜-- 如题, ...
- HDOJ 4416 Good Article Good sentence
题解转自:http://blog.csdn.net/dyx404514/article/details/8807440 2012杭州网络赛的一道题,后缀数组后缀自己主动机都行吧. 题目大意:给一个字符 ...
- [译]Java 设计模式之迭代器
(文章翻译自java-design-pattern-iterator) 迭代器模式用于迭代遍历一个集合对象.它是一个经常被用到的模式,你可能以前使用过它.不管在任何时候你看见一些方法像hasNext( ...
- 使用.net备份和还原数据库
原文:使用.net备份和还原数据库 CSDN网友的提问http://community.csdn.net/Expert/TopicView3.asp?id=4929678C#实现SQLSERVER20 ...
- C语言中的内存管理
开始陆续的发一下唐老师视频的笔记吧,顺便带一些正冲哥书的的内容.不能一下都发出来,因为内容发多了自己也受不了,而且发的都是学习视频时候的一些笔记,可能会有一些问题不是很清晰. 先说一下C语言中的内存管 ...