【问题标题】:How to remap data using a custom palette using OpenGL如何使用 OpenGL 使用自定义调色板重新映射数据
【发布时间】:2020-12-13 01:09:23
【问题描述】:

假设我有 640x256 的数据矩阵,其中每个元素都是 -10 到 600 范围内的浮点数。我想在屏幕上显示这个矩阵,每个元素都从 RGB 调色板中分配一个颜色。树莓派上的 OpenGL、C++

我目前在做什么:

    for (unsigned int i = 0; i < frameSize; ++i) { // frameSize = 640x256
        float value = data[i];

        if (value > maxVal) {
            color = palette.back();
        }
        else if (value < minVal) {
            color = palette.front();
        }
        else {
            color = palette[((value - minVal) / (maxVal - minVal)) * (palette.size() - 1)];
        }
        imgData[3 * i] = color.R;
        imgData[3 * i + 1] = color.G;
        imgData[3 * i + 2] = color.B;
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imgData);
    glBegin(GL_QUADS);
    {
        glTexCoord2f(0, 0); glVertex2f(0, 0);
        glTexCoord2f(1, 0); glVertex2f(width, 0);
        glTexCoord2f(1, 1); glVertex2f(width, height);
        glTexCoord2f(0, 1); glVertex2f(0, height);
    }
    glEnd();

palette 是用户自定义的 RGB 颜色向量; minVal 和 maxVal 是 data 中的最小值和最大值,但可以由用户更改。

此代码可以正常工作,但图像在 CPU 上被着色,这对于大型 数据 可能会很慢。是否可以直接将浮点 data 作为纹理传递,并在输出上使用 OpenGL 使用调色板对其进行着色?

我不是在问如何优化 CPU-bounded 循环。我的问题是是否可以在 OpenGL 渲染期间完全删除它并完成它的任务。

【问题讨论】:

  • 此代码工作正常,但图像在 CPU 上着色,这对于大数据可能会很慢。您是否检查过它在实际用例中是否不可接受? (我很难想象在调色板中进行额外的查找是那么昂贵。)先前的优化可能是只为可见部分生成纹理(即确切的显示尺寸)。使用着色器程序,您有更多选择,但从 OpenGL 1.x 切换到 OpenGL 3.x 也是您必须考虑的一项工作。 (我已经做到了。我知道我在说什么。);-)
  • 这是从相机流式传输的图像,并且始终可见。 320x256 @60 Hz 没有问题。但是当分辨率更高时,CPU 使用率会跃升至 100%,并且显示帧速率会降至 fps 以下。当我移除着色循环时,它仍然以超过 40 fps 的速度运行,CPU 使用率降低了 20-30%。
  • 这是一个值得edited in 的附加信息。尽管如此,[-10, 600] 范围内的值对我来说似乎有点令人惊讶。您仍然可以选择使用 OpenGL 3.x 和着色器将工作负载转移到 GPU。你也可以试试是否可以通过转动浮点运算来挤出一点。进入积分补偿。并仅用算术运算替换分支(使用if)。

标签: c++ opengl optimization


【解决方案1】:

你有没有测量过什么花费了多少时间(那么慢在哪里)?

  • GL 上的渲染
  • 在 CPU 和 GPU 之间传输纹理
  • 重新着色

我的赌注是重新着色...这里有一些提示我会改变什么:

  1. 您正在进行 3x 字节访问

     imgData[3 * i    ] = color.R;
     imgData[3 * i + 1] = color.G;
     imgData[3 * i + 2] = color.B;
    

    最好将像素格式对齐到 32 位(假设您的 CPU 是 32 位,具有 32 位内存访问,如果硬件支持,即使 16 位访问速度也会提高两倍以上),而是这样做:

     imgData[i] = color;
    

    其中颜色为 32 位 unsigned int。

  2. 你做了太多“慢”操作

    我没有为 RasberryPi 编写代码,但我怀疑你的 CPU 现在不如 x86/x64 先进,所以+,-,*,/ 和int/float 操作之间很可能仍然存在巨大的性能差异。比如:

    3 * i + 2
    ((value - minVal) / (maxVal - minVal)) * (palette.size() - 1)
    

    可能会很慢,幸运的是它们可以以不同的方式完成,例如:

    unsigned int frameSize3 = frameSize3*3,i;
    float value,dv=float(palette.size()-1)/(maxVal - minVal); 
    for (i=0;i<frameSize3;)
      {
      value = data[i];
           if (value>maxVal) color=palette.back(); // here you got temp is it typo?
      else if (value<minVal) color=palette.front(); // here you got temp is it typo?
      else color = palette[int((value-minVal)*dv)];         
      imgData[i]=color.R; i++;
      imgData[i]=color.G; i++;
      imgData[i]=color.B; i++;
      }
    

    您的主要问题仍然是float 和int 之间的转换很慢......所以data[] 真的是浮点数还是整数? data[i],maxVal,minVal,palette.size() 的值,范围是多少?它们是浮点数还是整数?

  3. 使用 LUT 进行颜色计算

    如果您可以转换为整数(取决于您声称的值的范围 -10...600 可以,但调色板大小和 maxVal,minVal 是多少?)然后:

    color = palette[((value - minVal) / (maxVal - minVal)) * (palette.size() - 1)];
    

    可以这样做:

    color = LUT[value - minVal];
    

    其中LUT[610] 是从调色板中获取的每个值的颜色。您可以在应用启动时或对调色板进行任何更改后预先计算一次,minVal,maxVal。

    LUT[i] = (i*(palette.size()-1)) / (maxVal-minVal);
    

    如果您的输入数据来自相机,请尝试查看它是否可以返回整数数据(甚至是固定格式),这会大大加快速度...

【讨论】:

    【解决方案2】:

    我只是把这个作为答案,因为评论太长了。

    我不认为 OpenGL 是实现您想要完成的目标的方法。使用制服将数据进出着色器并不是那么简单,特别是因为您必须通过从 1.x 迁移到 3.x 来重新学习 OpenGL,正如@Scheff 提到的(尽管我建议从一个有 20 多年历史的图书馆)。

    我建议采用以下方法之一:

    1.使用std::threads 池在 CPU 上并行化: 由于计算是独立的,因此您可以将图像分成多个单独填充的部分。同步会在你身上。 std::async 可能会帮助你。

    2。使用 OpenMP 在 CPU/GPU 上并行化: 使用 OpenMP 相对简单,大多数现代编译器都支持它。从 4.0 版开始,它还可以让您利用 GPU 进行并行计算。

    OpenMP 可能在实现时间和性能提升之间取得了最佳平衡。

    【讨论】:

    • 糟糕,我忘记了 RaspberryPi 部分。
    猜你喜欢
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    • 2015-10-20
    • 1970-01-01
    • 2012-06-21
    • 2013-07-31
    相关资源
    最近更新 更多