blob: f7ce121f70254a8ab485a27665ee3e5fca470db1 [file] [log] [blame]
jtgafb833d1999-08-19 00:55:39 +00001/*
2 * Demo of off-screen Mesa rendering
3 *
4 * See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
5 *
6 * If you want to render BIG images you'll probably have to increase
7 * MAX_WIDTH and MAX_HEIGHT in src/config.h.
8 *
9 * This program is in the public domain.
10 *
11 * Brian Paul
12 *
13 * PPM output provided by Joerg Schmalzl.
14 * ASCII PPM output added by Brian Paul.
Karl Schultz17642ed2002-04-05 17:40:20 +000015 *
Brian Paul3ae19052006-07-07 14:12:04 +000016 * Usage: osdemo [filename]
jtgafb833d1999-08-19 00:55:39 +000017 */
18
19
Brian Paul3ae19052006-07-07 14:12:04 +000020#include <math.h>
jtgafb833d1999-08-19 00:55:39 +000021#include <stdio.h>
22#include <stdlib.h>
Brian Paule2374912002-07-12 15:54:19 +000023#include <string.h>
jtgafb833d1999-08-19 00:55:39 +000024#include "GL/osmesa.h"
Brian Paul3ae19052006-07-07 14:12:04 +000025#include "GL/glu.h"
jtgafb833d1999-08-19 00:55:39 +000026
27
Brian Paule02ffc12000-03-06 23:56:21 +000028#define SAVE_TARGA
29
jtgafb833d1999-08-19 00:55:39 +000030#define WIDTH 400
31#define HEIGHT 400
32
jtgafb833d1999-08-19 00:55:39 +000033
Brian Paul3ae19052006-07-07 14:12:04 +000034static void
35Sphere(float radius, int slices, int stacks)
36{
37 GLUquadric *q = gluNewQuadric();
38 gluQuadricNormals(q, GLU_SMOOTH);
39 gluSphere(q, radius, slices, stacks);
40 gluDeleteQuadric(q);
41}
42
43
44static void
45Cone(float base, float height, int slices, int stacks)
46{
47 GLUquadric *q = gluNewQuadric();
48 gluQuadricDrawStyle(q, GLU_FILL);
49 gluQuadricNormals(q, GLU_SMOOTH);
50 gluCylinder(q, base, 0.0, height, slices, stacks);
51 gluDeleteQuadric(q);
52}
53
54
55static void
56Torus(float innerRadius, float outerRadius, int sides, int rings)
57{
58 /* from GLUT... */
59 int i, j;
60 GLfloat theta, phi, theta1;
61 GLfloat cosTheta, sinTheta;
62 GLfloat cosTheta1, sinTheta1;
63 const GLfloat ringDelta = 2.0 * M_PI / rings;
64 const GLfloat sideDelta = 2.0 * M_PI / sides;
65
66 theta = 0.0;
67 cosTheta = 1.0;
68 sinTheta = 0.0;
69 for (i = rings - 1; i >= 0; i--) {
70 theta1 = theta + ringDelta;
71 cosTheta1 = cos(theta1);
72 sinTheta1 = sin(theta1);
73 glBegin(GL_QUAD_STRIP);
74 phi = 0.0;
75 for (j = sides; j >= 0; j--) {
76 GLfloat cosPhi, sinPhi, dist;
77
78 phi += sideDelta;
79 cosPhi = cos(phi);
80 sinPhi = sin(phi);
81 dist = outerRadius + innerRadius * cosPhi;
82
83 glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
84 glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, innerRadius * sinPhi);
85 glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
86 glVertex3f(cosTheta * dist, -sinTheta * dist, innerRadius * sinPhi);
87 }
88 glEnd();
89 theta = theta1;
90 cosTheta = cosTheta1;
91 sinTheta = sinTheta1;
92 }
93}
94
95
96static void
97render_image(void)
jtgafb833d1999-08-19 00:55:39 +000098{
99 GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
100 GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
101 GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
102 GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
103 GLfloat red_mat[] = { 1.0, 0.2, 0.2, 1.0 };
104 GLfloat green_mat[] = { 0.2, 1.0, 0.2, 1.0 };
105 GLfloat blue_mat[] = { 0.2, 0.2, 1.0, 1.0 };
106
107
108 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
109 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
110 glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
111 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
112
113 glEnable(GL_LIGHTING);
114 glEnable(GL_LIGHT0);
115 glEnable(GL_DEPTH_TEST);
116
117 glMatrixMode(GL_PROJECTION);
118 glLoadIdentity();
119 glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
120 glMatrixMode(GL_MODELVIEW);
121
122 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
123
124 glPushMatrix();
125 glRotatef(20.0, 1.0, 0.0, 0.0);
126
127 glPushMatrix();
128 glTranslatef(-0.75, 0.5, 0.0);
129 glRotatef(90.0, 1.0, 0.0, 0.0);
130 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red_mat );
Brian Paul3ae19052006-07-07 14:12:04 +0000131 Torus(0.275, 0.85, 20, 20);
jtgafb833d1999-08-19 00:55:39 +0000132 glPopMatrix();
133
134 glPushMatrix();
135 glTranslatef(-0.75, -0.5, 0.0);
136 glRotatef(270.0, 1.0, 0.0, 0.0);
137 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, green_mat );
Brian Paul3ae19052006-07-07 14:12:04 +0000138 Cone(1.0, 2.0, 16, 1);
jtgafb833d1999-08-19 00:55:39 +0000139 glPopMatrix();
140
141 glPushMatrix();
142 glTranslatef(0.75, 0.0, -1.0);
143 glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue_mat );
Brian Paul3ae19052006-07-07 14:12:04 +0000144 Sphere(1.0, 20, 20);
jtgafb833d1999-08-19 00:55:39 +0000145 glPopMatrix();
146
jtgafb833d1999-08-19 00:55:39 +0000147 glPopMatrix();
Karl Schultz17642ed2002-04-05 17:40:20 +0000148
Brian Paul07841822003-03-03 03:14:25 +0000149 /* This is very important!!!
150 * Make sure buffered commands are finished!!!
151 */
152 glFinish();
jtgafb833d1999-08-19 00:55:39 +0000153}
154
155
Brian Paule2374912002-07-12 15:54:19 +0000156#ifdef SAVE_TARGA
jtgafb833d1999-08-19 00:55:39 +0000157
Brian Paule02ffc12000-03-06 23:56:21 +0000158static void
159write_targa(const char *filename, const GLubyte *buffer, int width, int height)
160{
161 FILE *f = fopen( filename, "w" );
162 if (f) {
163 int i, x, y;
164 const GLubyte *ptr = buffer;
165 printf ("osdemo, writing tga file \n");
166 fputc (0x00, f); /* ID Length, 0 => No ID */
167 fputc (0x00, f); /* Color Map Type, 0 => No color map included */
168 fputc (0x02, f); /* Image Type, 2 => Uncompressed, True-color Image */
169 fputc (0x00, f); /* Next five bytes are about the color map entries */
170 fputc (0x00, f); /* 2 bytes Index, 2 bytes length, 1 byte size */
171 fputc (0x00, f);
172 fputc (0x00, f);
173 fputc (0x00, f);
174 fputc (0x00, f); /* X-origin of Image */
175 fputc (0x00, f);
176 fputc (0x00, f); /* Y-origin of Image */
177 fputc (0x00, f);
178 fputc (WIDTH & 0xff, f); /* Image Width */
179 fputc ((WIDTH>>8) & 0xff, f);
180 fputc (HEIGHT & 0xff, f); /* Image Height */
181 fputc ((HEIGHT>>8) & 0xff, f);
182 fputc (0x18, f); /* Pixel Depth, 0x18 => 24 Bits */
183 fputc (0x20, f); /* Image Descriptor */
184 fclose(f);
185 f = fopen( filename, "ab" ); /* reopen in binary append mode */
186 for (y=height-1; y>=0; y--) {
187 for (x=0; x<width; x++) {
188 i = (y*width + x) * 4;
189 fputc(ptr[i+2], f); /* write blue */
190 fputc(ptr[i+1], f); /* write green */
191 fputc(ptr[i], f); /* write red */
192 }
193 }
194 }
195}
196
Brian Paule2374912002-07-12 15:54:19 +0000197#else
Brian Paule02ffc12000-03-06 23:56:21 +0000198
199static void
200write_ppm(const char *filename, const GLubyte *buffer, int width, int height)
201{
202 const int binary = 0;
203 FILE *f = fopen( filename, "w" );
204 if (f) {
205 int i, x, y;
206 const GLubyte *ptr = buffer;
207 if (binary) {
208 fprintf(f,"P6\n");
209 fprintf(f,"# ppm-file created by osdemo.c\n");
210 fprintf(f,"%i %i\n", width,height);
211 fprintf(f,"255\n");
212 fclose(f);
213 f = fopen( filename, "ab" ); /* reopen in binary append mode */
214 for (y=height-1; y>=0; y--) {
215 for (x=0; x<width; x++) {
216 i = (y*width + x) * 4;
217 fputc(ptr[i], f); /* write red */
218 fputc(ptr[i+1], f); /* write green */
219 fputc(ptr[i+2], f); /* write blue */
220 }
221 }
222 }
223 else {
224 /*ASCII*/
225 int counter = 0;
226 fprintf(f,"P3\n");
227 fprintf(f,"# ascii ppm file created by osdemo.c\n");
228 fprintf(f,"%i %i\n", width, height);
229 fprintf(f,"255\n");
230 for (y=height-1; y>=0; y--) {
231 for (x=0; x<width; x++) {
232 i = (y*width + x) * 4;
233 fprintf(f, " %3d %3d %3d", ptr[i], ptr[i+1], ptr[i+2]);
234 counter++;
235 if (counter % 5 == 0)
236 fprintf(f, "\n");
237 }
238 }
239 }
240 fclose(f);
241 }
242}
243
Brian Paule2374912002-07-12 15:54:19 +0000244#endif
245
Brian Paule02ffc12000-03-06 23:56:21 +0000246
247
Brian Paul3ae19052006-07-07 14:12:04 +0000248int
249main(int argc, char *argv[])
jtgafb833d1999-08-19 00:55:39 +0000250{
Brian Paul46dbaec2000-09-08 16:42:06 +0000251 void *buffer;
Karl Schultz17642ed2002-04-05 17:40:20 +0000252 int i;
253 char *filename = NULL;
Brian Paul46dbaec2000-09-08 16:42:06 +0000254
jtgafb833d1999-08-19 00:55:39 +0000255 /* Create an RGBA-mode context */
Brian Paul46dbaec2000-09-08 16:42:06 +0000256#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
257 /* specify Z, stencil, accum sizes */
Karl Schultz220e77a2001-09-24 15:29:27 +0000258 OSMesaContext ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000259#else
Karl Schultz220e77a2001-09-24 15:29:27 +0000260 OSMesaContext ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
Brian Paul46dbaec2000-09-08 16:42:06 +0000261#endif
262 if (!ctx) {
263 printf("OSMesaCreateContext failed!\n");
264 return 0;
265 }
jtgafb833d1999-08-19 00:55:39 +0000266
Brian Paul3ae19052006-07-07 14:12:04 +0000267 for (i = 1; i < argc; i++) {
268 if (argv[i][0] != '-')
269 filename = argv[i];
Karl Schultz17642ed2002-04-05 17:40:20 +0000270 }
271
jtgafb833d1999-08-19 00:55:39 +0000272 /* Allocate the image buffer */
Brian Paul601ce1d2001-07-13 20:09:18 +0000273 buffer = malloc( WIDTH * HEIGHT * 4 * sizeof(GLubyte) );
Brian Paul46dbaec2000-09-08 16:42:06 +0000274 if (!buffer) {
275 printf("Alloc image buffer failed!\n");
276 return 0;
277 }
jtgafb833d1999-08-19 00:55:39 +0000278
279 /* Bind the buffer to the context and make it current */
Brian Paul601ce1d2001-07-13 20:09:18 +0000280 if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, WIDTH, HEIGHT )) {
281 printf("OSMesaMakeCurrent failed!\n");
282 return 0;
283 }
284
jtgafb833d1999-08-19 00:55:39 +0000285
Brian Paul46dbaec2000-09-08 16:42:06 +0000286 {
287 int z, s, a;
288 glGetIntegerv(GL_DEPTH_BITS, &z);
289 glGetIntegerv(GL_STENCIL_BITS, &s);
290 glGetIntegerv(GL_ACCUM_RED_BITS, &a);
Karl Schultz17642ed2002-04-05 17:40:20 +0000291 printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
Brian Paul46dbaec2000-09-08 16:42:06 +0000292 }
293
jtgafb833d1999-08-19 00:55:39 +0000294 render_image();
295
Karl Schultz17642ed2002-04-05 17:40:20 +0000296 if (filename != NULL) {
Brian Paule02ffc12000-03-06 23:56:21 +0000297#ifdef SAVE_TARGA
Karl Schultz17642ed2002-04-05 17:40:20 +0000298 write_targa(filename, buffer, WIDTH, HEIGHT);
Brian Paule02ffc12000-03-06 23:56:21 +0000299#else
Karl Schultz17642ed2002-04-05 17:40:20 +0000300 write_ppm(filename, buffer, WIDTH, HEIGHT);
jtgafb833d1999-08-19 00:55:39 +0000301#endif
jtgafb833d1999-08-19 00:55:39 +0000302 }
303 else {
Brian Paule02ffc12000-03-06 23:56:21 +0000304 printf("Specify a filename if you want to make an image file\n");
jtgafb833d1999-08-19 00:55:39 +0000305 }
306
307 printf("all done\n");
308
309 /* free the image buffer */
310 free( buffer );
311
312 /* destroy the context */
313 OSMesaDestroyContext( ctx );
314
315 return 0;
316}