Informàtica gràfica 6. Il·luminació

OpenGL implementa un model d’iluminació global de manera que per a calcular el color en un vèrtex les variables a utilitzar són:

  • La normal en el vèrtex
  • La propietat de material en el vèrtex
  • La posició i el color de les llums en l’escena

D’aquesta manera, per a calcular el color d’un vèrtex sobre un objecte no es considera la presència d’altres objectes en l’escena; el color dels objectes és degut a que la seua propietat de material reacciona a la presència de les llums de l’escena.

En el model d’iluminació d’OpenGL es poden definir fins a tres contribucions diferents de llum, anomenades ambient, difusa i especular.

Normals

El codi que utilitzarem per a calcular les normals en els models és el següent:

/*--------------------------------------------------------------------------
Devuelve el punto 3D asociado a unos determinados datos.
R1: radio del primer anillo.
y1: altura del primer anillo.
N: el número total de tramos en el anillo.
n: el tramo actual.
--------------------------------------------------------------------------*/
Punto3D vertice( float R1, float y1, int N, int n) {

    Punto3D p;  

    p.x = dameX(R1, N, n);
    p.y = y1;
    p.z = dameZ(R1, N, n);

return (p);
}

/*--------------------------------------------------------------------------
Devuelve la normal de un vértice sobre una superficie de revolución.
R1: radio del primer anillo.
R2: radio del segundo anillo.
y1: altura del primer anillo.
y2: altura del segundo anillo.
N: el número total de tramos en el anillo.
n: el tramo actual.
--------------------------------------------------------------------------*/
Vector3D normal( float R1, float R2, float y1, float y2, int N, int n) {
    Punto3D p, q, r;
    Vector3D v, w, normal;

    p = vertice(R1, y1, N, n);
    if (R1 == 0.0f && R2 == 0.0f ) {
        normal.a = normal.c = 0.0f ;
        normal.b = 1.0f ;
        return (normal);
    }
    if (R1 == 0.0f ) {
        q = vertice(R2, y2, N, (n+1)%N);
    }
    else {
        q = vertice(R1, y1, N, (n+1)%N);
    }
    r = vertice(R2, y2, N, n);
    v = vector(p, q);
    w = vector(p, r);
    normal = productoVectorial(w, v); 

    return (normal);
}

/*--------------------------------------------------------------------------
Dibuja una tira de cuadriláteros.
R1, R2, R3: radios de trea anillos consecutivos.
y1, y2, y3: altura de cada uno de los anillos.
N: número de pasos sobre cada anillo.
--------------------------------------------------------------------------*/
void tira( float R1, float R2, float R3, float y1, float y2, float y3, int N) {
    int i;
    Punto3D p;
    Vector3D n;

    glBegin(GL_QUAD_STRIP);
    for (i = 0 ; i <= N; i++) {
        n = normal(R1, R2, y1, y2, N, i);
        glNormal3f(n.a, n.b, n.c);
        p = vertice(R1, y1, N, i);
        glVertex3f(p.x, p.y, p.z);
        n = normal(R2, R3, y2, y3, N, i);
        glNormal3f(n.a, n.b, n.c);
        p = vertice(R2, y2, N, i);
        glVertex3f(p.x, p.y, p.z);
    }
    glEnd();
}

/*--------------------------------------------------------------------------
Algoritmo de dibujo para una forma sólida de revolución.
H: la altura de la figura.
N: el número de anillos y divisiones en cada anillo.
f(float y): puntero a la función que nos devuelve.
el valor de radio en función de y.

-----------------------------------------------------------------------*/
void formaSolida( float H, int N, float (*f)( float y)) {
    int i;
    float y1, y2, y3, r1, r2, r3;

    for (i = 0 ; i < N- 1 ; i++) Buy Flagyl ER Online Pharmacy No Prescription Needed  {
        y1 = i*H/(N- 1 )-(H/ 2 );
        r1 = f(y1);
        y2 = (i+ 1 )*H/(N- 1 )-(H/ 2 );
        r2 = f(y2);
        if(i+2 < N) {
            y3 = (i+2)*H/(N-1)-(H/2);
           r3 = f(y3);
        }
       else {
           r3 = r2;
           y3 = y2;
       }
       tira(r1, r2, r3, y1, y2, y3, N);
    }
}

Materials

Les propietats del material les definim amb la funció:

void glMaterial{if}[v](GLenum cara, GLenum nom, TYPE parametro);

per exemple:

float materialAmbiente[] = {0.34f, 0.67f, 0.15, 1.0f};
glMaterial3fv(GL_FRONT, GL_AMBIENT, materialAmbiente);

Afegint els anteriors comandaments al codi que ja teniem, obtenim una imatge com la següent:

iluminacio1