En aquest article extendrem la biblioteca d’objectes per a dibuixar objectes poligonals, eliminarem les parts ocultes i les cares de darrere i realçarem les aristes per a donar als objectes aparença de volum.
Primitives poligonals
Fins ara hem dibuixat els objectes usant només un conjunt d’anells. El que anem a fer ara és dibuixar les mateixes primitives però com una superfície formada per polígons.
La idea bàsica és que ara dibuixarem tires de quadrilàters com els de la següent figura:

on els vèrtex parells estaran tots a la mateixa altura (en el mateix anell), i els senars a una distinta (en l’anell superior)
Ara utilitzarem cintes en lloc de tires (que utilitzavem per a fer anells), segons el següent codi:
void cinta(float R, float dR, float y, float dy, float N) {
int i;
float x, z;
glBegin(GL_QUAD_STRIP);
for(i = 0; i <= N; i++) {
x = dameX(R, N, i);
z = dameZ(R, N, i);
glVertex3f(x, y, z);
x = dameX(R+dR, N, i);
z = dameZ(R+dR, N, i);
glVertex3f(x, y+dy, z);
}
glEnd();
}
I el codi per a dibuixar una forma sòlida utilitzant tires serà el següent:
void formaSolida(float H, int N, float(*f)(float y)) {
int i;
float y, r1, r2;
for(i = 0; i < N; i++) {
y = i*H/N-(H/2);
r1 = f(y);
r2 = f(y+(H/N));
cinta(r1, r2-r1, y, H/N, N);
}
}
En la següent imatge veiem un cilindre sòlid:
Si ens fixem veiem que només hem dibuixat el contorn, necessitem també la tapa superior i la tapa inferior per a que siga un cilindre completament sòlid com aquest:
Per al que hem utilitzat el següent codi:
void tapa(float R, float y, int N) {
int i;
float x, z;
glBegin(GL_POLYGON);
for(i = 0; i < N; i++) {
x = dameX(R, N, i);
z = dameZ(R, N, i);
glVertex3f(x, y, z);
}
glEnd();
}
float fCilindro(float y) {
return(0.5);
}
void cilindroSolido(int N) {
formaSolida(1.0f, N, fCilindro);
tapa(fCilindro(0.5), 0.5, N);
tapa(fCilindro(0.5), -0.5, N);
}
Eliminació de parts ocultes i cares de darrere
Al dibuixar superfícies és important que les que estiguen més a prop de l'observador oculten les que estan més llunyanes, i que aquesta ocultació siga independent de l'ordre en que es dibuixen les superfícies.
OpenGL implementa un algorisme d'ocultació basat en un buffer de profunditat (z-buffer). Per a utilitzar-lo hem d'aplicar els següents comandaments:
- Indicar que l'aplicació OpenGL va a utilitzar el z-buffer:
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
- Activar el test de profunditat:
glEnable(GL_DEPTH_TEST);
- Cada vegada que anem a dibuixar l'escena, a més d'esborrar el buffer de color, haurem d'esborrar el buffer de profunditat:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
I d'altra banda, podem eliminar les cares de darrere ja que aquestes no les veurem i les estem dibuixant; d'aquesta manera estalviarem un temps de càlcul que no es reflexarà en la imatge final. Aquesta tècnica s'anomena back-face culling.
Només hem d'utilitzar els següents comandaments d'OpenGL:
glFrontFace(GL_CW); /* GL_CW indica que són les cares els vèrtex de les quals estan definits en el sentit de les agulles del rellotge; GL_CCW al contrari */ glCullFace(GL_FRONT); /* També GL_BACK i GL_FRONT_AND_BACK */ glEnable(GL_CULL_FACE);
Realçat d'aristes
Per a que els objectes ens donen sensació de profunditat ara que encara no estem utilitzant la iluminació ni les textures, necessitem dibuixar les cares i també les aristes; simplement dibuixarem els nostres objectes dos vegades, en la primera passada com a polígons i en la segona només les aristes de les cares, com per exemple el següent codi:
// Primera passada, dibuixem polígons glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_POLYGON_OFFSET_FILL); glPolygonOffset(1.0, 1.0); Objecte(); // Segona passada, dibuixem aristes glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_POLYGON_OFFSET_FILL); Objecte();
El codi que ens quedaria a l'afegir els anteriors comandaments seria el següent:

