博主作为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[4*nSize]; float* pfOutput=new float[4*nSize]; for (int i=0; i<nSize*4; i++) { pfInput[i]= (float)(i + 1.2345); } //初始化并设置GLFW glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); //创建GLFW窗口 GLFWwindow* window = glfwCreateWindow(3, 2, "LearnOpenGL", nullptr, nullptr); glfwMakeContextCurrent(window); //初始化GLEW //glewExperimental = GL_TRUE; glewInit(); //创建FBO并绑定 GLuint fb; glGenFramebuffersEXT(1, &fb); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); //创建纹理对象并绑定 GLuint tex; glGenTextures(1, &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, 0); //将纹理数据设置为单精度浮点数 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA_FLOAT32_ATI, nWidth, nHeight,0, GL_RGBA, GL_FLOAT, NULL); //将数据传至输入纹理缓存 //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_FLOAT, pfInput); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nWidth, nHeight, GL_RGBA, GL_FLOAT, pfInput); //从输出纹理缓存中读出数据 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadPixels(0,0, nWidth, nHeight, GL_RGBA, GL_FLOAT, pfOutput); //打印并检查结果 bool bCap=true; for (int i=0; i<nSize*4; 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(1, &fb); glDeleteTextures(1, &tex); system("pause"); return 0; }