/* Auteur: Nicolas JANEY */ /* nicolas.janey@univ-fcomte.fr */ /* Novembre 2007 */ /* Un mini programme de ray-tracing */ #include #include #include #include #include #include /* Variables globales de gestion */ /* de l'interactivite clavier et souris */ static int clic = 0; static int mx; static int my; static float rx = 0.0F; static float ry = 0.0F; /* Type de stockage d'une position */ typedef struct position { double x; double y; double z; double t; } position; /* Type de stockage d'une direction */ typedef struct direction { double x; double y; double z; double t; } direction; /* Type de stockage d'une couleur */ typedef struct couleur { double r; double v; double b; } couleur; /* Type de stockage d'une energie coloree */ typedef struct energie { double r; double v; double b; } energie; /* Type de stockage d'un materiel avec */ /* - coefficients de diffusion */ /* - coefficients de reflexion */ /* - coefficients de transmission */ /* - indice de refraction */ typedef struct materiel { couleur kd; couleur kr; couleur kt; double indice; } materiel; /* Type de stockage d'une sphere */ typedef struct sphere { position centre; double rayon; materiel materiel; } sphere; /* Type de stockage d'une lumiere ponctuelle */ typedef struct lumierePonctuelle { position position; double intensite; couleur couleur; } lumierePonctuelle; /* Type de stockage d'une lumiere */ /* directionnelle */ typedef struct lumiereDirectionnelle { direction direction; double intensite; couleur couleur; } lumiereDirectionnelle; /* Type de stockage d'une scene */ typedef struct scene { int nbSpheres; sphere *spheres; int nbLumieresPonctuelles; lumierePonctuelle *lumieresPonctuelles; int nbLumieresDirectionnelles; lumiereDirectionnelle *lumieresDirectionnelles; } scene; /* Type de stockage d'un rayon lumineux compose */ /* d'une origine et d'une direction d'emission */ typedef struct rayonLumineux { position origine; direction direction; } rayonLumineux; /* Definition d'une premiere scene en statique */ static sphere spheres1[6] = { { { 0.0,0.0,-600.0,1.0 }, 40.0, { { 1.0,1.0,0.0 }, { 0.0,0.0,0.0 }, { 0.0,0.0,0.0 }, 1.0 } }, { { 90.0,90.0,-600.0,1.0 }, 40.0, { { 1.0,1.0,1.0 }, { 0.0,0.0,0.0 }, { 0.0,0.0,0.0 }, 1.0 } }, { { -90.0,90.0,-600.0,1.0 }, 40.0, { { 1.0,0.0,0.0 }, { 0.0,0.0,0.0 }, { 0.0,0.0,0.0 }, 1.0 } }, { { 90.0,-90.0,-600.0,1.0 }, 40.0, { { 0.0,1.0,0.0 }, { 0.0,0.0,0.0 }, { 0.0,0.0,0.0 }, 1.0 } }, { { -90.0,-90.0,-600.0,1.0 }, 40.0, { { 0.0,0.0,1.0 }, { 0.0,0.0,0.0 }, { 0.0,0.0,0.0 }, 1.0 } },{ { 0.0,0.0,-200.0,1.0 }, 120.0, { { 0.25,0.25,0.25 }, { 0.0,0.0,0.0 }, { 0.75,0.75,0.75 }, 1.5 } } }; static lumierePonctuelle lumieresPonctuelles1[2] = { { { 80.0,20.0,0.0,1.0 }, 15000.0, { 0.9,0.9,0.0 } }, { { -80.0,-20.0,0.0,1.0 }, 28000.0, { 0.8,0.8,0.8 } } }; static lumiereDirectionnelle lumieresDirectionnelles1[2] = { { { 1.0,1.0,1.0,0.0 }, 3.0, { 0.0,0.9,0.9 } }, { { -1.0,1.0,1.0,0.0 }, 1.5, { 0.8,0.0,0.8 } } }; static scene scn1 = { 6, spheres1, 2, lumieresPonctuelles1, 2, lumieresDirectionnelles1 }; /* Definition d'une seconde scene en statique */ static sphere spheres2[8] = { { { 130.0,50.0,-200.0,1.0 }, 90.0, { { 0.8,0.8,0.8 }, { 0.1,0.1,0.1 }, { 0.1,0.1,0.1 }, 1.3 } }, { { 130.0,115.0,-100.0,1.0 }, 20.0, { { 0.3,0.3,0.8 }, { 0.6,0.6,0.1 }, { 0.1,0.1,0.1 }, 1.3 } }, { { 10.0,-10.0,-150.0,1.0 }, 70.0, { { 0.1,0.2,0.4 }, { 0.9,0.8,0.6 }, { 0.0,0.0,0.0 }, 1.5 } }, { { -150.0,-60.0,-150.0,1.0 }, 60.0, { { 0.5,0.4,0.3 }, { 0.1,0.1,0.1 }, { 0.4,0.5,0.6 }, 1.4 } }, { { -110.0,-80.0,-30.0,1.0 }, 30.0, { { 0.4,0.3,0.2 }, { 0.3,0.2,0.4 }, { 0.2,0.4,0.3 }, 1.2 } }, { { 50.0,20.0,-30.0,1.0 }, 10.0, { { 0.2,0.3,0.0 }, { 0.8,0.6,0.7 }, { 0.0,0.1,0.3 }, 1.2 } }, { { -90.0,90.0,-70.0,1.0 }, 50.0, { { 1.0,0.5,0.5 }, { 0.0,0.5,0.5 }, { 0.0,0.0,0.0 }, 1.2 } }, { { 0.0,65.0,-45.0,1.0 }, 44.0, { { 0.25,0.25,0.25 }, { 0.0,0.0,0.0 }, { 0.75,0.75,0.75 }, 1.45 } } }; static lumierePonctuelle lumieresPonctuelles2[2] = { { { 80.0,20.0,0.0,1.0 }, 15000.0, { 0.9,0.9,0.0 } }, { { -80.0,-20.0,0.0,1.0 }, 28000.0, { 0.8,0.8,0.8 } } }; static lumiereDirectionnelle lumieresDirectionnelles2[2] = { { { 1.0,1.0,1.0,0.0 }, 3.0, { 0.0,0.9,0.9 } }, { { -1.0,1.0,1.0,0.0 }, 1.5, { 0.8,0.0,0.8 } } }; static scene scn2 = { 8, spheres2, 2, lumieresPonctuelles2, 2, lumieresDirectionnelles2 }; /* Definition d'un tableau de 2 scenes */ static scene *scn[2] = { &scn1, &scn2 }; /* Definition d'une structure de stockage */ /* d'une image */ struct image { int tx; int ty; GLubyte **t; }; /* Variables globales de stockage des handles */ /* des deux fenetres */ static int f1; static int f2; /* Variables globales */ static int lignesTraitees = 0; static image ima = { 0,0,NULL } ; static long nbRayons; static int sc = 0; static int mode = 1; /* Variables globales de gestion du ray-tracing */ static int niveauRecursivite = 10; static int resolutionX = 480; static int resolutionY = 300; static double sensibilite = 100.0; /* Fonction d'allocation memoire */ /* d'une image bitmap */ void allocationMemoire(int tx,int ty,image *im) { im->tx = tx; im->ty = ty; im->t =(GLubyte **) calloc(ty,sizeof(GLubyte *)); int i; for ( i = 0 ; i < ty ; i++ ) { im->t[i] =(GLubyte *) calloc(3*tx,sizeof(GLubyte)); } } /* Fonction de desallocation memoire */ /* d'une image bitmap */ void desallocationMemoire(image *im) { if ( im->t != NULL ) { for ( int i = 0 ; i < im->ty ; i++ ) { free(im->t[i]); } free(im->t); } } /* Fonction d'affichage d'une eventuelle */ /* erreur OpenGL */ static void checkError(int line) { GLenum err = glGetError(); if (err) { printf("GL Error %s (0x%x) at line %d\n", gluErrorString(err), (int) err, line); } } /* Fonction d'affichage d'une image bitmap */ void affichageImage(image *img) { for ( int i = 0 ; i < img->ty ; i++ ) { glRasterPos2f(0,i); glDrawPixels(img->tx,1,GL_RGB,GL_UNSIGNED_BYTE,img->t[i]); } } /* Fonction display GLUT d'affichage */ /* de la bitmap resultat du ray-tracing */ void display(void) { glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); glClearColor(0.0,0.0,0.0,1.0); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_PACK_ALIGNMENT,1); affichageImage(&ima); glPopMatrix(); glFlush(); checkError(__LINE__); glutSwapBuffers(); } /* Fonction d'affectation de la couleur */ /* d'un pixel d'une image a partir */ /* d'une energie et d'une sensibilite */ void affecteEnergieSurPixel(energie *energie,double sensibilite, image *img,int x,int y) { GLubyte *p = &img->t[y][x*3]; double r = energie->r*sensibilite+0.5; double v = energie->v*sensibilite+0.5; double b = energie->b*sensibilite+0.5; if ( r > 255.0 ) r = 255.0; if ( v > 255.0 ) v = 255.0; if ( b > 255.0 ) b = 255.0; p[0] =(GLubyte) (r); p[1] =(GLubyte) (v); p[2] =(GLubyte) (b); } /* Fonction de determination de l'intersection */ /* entre un rayon lumineux et une sphere. */ /* Un int booleen en retour pour indiquer */ /* l'existence ou non d'une intersection. */ /* Un double en passage par adresse pour */ /* retourner la distance entre l'origine */ /* du rayon en l'intersection la plus proche */ /* de l'origine du rayon sur sa trajectoire. */ int intersection(rayonLumineux *rl,sphere *sp,double *d) { return(0); } /* Fonction de determination de l'existence */ /* d'une intersection entre un rayon lumineux */ /* et une sphere. */ int intersection(rayonLumineux *rl,sphere *sp) { return(0); } /* Fonction de test de nullite d'une couleur */ /* (noir) */ int estNul(couleur *cf) { return(( cf->r == 0.0 ) && ( cf->v == 0.0 ) && ( cf->b == 0.0 ) ); } /* Fonction de calcul de la position d'un point */ /* sur un rayon lumineux */ void calculPositionSurRayon(position *p,rayonLumineux *rl,double d) { p->x = rl->origine.x + d*rl->direction.x; p->y = rl->origine.y + d*rl->direction.y; p->z = rl->origine.z + d*rl->direction.z; } /* Fonction de calcul de la normale exterieur */ /* en un point d'une sphere */ void calculNormale(direction *d,position *p,sphere *sp) { d->x = (p->x - sp->centre.x)/sp->rayon; d->y = (p->y - sp->centre.y)/sp->rayon; d->z = (p->z - sp->centre.z)/sp->rayon; } /* Fonction de calcul du carre de la distance */ /* entre deux positions */ double carreDistance(position *p1,position *p2) { double dx = p2->x-p1->x; double dy = p2->y-p1->y; double dz = p2->z-p1->z; return(dx*dx+dy*dy+dz*dz); } /* Fonction de calcul de la distance */ /* entre deux positions */ double distance(position *p1,position *p2) { return(sqrt(carreDistance(p1,p2))); } /* Fonction de normalisation d'une direction */ void normalise(direction *d) { double l = sqrt(d->x*d->x+d->y*d->y+d->z*d->z); if ( l != 0 ) { d->x /= l; d->y /= l; d->z /= l; } } /* Fonction de calcul du produit scalaire */ /* entre deux directions */ double produitScalaire(direction *d1,direction *d2) { return(d1->x*d2->x+d1->y*d2->y+d1->z*d2->z); } /* Fonction de calcul de la direction */ /* normalisee definie d'une position */ /* a une autre position */ void calculDirectionNormalisee(direction *d, position *p1,position *p2) { d->x = p2->x-p1->x; d->y = p2->y-p1->y; d->z = p2->z-p1->z; normalise(d); } /* Fonction de calcul de la quantite d'energie */ /* diffusee sous l'eclairage d'une source */ /* lumineuse ponctuelle */ void calculDiffusion(energie *ed, position *p,direction *n, couleur *kd, lumierePonctuelle *lp) { if ( estNul(kd) ) { ed->r = ed->v = ed->b = 0.0; return; } direction l; calculDirectionNormalisee(&l,p,&lp->position); double ps = produitScalaire(&l,n); if ( ps <= 0.0 ) { ed->r = ed->v = ed->b = 0.0; return; } double fact = ps*lp->intensite/carreDistance(p,&lp->position); ed->r = fact*lp->couleur.r*kd->r; ed->v = fact*lp->couleur.v*kd->v; ed->b = fact*lp->couleur.b*kd->b; } /* Fonction de calcul de la quantite d'energie */ /* diffusee sous l'eclairage d'une source */ /* lumineuse directionnelle */ void calculDiffusion(energie *ed, direction *n, couleur *kd, lumiereDirectionnelle *ld) { if ( estNul(kd) ) { ed->r = ed->v = ed->b = 0.0; return; } direction l = ld->direction; normalise(&l); double ps = produitScalaire(&l,n); if ( ps <= 0.0 ) { ed->r = ed->v = ed->b = 0.0; return; } double fact = ps*ld->intensite; ed->r = fact*ld->couleur.r*kd->r; ed->v = fact*ld->couleur.v*kd->v; ed->b = fact*ld->couleur.b*kd->b; } /* Fonction de test de l'intersection */ /* d'un rayon d'ombre avec l'ensemble */ /* des objets d'une scene */ int intersection(rayonLumineux *rlo,scene *scn) { for ( int i = 0 ; i < scn->nbSpheres ; i++ ) if ( intersection(rlo,&scn->spheres[i]) ) return(1); return(0); } /* Fonction de test de l'occultation d'un point */ /* eclaire par une lumiere directionnelle */ /* par l'ensemble des objets d'une scene */ int estEclaire(position *p,scene *scn, lumiereDirectionnelle *ld) { rayonLumineux rlo; rlo.origine = *p; rlo.direction = ld->direction; normalise(&rlo.direction); return(!intersection(&rlo,scn)); } /* Fonction de test de l'intersection */ /* d'un rayon d'ombre avec l'ensemble */ /* des objets d'une scene. */ /* Les intersections candidates sont limitees */ /* a celles situees a une distance de la source */ /* du rayon inferieure a une distance limite. */ int intersection(rayonLumineux *rlo,scene *scn,double d) { double dist; for ( int i = 0 ; i < scn->nbSpheres ; i++ ) if ( intersection(rlo,&scn->spheres[i],&dist) ) { if ( dist < d ) return(1); } return(0); } /* Fonction de test de l'occultation d'un point */ /* eclaire par une source lumineuse ponctuelle */ /* par l'ensemble des objets d'une scene */ int estEclaire(position *p,scene *scn, lumierePonctuelle *lp,double d) { rayonLumineux rlo; rlo.origine = *p; calculDirectionNormalisee(&rlo.direction,p,&lp->position); return(!intersection(&rlo,scn,d)); } /* Fonction de calcul de la quantite d'energie */ /* diffusee en un point d'une sphere */ /* sous l'eclairage de l'ensemble des sources */ /* lumineuses d'une scene */ void calculDiffusion(energie *e, scene *scn, sphere *sp,position *p,direction *n) { e->r = e->v = e->b = 0.0; int i; for ( i = 0 ; i < scn->nbLumieresPonctuelles ; i++ ) { lumierePonctuelle *lp = &scn->lumieresPonctuelles[i]; double d = distance(p,&lp->position); if ( estEclaire(p,scn,lp,d) ) { energie ed; calculDiffusion(&ed,p,n, &sp->materiel.kd, lp); e->r += ed.r; e->v += ed.v; e->b += ed.b; } } for ( i = 0 ; i < scn->nbLumieresDirectionnelles ; i++ ) { lumiereDirectionnelle *ld = &scn->lumieresDirectionnelles[i]; if ( estEclaire(p,scn,ld) ) { energie ed; calculDiffusion(&ed,n, &sp->materiel.kd, ld); e->r += ed.r; e->v += ed.v; e->b += ed.b; } } } /* Fonction de calcul de la direction du rayon */ /* lumineux reflechi cree par un rayon lumineux */ /* incident defini par sa direction */ /* de propagation */ void reflexion(direction *r,direction *i,direction *n) { } /* Fonction de calcul du rayon lumineux */ /* reflechi cree par un rayon lumineux incident */ void rayonReflechi(rayonLumineux *rr, rayonLumineux *ri, sphere *sp,position *p,direction *n) { direction i = ri->direction; i.x *= -1; i.y *= -1; i.z *= -1; rr->origine = *p; reflexion(&rr->direction,&i,n); } /* Fonction de calcul de la direction du rayon */ /* lumineux transmis eventuellement cree */ /* par un rayon lumineux incident defini */ /* par sa direction de propagation */ int transmission(direction *t,direction *i,direction *n, double niSurnt) { return(0); } /* Fonction de calcul du rayon lumineux */ /* transmis genere eventuellement */ /* par un rayon lumineux incident */ int rayonTransmis(rayonLumineux *rt, rayonLumineux *ri, sphere *sp,position *p,direction *n, double niSurnt,int exterieur) { direction norm = *n; if ( !exterieur ) { norm.x *= -1; norm.y *= -1; norm.z *= -1; } direction i = ri->direction; i.x *= -1; i.y *= -1; i.z *= -1; if ( transmission(&rt->direction,&i,&norm,niSurnt) ) { rt->origine = *p; return(1); } else return(0); } /* Fonction principale recursive de calcul */ /* de ray-tracing */ void rayTracing(energie *e, rayonLumineux *rl, scene *scn, int niveau, double indiceRefraction, int exterieur) { nbRayons++; e->r = e->v = e->b = 0.0; double dmin = 1000000000.0; int obj = -1; int i; for ( i = 0 ; i < scn->nbSpheres ; i++ ) { double dist; if ( intersection(rl,&scn->spheres[i],&dist) ) { if ( dist < dmin ) { dmin = dist; obj = i; } } } if ( obj != -1 ) { position p; calculPositionSurRayon(&p,rl,dmin); direction n; calculNormale(&n,&p,&scn->spheres[obj]); if ( exterieur ) { energie ed; calculDiffusion(&ed,scn,&scn->spheres[obj],&p,&n); e->r += ed.r; e->v += ed.v; e->b += ed.b; } if ( niveau != 1 ) { sphere *sp = &scn->spheres[obj]; couleur *kr = &sp->materiel.kr; couleur *kt = &sp->materiel.kt; if ( !estNul(kr) && exterieur ) { rayonLumineux rr; rayonReflechi(&rr,rl,sp,&p,&n); energie er; rayTracing(&er,&rr,scn,niveau-1,indiceRefraction,1); e->r += er.r*kr->r; e->v += er.v*kr->v; e->b += er.b*kr->b; } if ( !estNul(kt) ) { rayonLumineux rt; double niSurnt = indiceRefraction/sp->materiel.indice; if ( rayonTransmis(&rt, rl,sp,&p,&n,niSurnt,exterieur) ) { energie et; rayTracing(&et, &rt, scn, niveau-1, (exterieur) ? sp->materiel.indice : 1.0, !exterieur); e->r += et.r*kt->r; e->v += et.v*kt->v; e->b += et.b*kt->b; } } } } } /* Fonction de calcul en ray-tracing */ /* d'une ligne de l'image */ /* Chaque rayon primaire est dirige en -z */ /* -> projection parallele orthographique */ void traiteLigne(int ligne,image *img) { for ( int i = 0 ; i < img->tx ; i++ ) { rayonLumineux rl; rl.origine.x = (i-img->tx/2.0)/(img->tx/480.0); rl.origine.y = (ligne-img->ty/2.0)/(img->tx/480.0); rl.origine.z = 0.0; rl.origine.t = 1.0; rl.direction.x = 0.0; rl.direction.y = 0.0; rl.direction.z = -1.0; rl.direction.t = 0.0; energie energieRecue; rayTracing(&energieRecue,&rl,scn[sc],niveauRecursivite,1.0,1); affecteEnergieSurPixel(&energieRecue,sensibilite,img,i,ligne); } } /* Fonction idle */ /* Calcul de 20 lignes de pixels en ray-tracing */ /* Arret quand l'image est entierement calculee */ void idle(void) { for ( int i = 0 ; i < 20 ; i++ ) { traiteLigne(lignesTraitees,&ima); lignesTraitees++; if ( lignesTraitees == resolutionY ) { glutIdleFunc(NULL); printf("%d %d\n",niveauRecursivite,nbRayons); glutPostWindowRedisplay(f1); return; } } glutPostWindowRedisplay(f1); } /* Fonction executee lors de la frappe */ /* d'une touche alphanumerique du clavier */ void key(unsigned char key,int x,int y) { switch ( key ) { case 43 : niveauRecursivite++; lignesTraitees = 0; desallocationMemoire(&ima); allocationMemoire(resolutionX,resolutionY,&ima); nbRayons = 0; glutIdleFunc(idle); break; case 45 : niveauRecursivite--; if ( niveauRecursivite < 1 ) niveauRecursivite = 1; lignesTraitees = 0; desallocationMemoire(&ima); allocationMemoire(resolutionX,resolutionY,&ima); nbRayons = 0; glutIdleFunc(idle); break; case 0x20 : sc = (sc+1)%2; glutIdleFunc(NULL); glutPostWindowRedisplay(f2); break; case 0x0D : lignesTraitees = 0; desallocationMemoire(&ima); allocationMemoire(resolutionX,resolutionY,&ima); nbRayons = 0; glutIdleFunc(idle); break; case 0x1B : desallocationMemoire(&ima); exit(0); break; } } /* Fonction reshape de l'affichage ray-tracing */ void reshape(int w,int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,w,0,h,-1.0,1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); resolutionX = w; resolutionY = h; desallocationMemoire(&ima); allocationMemoire(resolutionX,resolutionY,&ima); glutIdleFunc(NULL); glutSetWindow(f2); glutReshapeWindow(w,h); } /* Fonction reshape de l'affichage OpenGL */ void reshapeOpenGL(int w,int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-240.0,240.0, -240.0*(double) h/w,240.0*(double) h/w, -5000.0,5000.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } /* Fonction display GLUT d'affichage OpenGL */ /* de la scene */ void displayOpenGL(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glEnable(GL_AUTO_NORMAL); glEnable(GL_CULL_FACE); glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); float noir[4] = { 0.0F,0.0F,0.0F,0.0F }; glPushMatrix(); glTranslatef(0.0F,0.0F,-150.0F); glRotatef(rx,1.0F,0.0F,0.0F); glRotatef(ry,0.0F,1.0F,0.0F); glTranslatef(0.0F,0.0F,150.0F); int lum = GL_LIGHT0; int i; for ( i = 0 ; i < scn[sc]->nbLumieresPonctuelles ; i++ ) { lumierePonctuelle *lp = &scn[sc]->lumieresPonctuelles[i]; float fact = lp->intensite * sensibilite / 255.0; glEnable(lum); float pos[4] = { lp->position.x, lp->position.y, lp->position.z, 1.0F }; glLightfv(lum,GL_POSITION,pos); glLightf(lum,GL_CONSTANT_ATTENUATION,1.0F); glLightf(lum,GL_LINEAR_ATTENUATION,1.0F); glLightf(lum,GL_QUADRATIC_ATTENUATION,1.0F); float dif[4] = { lp->couleur.r * fact, lp->couleur.v * fact, lp->couleur.b * fact, 1.0F }; glLightfv(lum,GL_SPECULAR,noir); glLightfv(lum,GL_DIFFUSE,dif); lum++; } for ( i = 0 ; i < scn[sc]->nbLumieresDirectionnelles ; i++ ) { lumiereDirectionnelle *ld = &scn[sc]->lumieresDirectionnelles[i]; glEnable(lum); float dir[4] = { ld->direction.x, ld->direction.y, ld->direction.z, 0.0F }; glLightfv(lum,GL_POSITION,dir); glLightf(lum,GL_CONSTANT_ATTENUATION,1.0F); glLightf(lum,GL_LINEAR_ATTENUATION,1.0F); glLightf(lum,GL_QUADRATIC_ATTENUATION,1.0F); float fact = ld->intensite * sensibilite / 255.0; float dif[4] = { ld->couleur.r * fact, ld->couleur.v * fact, ld->couleur.b * fact, 1.0F }; glLightfv(lum,GL_SPECULAR,noir); glLightfv(lum,GL_DIFFUSE,dif); lum++; } for ( i = 0 ; i < scn[sc]->nbSpheres ; i++ ) { sphere *sp = &scn[sc]->spheres[i]; float alpha =(sp->materiel.kt.r+ sp->materiel.kt.v+ sp->materiel.kt.b)/3.0F; glPushMatrix(); glTranslated(sp->centre.x,sp->centre.y,sp->centre.z); float dif[4] = { sp->materiel.kd.r, sp->materiel.kd.v, sp->materiel.kd.b, 1.0F-alpha }; glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,dif); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,noir); glutSolidSphere(sp->rayon,180,180); glPopMatrix(); } glPopMatrix(); glFlush(); checkError(__LINE__); glutSwapBuffers(); } /* Fonction executee lors d'un clic de souris */ /* dans la fenetre */ void mouse(int bouton,int etat,int x,int y) { if ( bouton == GLUT_LEFT_BUTTON ) { if ( etat == GLUT_DOWN ) { clic = 1; mx = x; my = y; } if ( etat == GLUT_UP ) { clic = 0; } } } /* Fonction executee lors d'un deplacement */ /* de la souris sur la fenetre */ /* avec un bouton appuye */ void motion(int x,int y) { if ( clic ) { ry += (x-mx); rx += (y-my); mx = x; my = y; glutPostWindowRedisplay(f2); } } /* Fonction Pricipale */ int main(int argc,char **argv) { allocationMemoire(resolutionX,resolutionY,&ima); glutInit(&argc,argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowSize(resolutionX,resolutionY); glutInitWindowPosition(30,30); f1 = glutCreateWindow("Mini Ray-Tracing"); glutReshapeFunc(reshape); glutKeyboardFunc(key); glutDisplayFunc(display); glutInitWindowPosition(530,30); f2 = glutCreateWindow("OpenGL"); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(key); glutReshapeFunc(reshapeOpenGL); glutDisplayFunc(displayOpenGL); glutMainLoop(); return(0); }