Informàtica gràfica 0. Introducció

Des que ho vaig estudiar a la universitat la meua visió sobre els videojocs, animació per computador, simuladors… ha canviat considerablement. Informàtica gràfica només era una assignatura optativa que els primers cursos no m’atreia però després de conèixer l’opinió d’alguns companys vaig decidir cursar-la. I realment em va fascinar i va canviar la manera de veure aquest món.

Com que ja fa un temps que estic interessat en xarrar una mica sobre l’assumpte en plan pràctic i tal, per exemple en alguna Lan Party i pareix ser que no hi haja massa seguidors, he decidit postejar setmanalment un conjunt de xicotets articles sobre el tema (també per a donar vida a aquest moribund bloc…). Bàsicament consistents en les diferents pràctiques que vaig fer en el seu dia per a superar l’assignatura.

La llibreria que usarem és OpenGL i la biblioteca de funcions glut. OpenGL es una llibreria formada per uns cent vint comandaments aproximadament; entre les principals accions que podem realitzar s’inclouen l’especificació dels objectes i operacions necessàries per a produïr aplicacions interactives en 3D. S’ha dissenyat de forma independent del hardware de suport per a ser implementat sobre diferents plataformes; per això no hi han comandaments per a executar tasques dependents del hardware com per exemple la gestió de finestres o la lectura de dades d’entrada de l’usuari; tampoc proveeix comandaments d’alt nivell per a descriure models en 3D, de manera que el model ha de construïr-se a partir de primitives geomètriques simples com punts, línies i polígons.

Per exemple, amb aquest codi que podeu baixar d’ací (dof.c)


#include "GL/glut.h"
#include "stdlib.h"
#include "math.h"
#include "jitter.h"

#ifdef WIN32
#define near zNear
#define far zFar
#endif

#define PI_ 3.14159265358979323846

GLuint teapotList;

void accFrustum(GLdouble left, GLdouble right, GLdouble bottom,
   GLdouble top, GLdouble near, GLdouble far, GLdouble pixdx,
   GLdouble pixdy, GLdouble eyedx, GLdouble eyedy, GLdouble focus)
{
   GLdouble xwsize, ywsize;
   GLdouble dx, dy;
   GLint viewport[4];

   glGetIntegerv (GL_VIEWPORT, viewport);

   xwsize = right - left;
   ywsize = top - bottom;

   dx = -(pixdx*xwsize/(GLdouble) viewport[2] + eyedx*near/focus);
   dy = -(pixdy*ywsize/(GLdouble) viewport[3] + eyedy*near/focus);

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum (left + dx, right + dx, bottom + dy, top + dy, near, far);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef (-eyedx, -eyedy, 0.0);
}

void accPerspective(GLdouble fovy, GLdouble aspect,
   GLdouble near, GLdouble far, GLdouble pixdx, GLdouble pixdy,
   GLdouble eyedx, GLdouble eyedy, GLdouble focus)
{
   GLdouble fov2,left,right,bottom,top;

   fov2 = ((fovy*PI_) / 180.0) / 2.0;

   top = near / (cos(fov2) / sin(fov2));
   bottom = -top;

   right = top * aspect;
   left = -right;

   accFrustum (left, right, bottom, top, near, far,
               pixdx, pixdy, eyedx, eyedy, focus);
}

void init(void)
{
   GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
   GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 };

   GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
   GLfloat local_view[] = { 0.0 };

   glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
   glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
   glLightfv(GL_LIGHT0, GL_POSITION, position);

   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
   glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

   glFrontFace (GL_CW);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_AUTO_NORMAL);
   glEnable(GL_NORMALIZE);
   glEnable(GL_DEPTH_TEST);

   glClearColor(0.0, 0.0, 0.0, 0.0);
   glClearAccum(0.0, 0.0, 0.0, 0.0); 

   teapotList = glGenLists(1);
   glNewList (teapotList, GL_COMPILE);
   glutSolidTeapot (0.5);
   glEndList ();
}

void renderTeapot (GLfloat x, GLfloat y, GLfloat z,
   GLfloat ambr, GLfloat ambg, GLfloat ambb,
   GLfloat difr, GLfloat difg, GLfloat difb,
   GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
{
   GLfloat mat[4];

   glPushMatrix();
   glTranslatef (x, y, z);
   mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;
   glMaterialfv (GL_FRONT, GL_AMBIENT, mat);
   mat[0] = difr; mat[1] = difg; mat[2] = difb;
   glMaterialfv (GL_FRONT, GL_DIFFUSE, mat);
   mat[0] = specr; mat[1] = specg; mat[2] = specb;
   glMaterialfv (GL_FRONT, GL_SPECULAR, mat);
   glMaterialf (GL_FRONT, GL_SHININESS, shine*128.0);
   glCallList(teapotList);
   glPopMatrix();
}

void display(void)
{
   int jitter;
   GLint viewport[4];

   glGetIntegerv (GL_VIEWPORT, viewport);
   glClear(GL_ACCUM_BUFFER_BIT);

   for (jitter = 0; jitter < 8; jitter++) {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      accPerspective (45.0,
         (GLdouble) viewport[2]/(GLdouble) viewport[3],
         1.0, 15.0, 0.0, 0.0,
         0.33*j8[jitter].x, 0.33*j8[jitter].y, 5.0);

/*	ruby, gold, silver, emerald, and cyan teapots	*/
      renderTeapot (-1.1, -0.5, -4.5, 0.1745, 0.01175,
                    0.01175, 0.61424, 0.04136, 0.04136,
                    0.727811, 0.626959, 0.626959, 0.6);
      renderTeapot (-0.5, -0.5, -5.0, 0.24725, 0.1995,
                    0.0745, 0.75164, 0.60648, 0.22648,
                    0.628281, 0.555802, 0.366065, 0.4);
      renderTeapot (0.2, -0.5, -5.5, 0.19225, 0.19225,
                    0.19225, 0.50754, 0.50754, 0.50754,
                    0.508273, 0.508273, 0.508273, 0.4);
      renderTeapot (1.0, -0.5, -6.0, 0.0215, 0.1745, 0.0215,
                    0.07568, 0.61424, 0.07568, 0.633,
                    0.727811, 0.633, 0.6);
      renderTeapot (1.8, -0.5, -6.5, 0.0, 0.1, 0.06, 0.0,
                    0.50980392, 0.50980392, 0.50196078,
                    0.50196078, 0.50196078, .25);
      glAccum (GL_ACCUM, 0.125);
   }
  Buy Viagra Professional Online Pharmacy No Prescription Needed   glAccum (GL_RETURN, 1.0);
   glFlush();
}

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
}

void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB
			| GLUT_ACCUM | GLUT_DEPTH);
   glutInitWindowSize (400, 400);
   glutInitWindowPosition (100, 100);
   glutCreateWindow (argv[0]);
   init();
   glutReshapeFunc(reshape);
   glutDisplayFunc(display);
   glutKeyboardFunc(keyboard);
   glutMainLoop();
   return 0;
}

Amb l’anterior codi obtindriem uns teapots tant xulos com aquestos:

dof.jpg

Amb el codi que us proposo ací podem muntar una escena com aquesta (podeu baixar l’executable ací, funciona amb windows amb les llibreríes correctament instalades):

Comments (5)

  1. Javi wrote:

    Que xulo! La veritat és que pinta bé, intentaré seguir-lo… Aixi que t’agrairia que tinguera en compte la ignorància d’alguns de nosaltres…

    Ànim!

    PD: Quina llicència té? Ho dic perquè un tutorial d’este estil té tot el que cal per a convertir-se en un wikibook!

    Monday, December 1, 2008 at 11:58 #
  2. Javi wrote:

    Per cert… què hauria de tindre instalat per a compilar?? Serà això el 1r article?

    Monday, December 1, 2008 at 12:09 #
  3. david wrote:

    Si, el punt 1. va sobre preparar l’entorn de treball… Pero bé, pots anar trastejant si vols, només necessites un compilador (resposta obvia :)) de C++. Per a güindous, em pareix que aquest entorn de treball http://sourceforge.net/projects/dev-cpp/ inclou també el compilador… A més, per a que funcione suposo que hauràs d’instal·lar la llibreria OpenGL i la biblioteca glut, també pots anar mirant si vols com instalar-ho… Una vegada instal·lat, només has de crear un nou projecte i pots provar el codi de dalt de les teapots per exemple per comprovar que funciona…

    El següent article va una mica sobre això, encara que no em pararé molt a descriure com preparar l’entorn, ja que es una tasca que sol portar problemes derivats del sistema operatiu i l’entorn de desenvolupament que use cadascú; i ara mateix no recordo com ho vaig configurar jo tot en el seu dia, ja fa molt de temps… La idea és que qui vullga ho intente i consulte dubtes en els comentaris…

    Intentaré fer-ho per a tots els públics, la idea és que siga en plan introducció pero dureta, analitzant una mica de codi i tal…, ja vorem…, consulteu tots els dubtes!

    Tuesday, December 2, 2008 at 11:51 #
  4. Agustí wrote:

    Avuí entro al teu blog i veig la entrada de OpenGL. Jo també vaig fer la optativa de Informàtica Gràfica 1 i ens vam picar uns quants companys q veure qui feia millor el projecte.
    Per a qualsevol que vullga començar recomano que es miri el Llibre Roig de OpenGL
    http://fly.cc.fer.hr/~unreal/theredbook/

    Estaría be que diferenciesis que es OpenGL i que es GLUT, sent esta última l’encarregat de crear la finestra i de capturar els events que produeixen el teclat, ratolí ademes de que totes les funcions comencen per glut, mentre que en OpenGL comencen amb gl.

    I ja posats aci teniu el projecte que vaig fer:
    http://www.megaupload.com/es/?d=EW0ACDX8
    Només tinc el codi, però no crec que doni problemes per a compilar…

    PD. M’agrada l’efecte de profunditat de camp en l’exemple.
    PD2. Supose que eixe parc es el projecte que vas fer per a l’assignatura, no?

    Tuesday, December 2, 2008 at 19:54 #
  5. david wrote:

    Ei Agustí, com va? M’alegre de tindre notícies teues!

    La idea no és entrar massa en detalls de OpenGL i glut, més bé seria explicar una mica els passos que seguim per a modelar figures en 3D… efectivament si algú n’està interessat en aprendre aquestes llibreries, pues pot usar l’enllaç que proposes o preguntar en els comentaris… Això si, aniré deixant codi i potser el comente una mica, encara que sense parlar massa directament sobre els comandaments de OpenGL o glut…

    El parc és el projecte que vaig fer jo, que en els inicis era molt ambiciós i finalment va quedar passable, sense massa virgueríes… Per cert, he conseguit compilar el teu codi llevant els .md* ja que en xcode tinc problemes al carregar fitxers externs, també les textures .tga…; bé, finalment alguna cosa he pogut vore del teu projecte, té bona pinta!

    Salutacions!

    Wednesday, December 3, 2008 at 2:26 #