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 ...
随机推荐
- UVA - 11986 Save from Radiation
Description J Save from Radiation Most of you are aware of Nuclear Power Plant Explosion at Fukushim ...
- android网络操作使用汇总(http)
Android是作为智能手机的操作系统,我们开发的应用,大多数也都须要连接网络,通过网络发送数据.获取数据,因此作为一个应用开发人员必须熟悉怎么进行网络訪问与连接. 通常android中进行网络连接通 ...
- DEDECMS织梦常用二开自定义标签
网站名称:{dede:global.cfg_webname/} 网站根网址:{dede:global.cfg_basehost/} 网站根目录:{dede:global.cfg_cmsurl/} 网页 ...
- installshield 32位打包和64位打包的注意事项
原文:installshield 32位打包和64位打包的注意事项 32/64位问题要把握几点:1. 明确你的产品是否需要区分32/64位2. 明确你的产品中是否有32/64位的服务注册3. 了解In ...
- Linq to Sql : 三种事务处理方式
原文:Linq to Sql : 三种事务处理方式 Linq to SQL支持三种事务处理模型:显式本地事务.显式可分发事务.隐式事务.(from MSDN: 事务 (LINQ to SQL)).M ...
- leetcode第29题--Substring with Concatenation of All Words
problem: You are given a string, S, and a list of words, L, that are all of the same length. Find al ...
- 在ubuntu下开发stm32f4-discovery
前面零散地记录了一些如何安装编译器,调试器等笔记,这里就准备开始着手试一下这整块系统了. 简单不完全地回顾一下所需要安装的软件: 1 编译器 使用的是codesourcey,因为之前有使用过该套编译器 ...
- IE支持CSS3圆角
在CSS中使用CSS插件文件即可让IE6/IE7/IE8浏览器. 具体CSS代码: .yuan { border: 2px solid #C0C0C0; -moz-border-radius: 10p ...
- 使用CountDownLatch和CyclicBarrier处理并发线程
闲话不说,首先看一段代码: { IValueCallback remoteCallback = new IValueCallback.Stub() { <strong><span s ...
- dos下的cd指令
进入同根目录下的目录: 1.进入同根目录的下一级目录:cd 目录名 2.返回同根目录的上一级目录:cd .. 3.返回目录的根目录:cd \ 进入不同根目录下的目录: 1.进入另外一个根目录(的默认目 ...