博主作为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. spring boot RESTFul API拦截 以及Filter和interceptor 、Aspect区别

    今天学习一下RESTFul api拦截 大概有三种方式 一.通过Filter这个大家很熟悉了吧,这是java规范的一个过滤器,他会拦截请求.在springboot中一般有两种配置方式. 这种过滤器拦截 ...

  2. PHP 微信公众号-创建菜单-配置

    1.服务号 2.基本配置 注意: URL: 确保能访问到你对应的文件 Token:随意设置,但是要与文件里的一致 3.网页授权 注意:填写网站域名 4.更具实际需求创建菜单

  3. [Spark SQL] SparkSession、DataFrame 和 DataSet 练习

    本課主題 DataSet 实战 DataSet 实战 SparkSession 是 SparkSQL 的入口,然后可以基于 sparkSession 来获取或者是读取源数据来生存 DataFrameR ...

  4. HDFS High Availability Using the Quorum Journal Manager

    http://hadoop.apache.org/docs/r2.9.0/hadoop-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithQJM.htm ...

  5. 关于pocsuite的使用

    0x00 前言 pocsuite的用处就不多说了,早些时候也看到黑哥和余弦大佬在微博上说zoomeye 和pocsuite升级了. 结合最近自己在审计cms,也想收集一下其他cms的poc,比如chy ...

  6. (译)Web是如何工作的(2):客户端-服务器模型,以及Web应用程序的结构

    原文地址:https://medium.freecodecamp.org/how-the-web-works-part-ii-client-server-model-the-structure-of- ...

  7. Android系统上如何实现easyconfig(airkiss)

    刚买回来一个智能音箱和博联,需要给音箱和博联配置联网,音箱需要先打开蓝牙,然后在手机app中填写wifi的ssid和密码,通过蓝牙发送到音箱,音箱收到后连接到wifi. 博联就比较奇怪,进入联网模式以 ...

  8. 解决打开png图片黑屏问题(批量还原Xcode优化后的png)

    window 打开Xcode 里面的png图片会黑屏,但是在mac 打开就显示正常, 这是因为Xocde里面的png图片被 pngcrush 优化过了,需要还原它的优化,window 平台才可以打开. ...

  9. 如何在linux下录制terminal操作?

    相关包: ttyrec: ttyrec is a tty recorder. Recorded data can be played back with the included ttyplay co ...

  10. mwValidate.js验证插件

    这段时间在公司一直做项目的同时,也学了下js,感觉有必要做一些什么东西出来.思来想去就做了最简单的一个验证插件.我很清楚这个东西市面上已经很多了,但我的目的也很清楚,检验我的学习成果.所以也就无所谓了 ...