博主作为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. Windows 7样式地址栏(Address Bar)控件实现

    介绍 从Vista开始,地址栏就有了很大的改变,不知道大家有什么感觉,笔者觉得很方便,同时又兼容之前的功能,是个很不错的创新.不过,微软并不打算把这一很酷的功能提供给广大的开发人员. 本文提供了一个简 ...

  2. UWP 手绘视频创作工具技术分享系列 - Ink & Surface Dial

    本篇作为技术分享系列的第四篇,详细讲一下手绘视频中 Surface Pen 和 Surface Dial 的使用场景. 先放一张微软官方商城的图,Surface 的使用中结合了 Surface Pen ...

  3. Head First设计模式之解释器模式

    一.定义 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子. 主要解决:对于一些固定文法构建一个解释句子的解释器. 何时使用:如果一种特定类型的问题发生的频率足 ...

  4. linux ext4无法使用超过16T磁盘的解决办法

    大磁盘使用问题 问题:当所要挂载的设备大于16T的时候,可以用parted正常分区,但是分区完成之后,无法格式化, 报错:Size of device /dev/sdb1 too big to be ...

  5. [Spark内核] 第38课:BlockManager架构原理、运行流程图和源码解密

    本课主题 BlockManager 运行實例 BlockManager 原理流程图 BlockManager 源码解析 引言 BlockManager 是管理整个Spark运行时的数据读写的,当然也包 ...

  6. java中碰到无法解决的问题:无法访问类的getter访问器

    大牛们来看看,俺这是咋了?因博问不让发图,发到这里求助: 以上两个方法都是从mysql中select数据,为嘛第二个出现辣鸡报错? 请注意: reslist.size() = 289 第二种方法已经获 ...

  7. VSCode好用的Python插件及配置

    MS Python插件. 这是微软官方的Python插件,已经自带很多功能.下面是插件功能描述,其中部分内容我做了翻译. a)        Linting (Prospector, Pylint,  ...

  8. C++返回值优化RVO

    返回值优化,是一种属于编译器的技术,它通过转换源代码和对象的创建来加快源代码的执行速度.RVO = return value optimization. 测试平台:STM32F103VG + Keil ...

  9. js中var,let,const理解

    var变量提升: 解释:在声明a之前输出a,因为a是使用var声明变量得到提升,解释为下句 var a: console.log(a) a = 1; var声明会提到最上面的位置,但是赋值的位置还是当 ...

  10. 使用js对form表单base64加密

    利用js可以对前台数据加密,以防止被恶意获取,以下代码,用base64对数据进行加密,可以在后台进行解密. 引入的js <script type="text/javascript&qu ...