博主作为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. Gradle、Gradle Wrapper与Android Plugin for Gradle

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  2. Android开发之漫漫长途 X——Android序列化

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  3. Git-分布式版本控制系统(二)

    工作区(Woring directory ) 版本区(repository,即隐藏的.git文件) Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git ...

  4. 七牛php-sdk使用

    使用七牛云存储服务有一年多了,大部分功能基于其PHP-SDK来做开发,现对sdk的一些功能做一个总结. 一.资源上传 上传资源文件到七牛空间的不同实现方法 二.文档转换 介绍如何使用七牛以及七牛第三方 ...

  5. js设计模式之惰性单例模式

    <html> <body> <button id="loginBtn">登录</button> </body> < ...

  6. Open Judge 2750 鸡兔同笼

    2750:鸡兔同笼                                                                                            ...

  7. codechef [snackdown2017 Onsite Final] Fusing Weapons

    传送门 题目描述 大厨最近迷上了一款勇者斗恶龙的游戏. 游戏每局开始前,会有 N 件武器摆成一圈.每件武器有一个整数的等级.大厨可以选择两件 相邻的等级相同(不妨设同为 A 级)的武器,将它们合成.这 ...

  8. [51nod1425]减减数

    初始给定一个整数n.每次可以对其做一个操作,这个操作是将n减去他其中的某一位.得到新的一个数字n',然后继续操作,直到他变成0为止. 比如24这个例子,24 → 20 → 18 → 10 → 9 → ...

  9. HDU1097-A hard puzzle-快速幂+取模

    快速幂: 代码: kuaisumi(ll a,ll b){      ll ans=;      while(b){          ==){              ans=ans*a;     ...

  10. 南阳理工oj_The Triangle

    The Triangle 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (Figure 1) Figure 1 ...