1/* 2 * Demo of off-screen Mesa rendering with 32-bit float color channels. 3 * This requires the libOSMesa32.so library. 4 * 5 * Compile with something like this: 6 * 7 * gcc osdemo32.c -I../../include -L../../lib -lglut -lGLU -lOSMesa32 -lm -o osdemo32 8 */ 9 10 11#include <stdio.h> 12#include <stdlib.h> 13#include "GL/osmesa.h" 14#include "glut_wrap.h" 15 16 17#define SAVE_TARGA 18 19 20#define WIDTH 400 21#define HEIGHT 400 22 23 24 25static void render_image( void ) 26{ 27 GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 }; 28 GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; 29 GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; 30 GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; 31 GLfloat red_mat[] = { 1.0, 0.2, 0.2, 1.0 }; 32 GLfloat green_mat[] = { 0.2, 1.0, 0.2, 0.5 }; 33 GLfloat blue_mat[] = { 0.2, 0.2, 1.0, 1.0 }; 34 GLfloat white_mat[] = { 1.0, 1.0, 1.0, 1.0 }; 35 GLfloat purple_mat[] = { 1.0, 0.2, 1.0, 1.0 }; 36 GLUquadricObj *qobj = gluNewQuadric(); 37 38 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); 39 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); 40 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); 41 glLightfv(GL_LIGHT0, GL_POSITION, light_position); 42 43 glEnable(GL_LIGHTING); 44 glEnable(GL_LIGHT0); 45 glEnable(GL_DEPTH_TEST); 46 47 glMatrixMode(GL_PROJECTION); 48 glLoadIdentity(); 49 glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0); 50 glMatrixMode(GL_MODELVIEW); 51 52 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 53 54 glPushMatrix(); 55 glRotatef(20.0, 1.0, 0.0, 0.0); 56 57 /* red square */ 58 glPushMatrix(); 59 glTranslatef(0.0, -0.5, 0.0); 60 glRotatef(90, 1, 0.5, 0); 61 glScalef(3, 3, 3); 62 glDisable(GL_LIGHTING); 63 glColor4f(1, 0, 0, 0.5); 64 glBegin(GL_POLYGON); 65 glVertex2f(-1, -1); 66 glVertex2f( 1, -1); 67 glVertex2f( 1, 1); 68 glVertex2f(-1, 1); 69 glEnd(); 70 glEnable(GL_LIGHTING); 71 glPopMatrix(); 72 73#if 0 74 /* green square */ 75 glPushMatrix(); 76 glTranslatef(0.0, 0.5, 0.1); 77 glDisable(GL_LIGHTING); 78 glColor3f(0, 1, 0); 79 glBegin(GL_POLYGON); 80 glVertex2f(-1, -1); 81 glVertex2f( 1, -1); 82 glVertex2f( 1, 1); 83 glVertex2f(-1, 1); 84 glEnd(); 85 glEnable(GL_LIGHTING); 86 glPopMatrix(); 87 88 /* blue square */ 89 glPushMatrix(); 90 glTranslatef(0.75, 0.5, 0.3); 91 glDisable(GL_LIGHTING); 92 glColor3f(0, 0, 0.5); 93 glBegin(GL_POLYGON); 94 glVertex2f(-1, -1); 95 glVertex2f( 1, -1); 96 glVertex2f( 1, 1); 97 glVertex2f(-1, 1); 98 glEnd(); 99 glEnable(GL_LIGHTING); 100 glPopMatrix(); 101#endif 102 103 glPushMatrix(); 104 glTranslatef(-0.75, -0.5, 0.0); 105 glRotatef(270.0, 1.0, 0.0, 0.0); 106 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat ); 107 glEnable(GL_BLEND); 108 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 109 gluCylinder(qobj, 1.0, 0.0, 2.0, 16, 1); 110 glDisable(GL_BLEND); 111 glPopMatrix(); 112 113 glPushMatrix(); 114 glTranslatef(0.75, 1.0, 1.0); 115 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat ); 116 gluSphere(qobj, 1.0, 20, 20); 117 glPopMatrix(); 118 119 glPopMatrix(); 120 121 /* This is very important!!! 122 * Make sure buffered commands are finished!!! 123 */ 124 glFinish(); 125 126 gluDeleteQuadric(qobj); 127 128 { 129 GLint r, g, b, a, d; 130 glGetIntegerv(GL_RED_BITS, &r); 131 glGetIntegerv(GL_GREEN_BITS, &g); 132 glGetIntegerv(GL_BLUE_BITS, &b); 133 glGetIntegerv(GL_ALPHA_BITS, &a); 134 glGetIntegerv(GL_DEPTH_BITS, &d); 135 printf("channel sizes: %d %d %d %d\n", r, g, b, a); 136 printf("depth bits %d\n", d); 137 } 138} 139 140 141 142static void 143write_targa(const char *filename, const GLfloat *buffer, int width, int height) 144{ 145 FILE *f = fopen( filename, "w" ); 146 if (f) { 147 int i, x, y; 148 const GLfloat *ptr = buffer; 149 printf ("osdemo, writing tga file \n"); 150 fputc (0x00, f); /* ID Length, 0 => No ID */ 151 fputc (0x00, f); /* Color Map Type, 0 => No color map included */ 152 fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */ 153 fputc (0x00, f); /* Next five bytes are about the color map entries */ 154 fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */ 155 fputc (0x00, f); 156 fputc (0x00, f); 157 fputc (0x00, f); 158 fputc (0x00, f); /* X-origin of Image */ 159 fputc (0x00, f); 160 fputc (0x00, f); /* Y-origin of Image */ 161 fputc (0x00, f); 162 fputc (WIDTH & 0xff, f); /* Image Width */ 163 fputc ((WIDTH>>8) & 0xff, f); 164 fputc (HEIGHT & 0xff, f); /* Image Height */ 165 fputc ((HEIGHT>>8) & 0xff, f); 166 fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */ 167 fputc (0x20, f); /* Image Descriptor */ 168 fclose(f); 169 f = fopen( filename, "ab" ); /* reopen in binary append mode */ 170 for (y=height-1; y>=0; y--) { 171 for (x=0; x<width; x++) { 172 int r, g, b; 173 i = (y*width + x) * 4; 174 r = (int) (ptr[i+0] * 255.0); 175 g = (int) (ptr[i+1] * 255.0); 176 b = (int) (ptr[i+2] * 255.0); 177 if (r > 255) r = 255; 178 if (g > 255) g = 255; 179 if (b > 255) b = 255; 180 fputc(b, f); /* write blue */ 181 fputc(g, f); /* write green */ 182 fputc(r, f); /* write red */ 183 } 184 } 185 } 186} 187 188 189static void 190write_ppm(const char *filename, const GLfloat *buffer, int width, int height) 191{ 192 const int binary = 0; 193 FILE *f = fopen( filename, "w" ); 194 if (f) { 195 int i, x, y; 196 const GLfloat *ptr = buffer; 197 if (binary) { 198 fprintf(f,"P6\n"); 199 fprintf(f,"# ppm-file created by osdemo.c\n"); 200 fprintf(f,"%i %i\n", width,height); 201 fprintf(f,"255\n"); 202 fclose(f); 203 f = fopen( filename, "ab" ); /* reopen in binary append mode */ 204 for (y=height-1; y>=0; y--) { 205 for (x=0; x<width; x++) { 206 int r, g, b; 207 i = (y*width + x) * 4; 208 r = (int) (ptr[i+0] * 255.0); 209 g = (int) (ptr[i+1] * 255.0); 210 b = (int) (ptr[i+2] * 255.0); 211 if (r > 255) r = 255; 212 if (g > 255) g = 255; 213 if (b > 255) b = 255; 214 fputc(r, f); /* write red */ 215 fputc(g, f); /* write green */ 216 fputc(b, f); /* write blue */ 217 } 218 } 219 } 220 else { 221 /*ASCII*/ 222 int counter = 0; 223 fprintf(f,"P3\n"); 224 fprintf(f,"# ascii ppm file created by osdemo.c\n"); 225 fprintf(f,"%i %i\n", width, height); 226 fprintf(f,"255\n"); 227 for (y=height-1; y>=0; y--) { 228 for (x=0; x<width; x++) { 229 int r, g, b; 230 i = (y*width + x) * 4; 231 r = (int) (ptr[i+0] * 255.0); 232 g = (int) (ptr[i+1] * 255.0); 233 b = (int) (ptr[i+2] * 255.0); 234 if (r > 255) r = 255; 235 if (g > 255) g = 255; 236 if (b > 255) b = 255; 237 fprintf(f, " %3d %3d %3d", r, g, b); 238 counter++; 239 if (counter % 5 == 0) 240 fprintf(f, "\n"); 241 } 242 } 243 } 244 fclose(f); 245 } 246} 247 248 249 250int main( int argc, char *argv[] ) 251{ 252 GLfloat *buffer; 253 254 /* Create an RGBA-mode context */ 255#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 256 /* specify Z, stencil, accum sizes */ 257 OSMesaContext ctx = OSMesaCreateContextExt( GL_RGBA, 32, 0, 0, NULL ); 258#else 259 OSMesaContext ctx = OSMesaCreateContext( GL_RGBA, NULL ); 260#endif 261 if (!ctx) { 262 printf("OSMesaCreateContext failed!\n"); 263 return 0; 264 } 265 266 /* Allocate the image buffer */ 267 buffer = (GLfloat *) malloc( WIDTH * HEIGHT * 4 * sizeof(GLfloat)); 268 if (!buffer) { 269 printf("Alloc image buffer failed!\n"); 270 return 0; 271 } 272 273 /* Bind the buffer to the context and make it current */ 274 if (!OSMesaMakeCurrent( ctx, buffer, GL_FLOAT, WIDTH, HEIGHT )) { 275 printf("OSMesaMakeCurrent failed!\n"); 276 return 0; 277 } 278 279 render_image(); 280 281 if (argc>1) { 282#ifdef SAVE_TARGA 283 write_targa(argv[1], buffer, WIDTH, HEIGHT); 284#else 285 write_ppm(argv[1], buffer, WIDTH, HEIGHT); 286#endif 287 } 288 else { 289 printf("Specify a filename if you want to make an image file\n"); 290 } 291 292 printf("all done\n"); 293 294 /* free the image buffer */ 295 free( buffer ); 296 297 /* destroy the context */ 298 OSMesaDestroyContext( ctx ); 299 300 return 0; 301} 302