Color e iluminación
Transcripción
Color e iluminación
Color Teoría del color • El color es una longitud de onda de luz, visible para el ojo humano 390nm 720 nm • El color que vemos en los objetos es resultado de la luz reflejada por su superficie • El negro es la ausencia de color. Un objeto negro no refleja nada • El blanco es la combinación de todos los colores. Un objeto blanco refleja todas la luz que le llega Las tres componentes del color • El ojo humano tiene tres tipos de células receptoras de luz – el primer tipo se excita más con fotones de longitud de onda rojiza – el segundo tipo se excita más con fotones de longitud de onda verde – el tercer tipo se excita más con fotones de longitud de onda azulada • El cerebro mezcla la combinación de las tres y devuelve un solo color resultado • De esta forma, cualquier color que vemos es en realidad una combinación de ondas con longitudes dentro del espectro visible Espacio de color • Es un espacio 3D cuyas dimensiones son las componentes R, G y B • Variando cada eje entre 0 y 1 obtenemos el cubo de color, que incluye todos los colores visibles al ojo humano G Verde (0,1,0) Amarillo (1,1,0) Blanco (1,1,1) Cian (0,1,1) G s( e s ri x) x, , x Negro (0,0,0) Rojo (1,0,0) R Azul (0,0,1) B Magenta (1,0,1) Sombreado de polígonos • Para definir el color activo (con el que se pintan los vértices) se usa: void glColor3f (GLfloat rojo, GLfloat verde, GLfloat azul) void glColor3ub (GLfloat rojo, GLfloat verde, GLfloat azul) • Si todos los vértices tienen el mismo color, todo el polígono es constante • Si cada vértice tiene un color diferente, el color del interior del polígono dependerá del modo de sombreado elegido: G – Modo plano: el color del polígono es el del último vértice glShadeModel (GL_FLAT) – Modo interpolado: el color del polígono se deduce a partir del color de cada vértice R glShadeModel (GL_SMOOTH) B G // Activa el sombreado suave glShadeModel (GL_SMOOTH); // Dibuja el triángulo glBegin (GL_TRIANGLES); R B • Cambiando a modo de sombreado plano, el triángulo quedaría entero de color azul // Vértice rojo glColor3ub (255, 0, 0); glVertex3f (100, 0, 0); // Vértice verde glColor3ub (0, 255, 0); glVertex3f (0, 100, 0); // Vértice azul glColor3ub (0, 0, 255); glVertex3f (0, 0, 100); glEnd(); 24 bits Bits de color • Si el sistema operativo no puede mostrar 24 bits color, éste busca los colores más adecuados --> no es preciso cambiar el código! • Lógicamente, la calidad de la imagen será diferente • Si el número de bits color es pequeño, podemos indicarle a OpenGL que use tramas para aproximar el color real: glEnable (GL_DITHER); 8 bits con dithering 8 bits Modo indexado de color • OpenGL también permite trabajar directamente con la paleta de color, en lugar de usar las componentes RGB • Para establecer el color activo se usa: void glIndexi (GLint indice); • Ventajas del modo indexado: – es más rápido (sólo se utiliza un valor por pixel) – permite animaciones de paleta – permite usar el color para indicar otra magnitud • Desventajas – no permite efectos de iluminación Ejemplo: navegador 3D en color void PanelVista_Paint(TObject *Sender) { switch (ModoColor) { case 2: // modo sólido glPolygonMode(GL_FRONT,GL_FILL); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); break; case 1: // modo alámbrico glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT); } // Transformación de vista glPushMatrix(); gluLookAt (...); // dibujamos los objetos RenderWorld(); glPopMatrix(); } Iluminación Luz ambiente • Es la luz que no viene de ninguna dirección particular • Aunque provenga de una fuente, después de múltiples rebotes por la escena ha perdido la direccionalidad • Los objetos iluminados por esta luz la reciben de igual manera en todas sus superficies y en todas direcciones Materiales • En el mundo real, los objetos tienen color por sí mismos • El color del material se define según las longitudes de onda que refleje • • Bajo una luz blanca, los objetos aparecen con sus colores naturales En general, la luz emitida es el resultado de la luz que llega, escalada por los coeficientes del material (1.0, 1.0, 1.0) (0.5, 0.2, 1.0) (0.5, 0.2, 1.0) (lr, lg, lc) (lr*mr, lg*mg, lb*mb) (mr, mg, mb) Luz ambiente con OpenGL • Para indicar a OpenGL que ha de realizar los cálculos de iluminación: glEnable (GL_LIGHTING) • Para seleccionar el modelo de iluminación ambiente activo: void glLightModelfv (GL_LIGHT_MODEL_AMBIENT, GLfloat params[4]) • Para establecer el material activo: void glMaterialfv (Glenum cara, Glenum nombre, GLfloat params[4]) GL_BACK GL_SPECULAR GL_FRONT_AND_BACK GL_DIFFUSE GL_FRONT GL_AMBIENT Ejemplo con luz ambiente // Activar los cálculos de iluminación glEnable (GL_LIGHTING); // Seleccionar la luz ambiente GLfloat LuzAmbiente[4] = {1.0, 1.0, 0.0, 1.0}; glLightModelfv (GL_LIGHT_MODEL_AMBIENT, LuzAmbiente); // Seleccionar el material GLfloat MaterialAmbiente[4] = {1.0, 0.5, 0.5, 1.0}; glMaterialfv (GL_FRONT, GL_AMBIENT, MaterialAmbiente); // Dibujar el objeto glBegin (..) ... ... glEnd(); (1, 1, 0) (1, 0.5, 0) (1, 0.5, 0.5) Otra forma de definir el material • Si un objeto tiene diferentes materiales, sería muy tedioso declarar muchos vectores RGBA y llamar a glMaterialfv en cada polígono • Otra opción más cómoda es usar: void glColorMaterial (Glenum cara, Glenum nombre) • Ahora, las llamadas a glColor en realidad sirven para definir el material GLfloat mrojo[4]= {1,0,0,1}; GLfloat mverde[4]={0,1,0,1}; glColorMaterial(GL_FRONT, GL_AMBIENT); glBegin (..) glMaterialfv(GL_FRONT, GL_AMBIENT, mrojo); ... glMaterialfv(GL_FRONT, GL_AMBIENT, mverde); ... glEnd(); glBegin (..) glColor3f(1,0,0); ... glColor3f(0,1,0); ... glEnd(); Luz difusa • La fuente tiene una localización y una dirección particular • Una vez toca la superficie del objeto, se refleja en todas direcciones Luz incidente Ni Luz especular • También es direccional, pero el reflejo se produce en una dirección concreta • Produce un punto brillante en la superficie que ilumina --> reflejo especular Luz incidente Ni Reflexión especular ideal Reflexión difusa Fuentes de luz con OpenGL • Soporta hasta 8 fuentes de luz independientes • La iluminación del polígono dependerá de los ángulos A y B A B • Estos ángulos se usan en conjunción con la iluminación y las propiedades de los materiales para obtener el color de cada vértice • A partir del color de los vértices, se interpola el interior de los polígonos Vectores normales • Para obtener los ángulos hay que conocer la normal a la superficie • Para especificar la normal activa: void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz) void glNormal3fv (GLfloat n[3]) • Las normales deben tener longitud 1 • Si queremos que OpenGL normalize los vectores automáticamente: N=<nx, ny, nz> glEnable (GL_NORMALIZE) • Las normales pueden calcularse de varias maneras – promediando entre las normales de los polígonos adyacentes – a partir de la expresión analítica de la superficie Luz difusa con OpenGL • Para trabajar con luz difusa hay que crear una fuente de luz • Para indicar el color de la fuente de luz: void glLightfv (Glenum luz, Glenum nombre, GLfloat color[4]) GL_LIGHT0 GL_LIGHT7 GL_LIGHT1 • GL_AMBIENT GL_DIFFUSE Para indicar la posición de la fuente de luz: void glLightfv (Glenum luz, GL_POSITION, GLfloat pos[4]) • Para activar la fuente de luz: glEnable (Glenum luz) Ejemplo con una fuente de luz difusa GLfloat GLfloat GLfloat GLfloat LuzAmbiente[4] LuzDifusa[4] PosLuz[4] Material[4] = = = = {0.2, {1.0, {-50, {1.0, 0.2, 1.0, 50., 0.5, 0.2, 0.0, 100, 0.5, 1.0}; 1.0}; 1.0}; 1.0}; glEnable (GL_LIGHTING); // Seleccionar el material glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Material); // Fuente de luz glLightfv (GL_LIGHT0, GL_AMBIENT, LuzAmbiente); glLightfv (GL_LIGHT0, GL_DIFFUSE, LuzDifusa); glLightfv (GL_LIGHT0, GL_POSITION, PosLuz); glEnable (GL_LIGHT0); glBegin (..) // Dibujar el objeto glNormal3f(...); glVertex3f(...); ... glNormal3f(...); Luz especular con OpenGL • Se usa para simular superficies metálicas • Para indicar el color de la fuente de luz: void glLightfv (Glenum luz, GL_SPECULAR, GLfloat color[4]) • Para indicar el exponente de reflexión especular: void glLightf (Glenum luz, GL_SHININESS, GLfloat coef) donde 0<coef<128 coef=128 coef=32 coef=2 Ejemplo con una fuente de luz especular GLfloat GLfloat GLfloat GLfloat LuzAmbiente[4] LuzEspecular[4] PosLuz[4] Material[4] = = = = {0.2, {1.0, {-50, {1.0, 0.2, 1.0, 50., 0.5, 0.2, 0.0, 100, 0.5, 1.0}; 1.0}; 1.0}; 1.0}; glEnable (GL_LIGHTING); // Seleccionar el material glMaterialfv (GL_FRONT, GL_SPECULAR, Material); glMaterialf (GL_FRONT, GL_SHININESS, 32); // Fuente de luz glLightfv (GL_LIGHT0, GL_AMBIENT, LuzAmbiente); glLightfv (GL_LIGHT0, GL_POSITION, PosLuz); glEnable (GL_LIGHT0); glBegin (..) // Dibujar el objeto glNormal3f(...); glVertex3f(...); ... glNormal3f(...); Combinando los tres tipos • La luz en cada vértice se calcula con la siguiente ecuación: I = I Aka + ∑ (I a ka + I d kd cos θ + I e ke cosn α ) luces Luz ambiente global Luz ambiente + N Luz difusa Luz especular Objetos emisores de luz • Además de la luz que refleja un objeto, éste puede emitir luz propia • Para indicar el color de luz emitida por un objeto: void glMaterialfv (Glenum cara, GL_EMISSION, GLfloat color[4]) I = I e + I Aka + ∑ (I a ka + I d kd cos θ + I e ke cos α ) n luces Luz emitida • Este término no afecta al resto de objetos • En ese caso, habría que crear una fuente de luz en la misma posición del objeto Posición de una fuente • Si la fuente de luz está muy lejana -> fuente de luz direccional – los rayos de luz son todos paralelos – el ángulo con la normal es constante en todo el interior de un polígono • Para indicar si la fuente es direccional o posicional: GLfloat pos[4] = {a, b, c, w}; void glLightfv (Glenum luz, GL_POSITION, GLfloat pos[4]) Si w!=0, la posición de la fuente es (a,b,c,w) (coord. Homogéneas) N N Si w=0, la dirección de la luz viene dada por el vector <a,b,c> N N N Atenuación de una fuente • En la realidad, la intensidad de una fuente decrece con la distancia d • OpenGL usa un factor de atenuación dado por la ecuación: 1 f at = kc + kl d + k q d 2 glLightf (GLenum luz, GL_CONSTANT_ATTENUATION, GLfloat kc) glLightf (GLenum luz, GL_LINEAR_ATTENUATION, GLfloat kl) glLightf (GLenum luz, GL_QUADRATIC_ATTENUATION, GLfloat kq) • El factor de atenuación no afecta a: – el valor de emisión de los objetos – la luz ambiente global – las fuentes direccionales Focos de luz • Con un foco de luz, decidimos en qué dirección se radia la luz • Para indicar la dirección void glLightfv (Glenum luz, GL_SPOT_DIRECTION, GLfloat dir[3]) • Para indicar el ángulo de apertura del cono void glLightfv (Glenum luz, GL_SPOT_CUTOFF, GLfloat grados) • Para indicar la atenuación de la luz al alejarnos de la dirección central void glLightfv (Glenum luz, GL_SPOT_EXPONENT, GLfloat exp) GL_SPOT_CUTOFF GL_ SPO T_D IRE C TIO N Moviendo las luces • Las fuentes de luces también son transformadas por la matriz de modelado GLfloat Pos[4]={0,0,75,1}, Dir[3]={0,0,-1}; // limpio pantalla y dibujo la esfera azul glPushMatrix(); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glLightfv(GL_LIGHT0,GL_POSITION,Pos); glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,Dir); glTranslatef(Pos[0],Pos[1],Pos[2]); glColor3ub(255,0,0); auxSolidCone(4.0f,6.0f); glDisable(GL_LIGHTING); glColor3ub(255,255,0); auxSolidSphere(3.0f); glEnable(GL_LIGHTING); glPopMatrix(); Ejemplo: navegador 3D con iluminación void PanelVista_Paint(TObject *Sender) { switch (ModoColor) { case 3: // modo iluminación glEnable (GL_LIGHTING); glLightfv (GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, Luz); glLightfv (GL_LIGHT0, GL_POSITION, LuzPos); glEnable (GL_LIGHT0); glEnable (GL_COLOR_MATERIAL); glColorMaterial (GL_FRONT, GL_AMBIENT_AND_DIFFUSE); } glPushMatrix(); glLightfv (GL_LIGHT1, GL_DIFFUSE, FocoLuz); glLightfv (GL_LIGHT1, GL_POSITION, FocoPos); glLightfv (GL_LIGHT1, GL_SPOT_DIRECTION, FocoDir); glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.00001); glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 20); glEnable (GL_LIGHT1); gluLookAt (...); RenderWorld(); glPopMatrix(); }
Documentos relacionados
cuadrics - WordPress.com
GLfloat light_Ambient [4] = { 0.4, 0.4, 0.4, 1.0}; GLfloat light_Diffuse [4] = { 0.7, 0.7, 0.7, 1.0}; GLfloat light_Position [4] = {20.0, 15.0, 10.0, 1.0}; GLfloat GLfloat GLfloat GLfloat GLfloat G...
Más detalles