博主作为OpenGL新手,最近要用OpenGL进行并行的数据计算,突然发现这样的资料还是很少的,大部分资料和参考书都是讲用OpenGL进行渲染的。好不容易找到一本书《GPGPU编程技术,从OpenGL、CUDA到OpenCL》,里面对并行处理的发展进行了系统性的介绍,还是很不错的。小白博主很兴奋,看完书中第三章后恍然大悟了很多,就贴出书中代码3-3的例子,实现一番,并用一副图片数据做了实现。

实现环境:Window7 32bit, VS2013+OpenGL3.3+GLEW+GLFW。

OpenGL用来进行通用数据计算的流程如下图,数据从CPU(应用程序)中通过“用绘制来调用”发送到纹理缓存,以纹理映射的方式给到着色器,最后经过片段着色器的计算(GLSL语言)后,再将结果输出到纹理缓存,最后CPU(应用程序)再从纹理缓存中读取结果数据,至此计算完成。

1.书中代码3-3输入一组数据到纹理缓存,然后再从纹理缓存中读取这组数据,代码以及实验结果如下:

数据类型就设置为float,将数据发送至纹理缓存要用这个函数glTexSubImage2D( );

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
using namespace std;
#define WIDTH 2
#define HEIGHT 3
int main(int argc, char** argv)
{
int nWidth=(int)WIDTH;
int nHeight=(int)HEIGHT;
int nSize=(int)nWidth*nHeight; //创建输入数据
float* pfInput=new float[*nSize];
float* pfOutput=new float[*nSize];
for (int i=; i<nSize*; i++)
{
pfInput[i]= (float)(i + 1.2345);
}
//初始化并设置GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, );
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, );
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//创建GLFW窗口
GLFWwindow* window = glfwCreateWindow(, , "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
//初始化GLEW
//glewExperimental = GL_TRUE;
glewInit(); //创建FBO并绑定
GLuint fb;
glGenFramebuffersEXT(, &fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); //创建纹理对象并绑定
GLuint tex;
glGenTextures(, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
//设置纹理参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); //将纹理关联到FBO
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, ); //将纹理数据设置为单精度浮点数
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA_FLOAT32_ATI, nWidth, nHeight,, GL_RGBA, GL_FLOAT, NULL);
//将数据传至输入纹理缓存
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_FLOAT, pfInput);
glTexSubImage2D(GL_TEXTURE_2D, , , , nWidth, nHeight, GL_RGBA, GL_FLOAT, pfInput); //从输出纹理缓存中读出数据
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glReadPixels(,, nWidth, nHeight, GL_RGBA, GL_FLOAT, pfOutput); //打印并检查结果
bool bCap=true;
for (int i=; i<nSize*; i++)
{
cout<<i<<":\t"<<pfInput[i]<<'\t'<<pfOutput[i]<<endl;
if (pfInput[i]!=pfOutput[i]) bCap=false;
} if (bCap) cout<<"Round trip complete!"<<endl;
else cout<<"Round trip failed!" <<endl; delete pfInput;
delete pfOutput;
glDeleteFramebuffers(, &fb);
glDeleteTextures(, &tex); system("pause"); return ;
}

2.读取一幅图像,写入纹理缓存并从纹理缓存读出,配合OpenCV使用。代码如下(原理差不多):

 #include <iostream>
#include <stdlib.h>
#include <stdio.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <opencv.hpp>
using namespace std;
using namespace cv;
#define WIDTH 2
#define HEIGHT 3
int main(int argc, char** argv)
{
//读取图像
Mat srcImg=imread("./lena.jpg");
Mat dstImg=Mat::zeros(srcImg.size(), srcImg.type()); int nWidth=srcImg.cols;
int nHeight=srcImg.rows;
int nSize=(int)nWidth*nHeight; //BGR转换到RGB空间
cvtColor(srcImg, srcImg, CV_BGR2RGB);
cvtColor(dstImg, dstImg, CV_BGR2RGB); //获取图像数据指针
uchar* puInput=srcImg.data;
uchar* puOutput=dstImg.data; //初始化并设置GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, );
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, );
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
//创建GLFW窗口
GLFWwindow* window = glfwCreateWindow(, , "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
//初始化GLEW
glewExperimental = GL_TRUE;
glewInit(); //创建FBO并绑定
GLuint fb;
glGenFramebuffersEXT(, &fb);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); //创建纹理对象并绑定
GLuint tex;
glGenTextures(, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
//设置纹理参数
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//将纹理关联到FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, ); //将数据传至输入纹理缓存
glTexImage2D(GL_TEXTURE_2D, , GL_RGB, nWidth, nHeight, , GL_RGB, GL_UNSIGNED_BYTE, puInput); //从输出纹理缓存中读出数据
glReadPixels(,, nWidth, nHeight, GL_RGB, GL_UNSIGNED_BYTE, puOutput); //保存输出图像
imwrite("./LenaIsBack.jpg", dstImg); glDeleteFramebuffers(, &fb);
glDeleteTextures(, &tex); system("pause"); return ;
}

数据类型要设置为unsigned_byte,将数据送至纹理缓存要用这个函数glTexImage2D();最终保存出来的结果我没有再转换到BGR空间,所以输入的Lena和输出的Lena将会下面这样(仅供参考,哈哈)~:

        

其实最好设置两个纹理缓存对象,一个用于输入,一个用于输出,把输出的纹理缓存绑定的FBO(帧缓冲对象)。用GLSL语言在着色器中写出需要进行计算的算法就可以实现通用数据的处理了。对了,渲染的窗口还是要建立的,这样OpenGL以为它是在进行渲染到屏幕的操作,其实我们通过帧缓冲和纹理缓冲实现的是通用数据计算的过程。

今天就到这里,我继续去看书了,每天进步一点点点点。

OpenGL进行简单的通用计算实例的更多相关文章

  1. 审核流(3)低调奢华,简单不凡,实例演示-SNF.WorkFlow--SNF快速开发平台3.1

    下面我们就从什么都没有,结合审核流进行演示实例.从无到有如何快速完美的实现,然而如此简单.低调而奢华,简单而不凡. 从只有数据表通过SNF.CodeGenerator代码生成器快速生成单据并与审核流进 ...

  2. 初学redux笔记,及一个最简单的redux实例

    categories: 笔记 tags: react redux 前端框架 把初学redux的一些笔记写了下来 分享一个入学redux很合适的demo, 用redux实现计数器 这是从阮一峰老师git ...

  3. HTML与CSS简单页面效果实例

    本篇博客实现一个HTML与CSS简单页面效果实例 index.html <!DOCTYPE html> <html> <head> <meta charset ...

  4. Java Tread多线程(0)一个简单的多线程实例

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39341887 本文演示,一个简单的多线程实例,并简单分析一下线程. 编程多 ...

  5. 使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(三)(错误整理篇)

    使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(一) 使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(二) 以上两篇已经把流 ...

  6. 使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(二)(代码篇)

    这篇是上一篇的延续: 用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(一) 源代码在github上可以下载,地址:https://github.com/guoxia ...

  7. 使用ssm(spring+springMVC+mybatis)创建一个简单的查询实例(一)

    梳理下使用spring+springMVC+mybatis 整合后的一个简单实例:输入用户的 ID,之后显示用户的信息(此次由于篇幅问题,会分几次进行说明,此次是工程的创建,逆向生成文件以及这个简单查 ...

  8. 使用JAVA实现的一个简单IOC注入实例

    https://blog.csdn.net/echoshinian100/article/details/77977823 欲登高而望远,勿筑台于流沙 RSS订阅 原 使用JAVA实现的一个简单IOC ...

  9. Qt5.9一个简单的多线程实例(类QThread)(第一种方法)

    Qt开启多线程,主要用到类QThread.有两种方法,第一种用一个类继承QThread,然后重新改写虚函数run().当要开启新线程时,只需要实例该类,然后调用函数start(),就可以开启一条多线程 ...

随机推荐

  1. S2 深入.NET和C#编程 一: 深入C#.NET框架

    深入C#.NET框架 1..NET框架 之一   推荐一个代码管理平台,博客发布平台 git   之前的复习:   学习的网站: git   github.com 2.类和对象的关系  Dept de ...

  2. NPOI 1.2 教程

    NPOI 1.2 教程官方地址 很多人可能对NPOI还很陌生,别担心,通过本教程你将对NPOI有进一步的认识和理解. 目录 1. 认识NPOI 2. 使用NPOI生成xls文件 2.1 创建基本内容 ...

  3. volatile关键字是如何起作用的?

    关键字volatile是Java虚拟机提供的最轻量级的同步机制,但是在平时的项目里面,遇到需要多线程的时候更多地使用的是synchronized关键字来进行同步.个人而言,更多的原因是对volatil ...

  4. Netty对WebSocket的支持(五)

    Netty对WebSocket的支持(五) 一.WebSocket简介 在Http1.0和Http1.1协议中,我们要实现服务端主动的发送消息到网页或者APP上,是比较困难的,尤其是现在IM(即时通信 ...

  5. 【原创】Android AOP面向切面编程AspectJ

    一.背景: 在项目开发中,对 App 客户端重构后,发现用于统计用户行为的友盟统计代码和用户行为日志记录代码分散在各业务模块中,比如在视频模块,要想实现对用户对监控点的实时预览和远程回放行为进行统计, ...

  6. linux apache虚拟主机配置(基于ip,端口,域名)

    配置环境: linux版本:Centos6.4 httpd版本: [root@centos64Study init.d]# pwd/etc/init.d[root@centos64Study init ...

  7. Anaconda使用

    转自PeterYuan   序 Python易用,但用好却不易,其中比较头疼的就是包管理和Python不同版本的问题,特别是当你使用Windows的时候.为了解决这些问题,有不少发行版的Python, ...

  8. JAVA读取和写入properties文件

    1.读取 Properties prop = new Properties(); try { //这个getResourceAsStream方法就是把文件转为inputStream的方式 prop.l ...

  9. JavaScript(三) 数据类型

    数据类型 5+1种数据类型 5种 基础数据类型 Number String boolean null undefined 1种 复杂数据类型 object typeof 操作符   typeof 操作 ...

  10. Jenkins-Dingding Notification Plugin 配置

    具体内容请移步Jenkins官网或作者Github,本文仅为实践分享,记录几个小坑! 感谢插件作者的贡献! 转载注明出处:http://www.cnblogs.com/ityoung/p/648915 ...