使用OpenGL为像素指定颜色

时间:2015-08-31 09:31:49

标签: opengl colors pixels

我有一个NxM维度的数组。数据类型为double,其值范围为0.000001到1.0。我想使用OpenGL以NxM像素的颜色显示它们,例如0.0001~0.0005将为红色,0.0005~0.001将为浅红色,如同具有不同范围的图例的图片。

我认为我应该使用纹理来提高效率,但我不太明白如何将数组中的值与纹理匹配。我首先需要定义像传奇一样的纹理吗?数组中的值如何使用纹理中的颜色?

或者我应该首先创建一个颜色查找表并使用glDrawPixels?在这种情况下如何定义颜色表?

按照@Josef Rissling发布的方法,我定义了一个图例,然后每个像素在图例位置获得一个索引。我目前使用glDrawPixels()。我想每个图例位置都包含R,G,B值。我应该如何设置glPixelTransfer和glPixelMap()?我下面粘贴的代码只给我一个黑屏。

GLuint legend_image[1024][3];  // it contains { {0,0,255}, {0,0,254}, ...}

// GL initialization;
glutInit(&c, &argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(width_, height_);
glutCreateWindow("GPU render");
// allocate buffer handle
glGenBuffers(1, &buffer_obj_);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, buffer_obj_);
// allocate GPU memory
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, width_ * height_, NULL, GL_DYNAMIC_DRAW_ARB);
// request a CUDA C name for this buffer
CUDA_CALL(cudaGraphicsGLRegisterBuffer(&res_, buffer_obj_, cudaGraphicsMapFlagsNone));

glPixelTransferi(GL_MAP_COLOR, true);
glPixelMapuiv(GL_PIXEL_MAP_I_TO_I, 1024, legend_image[0]);

glutDisplayFunc(draw_func);
glutIdleFunc(idle_func);
glutMainLoop();

void idle_func()
{
    // cuda kernel to do calculation, and then convert to pixel legend position which is pointed by dev_ptr.
    cudaGraphicsMapResources(1, &res_, 0);
    unsigned int* dev_ptr;
    size_t size;
    cudaGraphicsResourceGetMappedPointer((void**)&dev_ptr, &size, res_);
    cuda_kernel(dev_ptr);
    cudaGraphicsUnmapResources(1, &res_, 0);
    glutPostRedisplay();
}

void draw_func()
{
    glDrawPixels(width_, height_, GL_COLOR_INDEX, GL_UNSIGNED_INT, 0);
    glutSwapBuffers();
}

// some cleanup code...

1 个答案:

答案 0 :(得分:0)

您应该提到您正在使用哪种语言和哪种openGL版本......

效率取决于您用于映射的函数类型,纹理查找并不便宜。特别是如果你没有使用纹理作为数组(比你必须先复制数据)。

但是对于你的映射示例: 您可以创建一个图例纹理(在其中应用非线性颜色空间),它允许您从值范围映射到逐个像素偏移(映射颜色值所在的位置)。一般情况将是伪着色器:

map(value)
{
    pixelStartPosition, pixelEndPosition;
    pixelRange = pixelEndPosition - pixelStartPosition;
    valueNormalizer = 1.0 / (valueMaximum - valueMinimum);
    pixelLegendPosition = pixelStartPosition + pixelRange * ( (value-valueMinimum) * valueNormalizer);
    return pixelLegendPosition;
}

假设你有一个2000像素的图例纹理,范围从0到1999,值为0到1:

pixelStartPosition=0
pixelEndPosition=1999
pixelRange = pixelEndPosition - pixelStartPosition // 1999
valueNormalizer = 1.0 / (valueMaximum - valueMinimum) // 1.0
pixelLegendPosition = pixelStartPosition + pixelRange * ( (value-valueMinimum) * valueNormalizer) 
// 0 + 1999 * ( (value-0) * 1 ) ===> 1999 * value 

如果你需要将数组数据传输到纹理,有几种方法可以做到 - 但这主要取决于你的版本/语言,但glTexImage2D是一个很好的方向。