我有一个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...
答案 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是一个很好的方向。