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

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