首页 > 解决方案 > 如何使用 OpenGL 使用自定义调色板重新映射数据

问题描述

假设我有 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();

调色板是用户定义的 RGB 颜色向量;minValmaxVal是data中的最小值和最大值,但可以由用户更改。

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

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

标签: c++opengloptimization

解决方案


您是否测量过花费了多少时间(那么慢在哪里)?

  • 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++;
      }
    

    仍然你的主要问题是之间的转换floatint慢......所以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);
    

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


推荐阅读