PDA

View Full Version : Rainbow color band and color palettes in OpenGL?



rakeshthp
10-04-2012, 04:41 AM
Hi

How to manage different colour palettes in OpenGL? Basically I want to display a set of 2d points and points must be colored based on the depth value at that particular point. The depth value may range from -ve to +ve say -25m to 3000m. So how do I color these set of points using rainbow colorband?

Thanks

tonyo_au
10-04-2012, 05:17 PM
A point will display with the currently selected colour. So you have to do the mapping in your code to change the currently selected colour prior to rendering the point.

Your logic could look like this


void setColour(float p_height)
{
if (p_Height < 0) glColor3f(1.0f,0.0f,0.0f);
else if (p_Height < 10) glColor3f(0.0f, 1.0f, 0.0f);
else glColor3f(0.0f,0.0f,1.0f);
}

// main code
glBegin(..
setColour(vertex_1_Depth);
glVertex2f(vertex_1_X,vertex_1_Y);
setColour(vertex_2_Depth);
glVertex2f(vertex_2_X,vertex_2Y);
...
glEnd();



The number of colours in your range is up to you.

If you are familar with shaders you could use a 1D texture and look up the colour with a texture lookup. This would be easier then the method above.

rakeshthp
10-04-2012, 10:27 PM
Hi tonyo_au,

Exactly that's the word. Lookup table. I don't want to hard code it every time. The logic you mentioned, I did used once, but for testing and it works fine for small number of points. So if number of points are more, then iterating all points and checking for height is time consuming isn't it? Presently I am working with VBOs. Based on the input array, the range must be automatically selected and the color palette should be used, the one which user selects. I googled up in regards to this, and I got this article (though it is quite old)

http://web.agelid.com/protect/utile/documentation/OpenGL/OpenGL%204%20-%20Color%20Index%20Mode.htm

It suites my requirement. But wondering how to go ahead with this. Any idea or clue?

As far as shaders are concerned, I tried a small example on shaders. I got the compilation error. vertex and fragment gets loaded but do not gets compiled. Is it that my system doesn't support shading programming. I am working with OpenGL 2.0. I am not sure whats going wrong. Any comments on this?

Thanks

rakeshthp
10-09-2012, 12:30 AM
Should I go ahead with color index mode to solve my problem or is there much better way to do it.?

Thanks

mhagain
10-09-2012, 02:19 AM
Color index mode is highly unlikely to be supported well or even hardware accelerated. Could you elaborate some more about what errors you got when you tried shaders? I ask because the classic approach to this would be to encode a palette in a 1D texture and fetch the colour from it in a vertex shader.

rakeshthp
10-11-2012, 02:23 AM
Hi mhagain,

The sample shader program which I tested was having some problem. I got another example which displays an ellipse using shaders. IT works fine. Now I am experimenting on shader programming. Can you direct me towards a material, or link or article which helps me to understand how to encode a palette in a 1D texture and fetch color from it?

Thanks

Regards

rakeshthp
10-12-2012, 01:57 AM
Hi,

How to 1D texture and look up the colour with a texture lookup.??

Thanks

tonyo_au
10-13-2012, 06:08 PM
Sorry to take so long to get back, I got a bit distracted with other things.
Take a look at this on reading textures using shaders
http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php

rakeshthp
10-18-2012, 05:38 AM
Hi,

I went through various links and tried to implement them. The examples mentioned here (http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/texturing.php), also executes well. I went through the teapot example mentioned in The Redbook here (http://fly.cc.fer.hr/~unreal/theredbook/chapter09.html) on the online version. The redbook example when executed seperately works fine. But instead on teapot if I plot some points, it doesn't produce appropriate result. Though this is very old one and doesn't use shaders. After reading some more literature, I was able to write my own shaders(of course with help of other examples)

This is my Vertex Shader

attribute vec3 coord2d;attribute float v_color;
varying vec3 f_color;
uniform sampler1D texture_id;


void main(void) {
gl_Position = vec4(coord2d.x, coord2d.y, 0.0, 1.0);
vec4 col = texture1D(texture_id, v_color);
f_color = vec3(col.x, col.y, col.z);
}

And, this is my fragment shader

varying vec3 f_color;

void main(void) {
gl_FragColor = vec4(f_color.x, f_color.y, f_color.z, 1.0);
}

Required VBO variables

GLint attribute_coord2d, attrib_v_color;GLuint vbo_triangle, vbo_triangle_colors, attr_Utexture_id;


GLfloat *triangle_vertices = NULL;


GLfloat *triangle_colors= NULL;

Here's the code which executes in Init function

virtual void OnInit() {


FILE *fp = fopen("test.pts", "r");
if(!fp){
std::cout << "Unable to open file" << std::endl;
return;
}


char buffer[256];
char str[256];
static const int max = 100;


if(!fgets(buffer, sizeof(buffer), fp)) return;
str[0]='\0';
sscanf(buffer, "%s", str);


// Create system memory buffer
sscanf(buffer, "%d", &nPoints);


triangle_vertices = new GLfloat[nPoints*3];
triangle_colors = new GLfloat[nPoints];


size_t i_ind = 0, v_ind = 0;
float _xval, _yval, _zval;
float min_x, min_y;
float max_x, max_y;

while(i_ind < nPoints)
{
if(!fgets(buffer, sizeof(buffer), fp))
break;


std::cout << (i_ind/nPoints)*100 << "%\r";
sscanf(buffer, "%f%f%f", &_xval, &_yval, &_zval);
if(i_ind == 0)
{
min_x = max_x = _xval;
min_y = max_y = _yval;
}
else
{
if (_xval < min_x)
min_x = _xval;
if (_xval > max_x)
max_x = _xval;
if (_yval < min_y)
min_y = _yval;
if (_yval > max_y)
max_y = _yval;
}
triangle_vertices[v_ind++] = _xval;
triangle_vertices[v_ind++] = _yval;
triangle_vertices[v_ind++] = _zval;


triangle_colors[i_ind++] = _zval;


}
fclose(fp);




glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_FLAT);


shader = SM.loadfromFile("vertexshader.txt","fragmentshader.txt"); // load (and compile, link) from file
if (shader==0)
std::cout << "Error Loading, compiling or linking shader\n";


const char *uniAttr="texture_id";
attr_Utexture_id = shader->GetUniformLocation(uniAttr);
if(attr_Utexture_id == -1)
{
std::cout << "Could not bind texture sampler" << std::endl;
return;
}


/* lookup texture */
glGenTextures(1, &attr_Utexture_id); /* GL_TEXTURE0 */
glBindTexture(GL_TEXTURE_1D,attr_Utexture_id);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glEnable(GL_TEXTURE_1D);
unsigned char colors[3*32];

colors[0] = 255; colors[1] = 0; colors[2] = 0; /* red */
colors[3] = 0; colors[4] = 0; colors[5] = 255; /* green */
//colors[6] = 0; colors[7] = 0; colors[8] = 255; /* blue */



glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 6, 0, GL_RGB, GL_UNSIGNED_BYTE, colors);

glGenBuffers(1, &vbo_triangle);
glBindBuffer(GL_ARRAY_BUFFER, vbo_triangle);
glBufferData(GL_ARRAY_BUFFER, nPoints*3*sizeof(GLfloat), triangle_vertices, GL_STATIC_DRAW);


glGenBuffers(1, &vbo_triangle_colors);
glBindBuffer(GL_ARRAY_BUFFER, vbo_triangle_colors);
glBufferData(GL_ARRAY_BUFFER, nPoints*sizeof(GLfloat), triangle_colors, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

const char* attribute_name="coord2d";
attribute_coord2d = shader->GetAttribLocation(attribute_name);
if(attribute_coord2d == -1){
std::cout << "Could not bind attribute " << attribute_name << std::endl;
return;
}


attribute_name="v_color";
attrib_v_color = shader->GetAttribLocation(attribute_name);
if(attrib_v_color == -1){
std::cout << "Could not bind attribute " << attribute_name << std::endl;
return;
}
}


And display function looks like this

virtual void OnRender(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if (shader) shader->begin();
//glutSolidSphere(1.0,32,32);


glActiveTexture(GL_TEXTURE0 );
glBindTexture(GL_TEXTURE_1D,attr_Utexture_id);
//glEnable(GL_TEXTURE_2D);
//glDisable(GL_TEXTURE_1D);

glEnableVertexAttribArray(attribute_coord2d);
glBindBuffer(GL_ARRAY_BUFFER, vbo_triangle);
glVertexAttribPointer(
attribute_coord2d,
3, GL_FLOAT, GL_FALSE, 0, 0);


glEnableVertexAttribArray(attrib_v_color);
glBindBuffer(GL_ARRAY_BUFFER, vbo_triangle_colors);
glVertexAttribPointer(
attrib_v_color, // attribute
1, // number of elements per vertex, here (r,g,b)
GL_FLOAT, // the type of each element
GL_FALSE, // make our values as-is
0, // no extra data between each position
0 // offset of first element
);


glPointSize(8);
glDrawArrays(GL_POINTS, 0, nPoints);


glDisableVertexAttribArray(attrib_v_color);
glDisableVertexAttribArray(attribute_coord2d);



if (shader) shader->end();


glutSwapBuffers();


//Repaint();
}

So basically what I am doing here is reading set of xyz points and plotting them. Sample xyz points is shown below



13
0.1 0.0 8
0.5 -0.2 25
-0.2 0.4 3346
-0.1 0.3 500
0.4 0.5 3244
0.8 -0.5 3212
0.8 -0.9 60
-0.2 -0.5 3166
-0.3 0.8 -20
-0.6 0.4 -500
0.3 0.8 3173
-0.8 -0.3 2456
0.1 0.7 3214

Which this set up I do get colored points. But, 4 points are of same color and remaining points are of same color. My question here is,

1) Is Texture 1D lookup construction what I have done is correct?
2) If so, then how is the range of colors will be computed? For example, in the above test file, the range is -500 to 3346. This range how should be supplied so that the color map should take place only for values falling within this range.?

I'm sure that I am missing something somewhere. But where I am not able to locate. Some one please help me out.

Thanks

Regards
Rakesh Patil

rakeshthp
10-24-2012, 11:06 PM
Can someone suggest something on this?

Thanks

Dan Bartlett
10-25-2012, 03:35 AM
You should be providing coordinates between 0.0 and 1.0. How you map the values you have (-500 to 3346) to this range is up to you.
If you want to map your range in an increasing linear fashion (lowest value = 0.0, highest value = 1.0, linear mapping between), you could use:


//TexCoord = (Value -(-500))/(3346-(-500));
TexCoord = (Value + 500)/(500+3346)
You could either do this before you pass values into the shaders, or within the shader.

rakeshthp
01-15-2013, 12:57 AM
You should be providing coordinates between 0.0 and 1.0. How you map the values you have (-500 to 3346) to this range is up to you.
If you want to map your range in an increasing linear fashion (lowest value = 0.0, highest value = 1.0, linear mapping between), you could use:


//TexCoord = (Value -(-500))/(3346-(-500));
TexCoord = (Value + 500)/(500+3346)
You could either do this before you pass values into the shaders, or within the shader.

Which one would be the good approach? Mapping values before they are passed into shaders? or within the shaders itself? I feel doing it within the shader is easy.

Thanks