Home | History | Annotate | Line # | Download | only in demos
      1 /*-----------------------------
      2  * stex3d.c GL example of the mesa 3d-texture extention to simulate procedural
      3  *            texturing, it uses a perlin noise and turbulence functions.
      4  *
      5  * Author:   Daniel Barrero
      6  *           barrero (at) irit.fr
      7  *           dbarrero (at) pegasus.uniandes.edu.co
      8  *
      9  * Converted to GLUT by brianp on 1/1/98
     10  * Massive clean-up on 2002/10/23 by brianp
     11  *
     12  *
     13  * cc stex3d.c -o stex3d -lglut -lMesaGLU -lMesaGL -lX11 -lXext -lm
     14  *
     15  *---------------------------- */
     16 
     17 #include <string.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #include <math.h>
     21 #include <GL/glew.h>
     22 #include "glut_wrap.h"
     23 
     24 
     25 #ifndef M_PI
     26 #define M_PI            3.14159265358979323846
     27 #endif
     28 
     29 #define NOISE_TEXTURE 1
     30 #define GRADIENT_TEXTURE 2
     31 
     32 #define TORUS 1
     33 #define SPHERE 2
     34 
     35 static int tex_width=64, tex_height=64, tex_depth=64;
     36 static float angx=0, angy=0, angz=0;
     37 static int texgen = 2, animate = 1, smooth = 1, wireframe = 0;
     38 static int CurTexture = NOISE_TEXTURE, CurObject = TORUS;
     39 static GLenum Filter = GL_LINEAR;
     40 
     41 
     42 static void
     43 BuildTorus(void)
     44 {
     45    GLint i, j;
     46    float theta1, phi1, theta2, phi2, rings, sides;
     47    float v0[03], v1[3], v2[3], v3[3];
     48    float t0[03], t1[3], t2[3], t3[3];
     49    float n0[3], n1[3], n2[3], n3[3];
     50    float innerRadius = 0.25;
     51    float outerRadius = 0.5;
     52    float scalFac;
     53 
     54    rings = 16;
     55    sides = 12;
     56    scalFac = 1 / (outerRadius * 2);
     57 
     58    glNewList(TORUS, GL_COMPILE);
     59    for (i = 0; i < rings; i++) {
     60       theta1 = (float) i *2.0 * M_PI / rings;
     61       theta2 = (float) (i + 1) * 2.0 * M_PI / rings;
     62       for (j = 0; j < sides; j++) {
     63 	 phi1 = (float) j *2.0 * M_PI / sides;
     64 	 phi2 = (float) (j + 1) * 2.0 * M_PI / sides;
     65 
     66 	 v0[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi1));
     67 	 v0[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi1));
     68 	 v0[2] = innerRadius * sin(phi1);
     69 
     70 	 v1[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi1));
     71 	 v1[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi1));
     72 	 v1[2] = innerRadius * sin(phi1);
     73 	 v2[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi2));
     74 	 v2[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi2));
     75 	 v2[2] = innerRadius * sin(phi2);
     76 
     77 	 v3[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi2));
     78 	 v3[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi2));
     79 	 v3[2] = innerRadius * sin(phi2);
     80 
     81 	 n0[0] = cos(theta1) * (cos(phi1));
     82 	 n0[1] = -sin(theta1) * (cos(phi1));
     83 	 n0[2] = sin(phi1);
     84 
     85 	 n1[0] = cos(theta2) * (cos(phi1));
     86 	 n1[1] = -sin(theta2) * (cos(phi1));
     87 	 n1[2] = sin(phi1);
     88 
     89 	 n2[0] = cos(theta2) * (cos(phi2));
     90 	 n2[1] = -sin(theta2) * (cos(phi2));
     91 	 n2[2] = sin(phi2);
     92 
     93 	 n3[0] = cos(theta1) * (cos(phi2));
     94 	 n3[1] = -sin(theta1) * (cos(phi2));
     95 	 n3[2] = sin(phi2);
     96 
     97 	 t0[0] = v0[0] * scalFac + 0.5;
     98 	 t0[1] = v0[1] * scalFac + 0.5;
     99 	 t0[2] = v0[2] * scalFac + 0.5;
    100 
    101 	 t1[0] = v1[0] * scalFac + 0.5;
    102 	 t1[1] = v1[1] * scalFac + 0.5;
    103 	 t1[2] = v1[2] * scalFac + 0.5;
    104 
    105 	 t2[0] = v2[0] * scalFac + 0.5;
    106 	 t2[1] = v2[1] * scalFac + 0.5;
    107 	 t2[2] = v2[2] * scalFac + 0.5;
    108 
    109 	 t3[0] = v3[0] * scalFac + 0.5;
    110 	 t3[1] = v3[1] * scalFac + 0.5;
    111 	 t3[2] = v3[2] * scalFac + 0.5;
    112 
    113 	 glBegin(GL_POLYGON);
    114 	 glNormal3fv(n3);
    115 	 glTexCoord3fv(t3);
    116 	 glVertex3fv(v3);
    117 	 glNormal3fv(n2);
    118 	 glTexCoord3fv(t2);
    119 	 glVertex3fv(v2);
    120 	 glNormal3fv(n1);
    121 	 glTexCoord3fv(t1);
    122 	 glVertex3fv(v1);
    123 	 glNormal3fv(n0);
    124 	 glTexCoord3fv(t0);
    125 	 glVertex3fv(v0);
    126 	 glEnd();
    127       }
    128    }
    129    glEndList();
    130 }
    131 
    132 
    133 /*--------------------------------------------------------------------
    134  noise function over R3 - implemented by a pseudorandom tricubic spline
    135               EXCERPTED FROM SIGGRAPH 92, COURSE 23
    136                         PROCEDURAL MODELING
    137                              Ken Perlin
    138                            New York University
    139 ----------------------------------------------------------------------*/
    140 
    141 
    142 #define DOT(a,b) (a[0] * b[0] + a[1] * b[1] + a[2] * b[2])
    143 #define B 128
    144 static int p[B + B + 2];
    145 static float g[B + B + 2][3];
    146 #define setup(i,b0,b1,r0,r1) \
    147         t = vec[i] + 10000.; \
    148         b0 = ((int)t) & (B-1); \
    149         b1 = (b0+1) & (B-1); \
    150         r0 = t - (int)t; \
    151         r1 = r0 - 1.;
    152 
    153 static float
    154 noise3(float vec[3])
    155 {
    156    int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
    157    float rx0, rx1, ry0, ry1, rz0, rz1, *q, sx, sy, sz, a, b, c, d, t, u, v;
    158    register int i, j;
    159 
    160    setup(0, bx0, bx1, rx0, rx1);
    161    setup(1, by0, by1, ry0, ry1);
    162    setup(2, bz0, bz1, rz0, rz1);
    163 
    164    i = p[bx0];
    165    j = p[bx1];
    166 
    167    b00 = p[i + by0];
    168    b10 = p[j + by0];
    169    b01 = p[i + by1];
    170    b11 = p[j + by1];
    171 
    172 #define at(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
    173 #define surve(t) ( t * t * (3. - 2. * t) )
    174 #define lerp(t, a, b) ( a + t * (b - a) )
    175 
    176    sx = surve(rx0);
    177    sy = surve(ry0);
    178    sz = surve(rz0);
    179 
    180    q = g[b00 + bz0];
    181    u = at(rx0, ry0, rz0);
    182    q = g[b10 + bz0];
    183    v = at(rx1, ry0, rz0);
    184    a = lerp(sx, u, v);
    185 
    186    q = g[b01 + bz0];
    187    u = at(rx0, ry1, rz0);
    188    q = g[b11 + bz0];
    189    v = at(rx1, ry1, rz0);
    190    b = lerp(sx, u, v);
    191 
    192    c = lerp(sy, a, b);		/* interpolate in y at lo x */
    193 
    194    q = g[b00 + bz1];
    195    u = at(rx0, ry0, rz1);
    196    q = g[b10 + bz1];
    197    v = at(rx1, ry0, rz1);
    198    a = lerp(sx, u, v);
    199 
    200    q = g[b01 + bz1];
    201    u = at(rx0, ry1, rz1);
    202    q = g[b11 + bz1];
    203    v = at(rx1, ry1, rz1);
    204    b = lerp(sx, u, v);
    205 
    206    d = lerp(sy, a, b);		/* interpolate in y at hi x */
    207 
    208    return 1.5 * lerp(sz, c, d);	/* interpolate in z */
    209 }
    210 
    211 static void
    212 initNoise(void)
    213 {
    214    /*long random(); */
    215    int i, j, k;
    216    float v[3], s;
    217 
    218    /* Create an array of random gradient vectors uniformly on the unit sphere */
    219    /*srandom(1); */
    220    srand(1);
    221    for (i = 0; i < B; i++) {
    222       do {			/* Choose uniformly in a cube */
    223 	 for (j = 0; j < 3; j++)
    224 	    v[j] = (float) ((rand() % (B + B)) - B) / B;
    225 	 s = DOT(v, v);
    226       } while (s > 1.0);	/* If not in sphere try again */
    227       s = sqrt(s);
    228       for (j = 0; j < 3; j++)	/* Else normalize */
    229 	 g[i][j] = v[j] / s;
    230    }
    231 
    232    /* Create a pseudorandom permutation of [1..B] */
    233    for (i = 0; i < B; i++)
    234       p[i] = i;
    235    for (i = B; i > 0; i -= 2) {
    236       k = p[i];
    237       p[i] = p[j = rand() % B];
    238       p[j] = k;
    239    }
    240 
    241    /* Extend g and p arrays to allow for faster indexing */
    242    for (i = 0; i < B + 2; i++) {
    243       p[B + i] = p[i];
    244       for (j = 0; j < 3; j++)
    245 	 g[B + i][j] = g[i][j];
    246    }
    247 }
    248 
    249 
    250 static float
    251 turbulence(float point[3], float lofreq, float hifreq)
    252 {
    253    float freq, t, p[3];
    254 
    255    p[0] = point[0] + 123.456;
    256    p[1] = point[1];
    257    p[2] = point[2];
    258 
    259    t = 0;
    260    for (freq = lofreq; freq < hifreq; freq *= 2.) {
    261       t += fabs(noise3(p)) / freq;
    262       p[0] *= 2.;
    263       p[1] *= 2.;
    264       p[2] *= 2.;
    265    }
    266    return t - 0.3;		/* readjust to make mean value = 0.0 */
    267 }
    268 
    269 
    270 static void
    271 create3Dtexture(void)
    272 {
    273    unsigned char *voxels = NULL;
    274    int i, j, k;
    275    unsigned char *vp;
    276    float vec[3];
    277    int tmp;
    278 
    279    printf("creating 3d textures...\n");
    280    voxels =
    281       (unsigned char *)
    282       malloc((size_t) (4 * tex_width * tex_height * tex_depth));
    283    vp = voxels;
    284    for (i = 0; i < tex_width; i++) {
    285       vec[0] = i;
    286       for (j = 0; j < tex_height; j++) {
    287 	 vec[1] = j;
    288 	 for (k = 0; k < tex_depth; k++) {
    289 	    vec[2] = k;
    290 	    tmp = (sin(k * i * j + turbulence(vec, 0.01, 1)) + 1) * 127.5;
    291 	    *vp++ = 0;
    292 	    *vp++ = 0;
    293 	    *vp++ = tmp;
    294 	    *vp++ = tmp + 128;
    295 	 }
    296       }
    297    }
    298 
    299    printf("setting up 3d texture...\n");
    300 
    301    glBindTexture(GL_TEXTURE_3D, NOISE_TEXTURE);
    302    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    303    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    304    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
    305    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    306 
    307    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    308    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
    309 		tex_width, tex_height, tex_depth,
    310 		0, GL_RGBA, GL_UNSIGNED_BYTE, voxels);
    311    if (glGetError() == GL_OUT_OF_MEMORY)
    312       printf("stex3d: Out of memory allocating %d x %d x %d RGBA texture",
    313              tex_width, tex_height, tex_depth);
    314 
    315    free(voxels);
    316 
    317    printf("finished setting up 3d texture image.\n");
    318 }
    319 
    320 
    321 static void
    322 printHelp(void)
    323 {
    324    printf("\nUsage: stex3d  <cmd line options>\n");
    325    printf(" cmd line options:\n");
    326    printf("      -wxxx   Width of the texture (Default=64)\n");
    327    printf("      -hxxx   Height of the texture (Default=64)\n");
    328    printf("      -dxxx   Depth of the texture (Default=64)\n");
    329    printf(" Keyboard Options:\n");
    330    printf("    up/down   rotate around X\n");
    331    printf("  left/right  rotate around Y\n");
    332    printf("      z/Z     rotate around Z\n");
    333    printf("       a      toggle animation\n");
    334    printf("       s      toggle smooth shading\n");
    335    printf("       t      toggle texgen mode\n");
    336    printf("       o      toggle object: torus/sphere\n");
    337    printf("       i      toggle texture image: noise/gradient\n");
    338    printf("       f      toggle linear/nearest filtering\n");
    339 }
    340 
    341 
    342 static GLenum
    343 parseCmdLine(int argc, char **argv)
    344 {
    345    GLint i;
    346 
    347    for (i = 1; i < argc; i++) {
    348       if (strcmp(argv[i], "-help") == 0) {
    349 	 printHelp();
    350 	 return GL_FALSE;
    351       }
    352       else if (strstr(argv[i], "-w") != NULL) {
    353 	 tex_width = atoi((argv[i]) + 2);
    354       }
    355       else if (strstr(argv[i], "-h") != NULL) {
    356 	 tex_height = atoi((argv[i]) + 2);
    357       }
    358       else if (strstr(argv[i], "-d") != NULL) {
    359 	 tex_depth = atoi((argv[i]) + 2);
    360       }
    361       else {
    362 	 printf("%s (Bad option).\n", argv[i]);
    363 	 printHelp();
    364 	 return GL_FALSE;
    365       }
    366    }
    367    if (tex_width == 0 || tex_height == 0 || tex_depth == 0) {
    368       printf("%s (Bad option).\n", "size parameters can't be 0");
    369       printHelp();
    370       return GL_FALSE;
    371    }
    372    return GL_TRUE;
    373 }
    374 
    375 
    376 static void
    377 drawScene(void)
    378 {
    379    static const GLfloat sPlane[4] = { 0.5, 0, 0, -.5 };
    380    static const GLfloat tPlane[4] = { 0, 0.5, 0, -.5 };
    381    static const GLfloat rPlane[4] = { 0, 0, 0.5, -.5 };
    382 
    383    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    384    glPushMatrix();
    385    if (texgen == 2) {
    386       glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
    387       glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
    388       glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
    389    }
    390 
    391    glRotatef(angx, 1.0, 0.0, 0.0);
    392    glRotatef(angy, 0.0, 1.0, 0.0);
    393    glRotatef(angz, 0.0, 0.0, 1.0);
    394 
    395    if (texgen == 1) {
    396       glTexGenfv(GL_S, GL_EYE_PLANE, sPlane);
    397       glTexGenfv(GL_T, GL_EYE_PLANE, tPlane);
    398       glTexGenfv(GL_R, GL_EYE_PLANE, rPlane);
    399    }
    400 
    401    if (texgen) {
    402       glEnable(GL_TEXTURE_GEN_S);
    403       glEnable(GL_TEXTURE_GEN_T);
    404       glEnable(GL_TEXTURE_GEN_R);
    405    }
    406    else {
    407       glDisable(GL_TEXTURE_GEN_S);
    408       glDisable(GL_TEXTURE_GEN_T);
    409       glDisable(GL_TEXTURE_GEN_R);
    410    }
    411 
    412    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, Filter);
    413    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, Filter);
    414 
    415    glCallList(CurObject);
    416    glPopMatrix();
    417 
    418    glutSwapBuffers();
    419 }
    420 
    421 
    422 static void
    423 resize(int w, int h)
    424 {
    425    float ar = (float) w / (float) h;
    426    float ax = 0.6 * ar;
    427    float ay = 0.6;
    428    glViewport(0, 0, (GLint) w, (GLint) h);
    429    glMatrixMode(GL_PROJECTION);
    430    glLoadIdentity();
    431    glFrustum(-ax, ax, -ay, ay, 2, 20);
    432    /*glOrtho(-2, 2, -2, 2, -10, 10);*/
    433    glMatrixMode(GL_MODELVIEW);
    434    glLoadIdentity();
    435    glTranslatef(0, 0, -4);
    436 }
    437 
    438 
    439 static void
    440 Idle(void)
    441 {
    442    float t = glutGet(GLUT_ELAPSED_TIME);
    443    angx = 0.01 * t;
    444    angy = 0.03 * t;
    445    angz += 0;
    446    glutPostRedisplay();
    447 }
    448 
    449 
    450 static void
    451 SpecialKey(int k, int x, int y)
    452 {
    453   switch (k) {
    454   case GLUT_KEY_UP:
    455     angx += 5.0;
    456     break;
    457   case GLUT_KEY_DOWN:
    458     angx -= 5.0;
    459     break;
    460   case GLUT_KEY_LEFT:
    461     angy += 5.0;
    462     break;
    463   case GLUT_KEY_RIGHT:
    464     angy -= 5.0;
    465     break;
    466   default:
    467     return;
    468   }
    469   glutPostRedisplay();
    470 }
    471 
    472 
    473 static void
    474 KeyHandler(unsigned char key, int x, int y)
    475 {
    476    static const char *mode[] = {
    477       "glTexCoord3f (no texgen)",
    478       "texgen fixed to object coords",
    479       "texgen fixed to eye coords"
    480    };
    481    (void) x;
    482    (void) y;
    483    switch (key) {
    484    case 27:
    485    case 'q':
    486    case 'Q':			/* quit game. */
    487       exit(0);
    488       break;
    489    case 'z':
    490       angz += 10;
    491       break;
    492    case 'Z':
    493       angz -= 10;
    494       break;
    495    case 's':
    496       smooth = !smooth;
    497       if (smooth)
    498          glShadeModel(GL_SMOOTH);
    499       else
    500          glShadeModel(GL_FLAT);
    501       break;
    502    case 't':
    503       texgen++;
    504       if (texgen > 2)
    505          texgen = 0;
    506       printf("Texgen: %s\n", mode[texgen]);
    507       break;
    508    case 'o':
    509       if (CurObject == TORUS)
    510          CurObject = SPHERE;
    511       else
    512          CurObject = TORUS;
    513       break;
    514    case 'f':
    515       if (Filter == GL_LINEAR)
    516          Filter = GL_NEAREST;
    517       else
    518          Filter = GL_LINEAR;
    519       break;
    520    case 'i':
    521       if (CurTexture == NOISE_TEXTURE)
    522          CurTexture = GRADIENT_TEXTURE;
    523       else
    524          CurTexture = NOISE_TEXTURE;
    525       glBindTexture(GL_TEXTURE_3D, CurTexture);
    526       break;
    527    case 'a':
    528    case ' ':
    529       animate = !animate;
    530       if (animate)
    531          glutIdleFunc(Idle);
    532       else
    533          glutIdleFunc(NULL);
    534       break;
    535    case 'w':
    536       wireframe = !wireframe;
    537       if (wireframe)
    538          glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    539       else
    540          glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    541       break;
    542    default:
    543       break;
    544    }
    545    glutPostRedisplay();
    546 }
    547 
    548 
    549 static void
    550 create3Dgradient(void)
    551 {
    552    unsigned char *v;
    553    int i, j, k;
    554    unsigned char *voxels = NULL;
    555 
    556    voxels = (unsigned char *) malloc(4 * tex_width * tex_height * tex_depth);
    557    v = voxels;
    558 
    559    for (i = 0; i < tex_depth; i++) {
    560       for (j = 0; j < tex_height; j++) {
    561 	 for (k = 0; k < tex_width; k++) {
    562 	    GLint r = (255 * i) / (tex_depth - 1);
    563 	    GLint g = (255 * j) / (tex_height - 1);
    564 	    GLint b = (255 * k) / (tex_width - 1);
    565 	    *v++ = r;
    566 	    *v++ = g;
    567 	    *v++ = b;
    568 	    *v++ = 255;
    569 	 }
    570       }
    571    }
    572 
    573 
    574    glBindTexture(GL_TEXTURE_3D, GRADIENT_TEXTURE);
    575    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    576    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    577    glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
    578    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    579 
    580    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    581    glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA,
    582 		tex_width, tex_height, tex_depth,
    583 		0, GL_RGBA, GL_UNSIGNED_BYTE, voxels);
    584    if (glGetError() == GL_OUT_OF_MEMORY)
    585       printf("stex3d: Out of memory allocating %d x %d x %d RGBA texture",
    586              tex_width, tex_height, tex_depth);
    587 
    588    free(voxels);
    589 }
    590 
    591 
    592 
    593 static void
    594 init(void)
    595 {
    596    static const GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
    597    static const GLfloat mat_shininess[] = { 25.0 };
    598    static const GLfloat gray[] = { 0.6, 0.6, 0.6, 0.0 };
    599    static const GLfloat white[] = { 1.0, 1.0, 1.0, 0.0 };
    600    static const GLfloat light_position[] = { 0.0, 1.0, 1.0, 0.0 };
    601 
    602    int max;
    603 
    604    /* see if we have OpenGL 1.2 or later, for 3D texturing */
    605    {
    606       const char *version = (const char *) glGetString(GL_VERSION);
    607       if (strncmp(version, "1.0", 3) == 0 || strncmp(version, "1.1", 3) == 0) {
    608 	 printf("Sorry, OpenGL 1.2 or later is required\n");
    609 	 exit(1);
    610       }
    611    }
    612    printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
    613    glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &max);
    614    printf("GL_MAX_3D_TEXTURE_SIZE: %d\n", max);
    615    printf("Current 3D texture size: %d x %d x %d\n",
    616           tex_width, tex_height, tex_depth);
    617 
    618    /* init light */
    619    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    620    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    621    glLightfv(GL_LIGHT1, GL_POSITION, light_position);
    622    glLightfv(GL_LIGHT1, GL_AMBIENT, gray);
    623    glLightfv(GL_LIGHT1, GL_DIFFUSE, white);
    624    glLightfv(GL_LIGHT1, GL_SPECULAR, white);
    625    glColorMaterial(GL_FRONT, GL_DIFFUSE);
    626    glEnable(GL_COLOR_MATERIAL);
    627    glEnable(GL_LIGHTING);
    628    glEnable(GL_LIGHT1);
    629 
    630    glClearColor(.5, .5, .5, 0);
    631 
    632    {
    633       GLUquadricObj *q;
    634       q = gluNewQuadric();
    635       gluQuadricTexture( q, GL_TRUE );
    636       glNewList(SPHERE, GL_COMPILE);
    637       gluSphere( q, 0.95, 30, 15 );
    638       glEndList();
    639       gluDeleteQuadric(q);
    640    }
    641 
    642    BuildTorus();
    643 
    644 
    645    create3Dgradient();
    646 
    647    initNoise();
    648    create3Dtexture();
    649 
    650    glEnable(GL_TEXTURE_3D);
    651 
    652    /*
    653       glBlendFunc(GL_SRC_COLOR, GL_SRC_ALPHA);
    654       glEnable(GL_BLEND);
    655     */
    656    glEnable(GL_DEPTH_TEST);
    657 
    658    glColor3f(0.6, 0.7, 0.8);
    659 }
    660 
    661 
    662 int
    663 main(int argc, char **argv)
    664 {
    665    glutInit(&argc, argv);
    666 
    667    if (parseCmdLine(argc, argv) == GL_FALSE) {
    668       exit(0);
    669    }
    670 
    671    glutInitWindowPosition(0, 0);
    672    glutInitWindowSize(400, 400);
    673    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    674 
    675    if (glutCreateWindow("stex3d") <= 0) {
    676       exit(0);
    677    }
    678 
    679    glewInit();
    680 
    681    init();
    682 
    683    printHelp();
    684 
    685    glutReshapeFunc(resize);
    686    glutKeyboardFunc(KeyHandler);
    687    glutSpecialFunc(SpecialKey);
    688    glutDisplayFunc(drawScene);
    689    if (animate)
    690       glutIdleFunc(Idle);
    691    glutMainLoop();
    692    return 0;
    693 }
    694 
    695