可以使用OpenGL将实值三角形绘制到缓冲区中吗?

时间:2014-05-28 17:44:15

标签: c++ opengl gpu

我需要实现图像重建,其涉及在表示图像中的像素的缓冲区中绘制三角形。为这些三角形分配一些要填充的浮点值。如果绘制三角形使它们重叠,则必须将重叠区域的值相加。

使用OpenGL可以实现这一目标吗?我想利用栅格化三角形是一个可以在显卡上加速的基本图形任务这一事实。我已经有了这个算法的仅cpu实现,但是对于我的目的来说它还不够快。这是由于需要绘制大量三角形。

具体来说,我的问题是:

  1. 我可以使用openGL绘制具有实际值的三角形吗? (或者我可以想出一个使用颜色等的黑客?)
  2. OpenGL可以添加三角形重叠的值吗? (再次,我可以处理黑客,如混色)
  3. 我可以将像素的实际值恢复为浮点数或类似的数组以进一步处理吗?
  4. 我是否对使用OpenGL绘图的想法有误解 - >使用GPU绘制 - >可能会更快执行?
  5. 此外,我想在虚拟机上运行此代码,因此,据我所知,加速使用OpenGL比在Cuda中使用Cuda这样的实现更可行。这是真的吗?

    编辑:累积缓冲区是一个选项吗?

2 个答案:

答案 0 :(得分:8)

  1. 如果32位浮点数足够,那么答案是肯定的:http://www.opengl.org/wiki/Image_Format#Required_formats
  2. 即使在旧的固定管道下,您也可以使用功能GL_FUNC_ADD的混合模式,但我确信片段着色器现在可以更轻松地完成。
  3. glReadPixels()将在绘制后将数据从缓冲区中取回。
  4. 有OpenGL的软件实现,但您可以在设置上下文时进行选择。使用GPU应该比CPU快得多。
  5. 不知道。我从来没有在VM上使用过OpenGL或CUDA。我从来没有使用过CUDA。

答案 1 :(得分:2)

我认为提供一些代码作为答案并不合适,因为您的问题非常广泛。所以我只是简单地用一些提示回答你的问题。

  1. 是的,使用openGL绘制三角形是件小事。每个三角形提供3个顶点,使用适当的着色器,您可以绘制三角形,填充或只是边缘,无论您想要什么。你似乎需要一个大的集合(大于[0,255]),因为很多三角形可能重叠,并且每个的值可能大于1。这不是问题。您可以填充32位精度单通道帧缓冲​​区。在您的情况下,只有一个频道就足够了。
  2. 是的,混合在openGL上永远存在。因此,无论您选择使用哪种版本的openGL,都会有一种方法可以将trianlges的值重叠起来。
  3. 是的,根据您的实施情况,您可能需要使用glGetSubData()glReadPixels或其他内容。但是,根据您要填充的矩阵的大小,下载完整缓冲区可能有点长(32位的一个通道的2000x1000像素大约为4-5ms)。在GPU上进行所有处理并仅提取少量有价值的信息而不是继续在CPU上进行处理可能更有效。
  4. 毫无疑问,执行速度会更快。但是,从GPU内存下载数据通常不会优化(上传)。因此,下载时可能会丢失您在处理上获胜的时间。我从来没有在VM上使用openGL,所以我不知道额外的性能损失。

  5. //Struct definition
    struct Triangle {
        float[2] position;
        float intensity;
    };
    
    //Init
    glGenBuffers(1, &m_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, 0, m_buffer);
    glBufferData(GL_ARRAY_BUFFER, 
        triangleVector.data() * sizeof(Triangle), 
        triangleVector.size(), 
        GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_ARRAY_BUFFER, 0, 0);
    
    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);
    glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
    glVertexAttribPointer(
        POSITION, 
        2, 
        GL_FLOAT, 
        GL_FALSE, 
        sizeof(Triangle), 
        0);
    glVertexAttribPointer(
        INTENSITY, 
        1, 
        GL_FLOAT, 
        GL_FALSE, 
        sizeof(Triangle), 
        sizeof(float)*2);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
    
    glGenTextures(1, &m_texture);
    glBindTexture(GL_TEXTURE_2D, m_texture);
    glTexImage2D(
        GL_TEXTURE_2D,
        0,
        GL_R32F,
        width,
        height,
        0,
        GL_RED,
        GL_FLOAT,
        NULL);
    glBindTexture(GL_FRAMEBUFFER, 0);
    
    glGenFrameBuffers(1, &m_frameBuffer);
    glBindFrameBuffer(GL_FRAMEBUFFER, m_frameBuffer);
    glFramebufferTexture(
        GL_FRAMEBUFFER,
        GL_COLOR_ATTACHMENT0,
        m_texture,
        0);
    glBindFrameBuffer(GL_FRAMEBUFFER, 0);
    

    您只需要编写渲染功能。一个简单的glDraw*()就足够了。只需记住正确绑定缓冲区即可。使用适当的功能进行混合。您可能还想为您的案例禁用抗锯齿。起初我说你需要一个正射投影,但我没有你问题的所有元素,所以它取决于你。

    长话短说,如果你从未使用过openGL,那么只有在你阅读了一些关于openGL / GLSL的文档/教程后,上面的代码才会有用。