Color Table Effects on the SGI 230,330 and 550 Visual Workstations. By Jaya Kanajan, SGI H1. Introduction: A question often asked by technical computing customers is whether or not the V[R]3..7 graphics subsystems shipping with the 230,330,550 supports colortable functionality. The answer is yes, it does. However, it is syntactically and somewhat functionally different from traditional MIPS/IRIX graphics subsystems. Those differences require more detailed an explanation that's not within the scope of this article. Most of the questions that I received as feedback from previous articles related to this was simply for an example of how to achieve color table effects on the 230, 330, and 550 Visual Workstations. H1. Details I felt the best way for me to describe the use of the colortable extension was to give a full example. In the following example, I render the first 32 view plane aligned slices of a data set consisting of a 64x64x64 sampling of a jet shock wave. This is achieved by binding the 64x64x32 data as a 128k texture of size 64x2048 (max texture size is 2kx2k). I only render 32 slices to make things very simple. ( To better optimize performance, one should benchmark texture bind time versus texture size and also consider texsubimage time.) In this particular case, the data is intensity only so I match intensity to alpha value. I use the intensity value as a lookup into a 256x4 RGBA colortable. I set the example up such that one can use the lookup table to highlight certain ranges of intensity. In this case, the mouse buttons allow one to narrow and reset the range of nonzero outputs from the lookup table. The middle mouse button is then used to trigger the update of the color table. Note, only the geometry needs to be resent to the pipe. H1. Conclusion The colortable extension is very useful for many different purposes. It is essential to enable useful visualization of data. Examples of this need can be found in any industry that requires 3 dimensional data visualization. The level of functionality currently offered by the 230, 330, and 550 Visual Workstations with V[R]3..7 graphics should help match provide solutions to many of those needs. H1. Example Application I tested this on a 550 running ProPack 1.3-VW with VR7 graphics. 3dtexwith2d.c =============================================================================== /* * jaya@sgi.com * show use of paletted texture to show colortable behavior * i show how one can highlight particular data values in * a data set using this method * the data is 64x64x64 but i want to keep things very simple so i'll * just use the first 32 slices */ #include #include #include #include #include #include #include GLuint h=300,w=300,x=0,y=0; #define width 64 #define height 64 #define depth 64 static GLubyte *image; static GLubyte colortable[256][4]; static GLuint texName; static GLuint tablebottom=0,tabletop=256; static int alreadydownloaded=0; void display(void) { double inverse = (double) 1/32; double tmpdown,tmpup; int i=0; glClearColor(0,0,0,0); if (alreadydownloaded == 0) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, &texName); glBindTexture(GL_TEXTURE_2D, texName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, width, height*32, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image); glColorTableEXT(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, colortable); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); glEnable(GL_ALPHA_TEST); glDisable(GL_DEPTH_TEST); glAlphaFunc(GL_GREATER,0.01); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); } alreadydownloaded++; glClear(GL_COLOR_BUFFER_BIT); for (i=1; i <= 32; i++) { tmpdown = ( (double) 1 - (double) i*inverse ); tmpup = ( (double) 1 - (double) (i - 1) *inverse ); glBegin(GL_QUADS); glTexCoord2f((float) 0,(float) ( tmpdown ) ) ; glVertex2f(0,0); glTexCoord2f((float) 0,(float) ( tmpup ) ); glVertex2f(0,1); glTexCoord2f((float) 1,(float) ( tmpup ) ); glVertex2f(1,1); glTexCoord2f((float) 1,(float) ( tmpdown ) ); glVertex2f(1,0); glEnd(); glFinish(); glutSwapBuffers(); } glFinish(); glutSwapBuffers(); } void reshape(int w, int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1,0,1,-1,+1); } void keyboard(unsigned char key, int x, int y) { switch(key) { case 27: case 'q': exit(0); case 'r': tabletop=256;tablebottom=0; break; } } void mousehandler(int button, int state, int x, int y) { int j=0; switch(button) { case GLUT_LEFT_BUTTON: tablebottom++; fprintf(stderr,"bottom: %d top %d\n",tablebottom,tabletop); break; case GLUT_RIGHT_BUTTON: tabletop--; fprintf(stderr,"bottom: %d top %d\n",tablebottom,tabletop); break; case GLUT_MIDDLE_BUTTON: for (j=0; j<256;j++) { if ( (j > tablebottom) && (j < tabletop) ) { colortable[j][0] = j; colortable[j][3] = j; } else { colortable[j][0] = 0; colortable[j][3] = 0; } } glColorTableEXT(GL_TEXTURE_2D, GL_RGBA, 256, GL_RGBA, GL_UNSIGNED_BYTE, colortable); fprintf(stderr,"bottom: %d top %d\n",tablebottom,tabletop); glutPostRedisplay(); break; } } int main(int argc, char **argv) { int voxw=64,voxh=64,voxd=64,fd,result,i; image = (GLubyte *) malloc ( (voxw*voxh*voxd) * sizeof(unsigned char)); fd = open("jetshockwave.bin", O_RDONLY); result = read(fd,image,voxw*voxh*voxd); close(fd); for(i=0;i<256;i++) { colortable[i][0] = i; colortable[i][1] = 0; colortable[i][2] = 0; colortable[i][3] = i; } glutInitWindowSize(w, h); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutCreateWindow(argv[0]); glutReshapeFunc(reshape); glutDisplayFunc(display); glutKeyboardFunc(keyboard); glutMouseFunc(mousehandler); glutMainLoop(); return 0; }