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

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

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

OpenGL进行简单的通用计算实例

 

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;
}
View Code

相关文章:

  • 2022-12-23
  • 2022-02-01
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-04-28
  • 2021-12-10
猜你喜欢
  • 2021-07-07
  • 2022-12-23
  • 2022-12-23
  • 2021-06-28
  • 2021-12-21
相关资源
相似解决方案