32
Color

Color - sis2430.files.wordpress.com · Teoría del color • El color que vemos en los objetos es resultado de la luz reflejada por su superficie • El negro es la ausencia de color

Embed Size (px)

Citation preview

Color

Teoría del color

• 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

390nm 720 nm

• El color es una longitud de onda de luz, visible para el ojo humano

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

Azul (0,0,1)

R

B

Rojo (1,0,0)

Verde (0,1,0)

Magenta (1,0,1)

Blanco (1,1,1)Cian (0,1,1)

Amarillo (1,1,0)

Negro (0,0,0)

Grises

(x,x,x)

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:

– Modo plano: el color del polígono es el del último vérticeglShadeModel (GL_FLAT)

– Modo interpolado: el color del polígono se deduce a partir del color de cada vérticeglShadeModel (GL_SMOOTH)

G

R

B

// Activa el sombreado suaveglShadeModel (GL_SMOOTH);

// Dibuja el triánguloglBegin (GL_TRIANGLES);

// Vértice rojoglColor3ub (255, 0, 0);glVertex3f (100, 0, 0);

// Vértice verdeglColor3ub (0, 255, 0);glVertex3f (0, 100, 0);

// Vértice azulglColor3ub (0, 0, 255);glVertex3f (0, 0, 100);

glEnd();

G

R

B

• Cambiando a modo de sombreado plano, el triángulo quedaría entero de color azul

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

24 bits

8 bits

• 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

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ámbricoglPolygonMode(GL_FRONT_AND_BACK,GL_LINE);glDisable(GL_CULL_FACE);glDisable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT);

}

// Transformación de vistaglPushMatrix(); gluLookAt (...);

// dibujamos los objetosRenderWorld();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

(1.0, 1.0, 1.0)

(0.5, 0.2, 1.0)

(0.5, 0.2, 1.0)

• En general, la luz emitida es el resultado de la luz que llega, escalada por los coeficientes del material

(lr, lg, lc)

(mr, mg, mb)

(lr*mr, lg*mg, lb*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_AMBIENT

GL_DIFFUSE

GL_SPECULARGL_BACKGL_FRONT_AND_BACK

GL_FRONT

// Activar los cálculos de iluminaciónglEnable (GL_LIGHTING);

// Seleccionar la luz ambienteGLfloat LuzAmbiente[4] = {1.0, 1.0, 0.0, 1.0};glLightModelfv (GL_LIGHT_MODEL_AMBIENT, LuzAmbiente);

// Seleccionar el materialGLfloat MaterialAmbiente[4] = {1.0, 0.5, 0.5, 1.0};glMaterialfv (GL_FRONT, GL_AMBIENT, MaterialAmbiente);

// Dibujar el objetoglBegin (..)

...

...glEnd(); (1, 1, 0)

(1, 0.5, 0.5)

(1, 0.5, 0)

Ejemplo con luz ambiente

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};

glBegin (..)glMaterialfv(GL_FRONT,

GL_AMBIENT, mrojo);...glMaterialfv(GL_FRONT,

GL_AMBIENT, mverde);...

glEnd();

glColorMaterial(GL_FRONT,GL_AMBIENT);

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

Luzincidente 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

Luzincidente Ni

Reflexióndifusa

Reflexiónespecularideal

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])N=<nx, ny, nz>

• Las normales deben tener longitud 1

• Si queremos que OpenGL normalize los vectores automáticamente:

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_DIFFUSE

GL_AMBIENTGL_LIGHT7GL_LIGHT0

GL_LIGHT1

• 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)

GLfloat LuzAmbiente[4] = {0.2, 0.2, 0.2, 1.0};GLfloat LuzDifusa[4] = {1.0, 1.0, 0.0, 1.0};GLfloat PosLuz[4] = {-50, 50., 100, 1.0};GLfloat Material[4] = {1.0, 0.5, 0.5, 1.0};

glEnable (GL_LIGHTING);

// Seleccionar el materialglMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Material);

// Fuente de luzglLightfv (GL_LIGHT0, GL_AMBIENT, LuzAmbiente);glLightfv (GL_LIGHT0, GL_DIFFUSE, LuzDifusa);glLightfv (GL_LIGHT0, GL_POSITION, PosLuz);glEnable (GL_LIGHT0);

glBegin (..) // Dibujar el objetoglNormal3f(...);glVertex3f(...);...glNormal3f(...);

Ejemplo con una fuente de luz difusa

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

GLfloat LuzAmbiente[4] = {0.2, 0.2, 0.2, 1.0};GLfloat LuzEspecular[4] = {1.0, 1.0, 0.0, 1.0};GLfloat PosLuz[4] = {-50, 50., 100, 1.0};GLfloat Material[4] = {1.0, 0.5, 0.5, 1.0};

glEnable (GL_LIGHTING);

// Seleccionar el materialglMaterialfv (GL_FRONT, GL_SPECULAR, Material);glMaterialf (GL_FRONT, GL_SHININESS, 32);

// Fuente de luzglLightfv (GL_LIGHT0, GL_AMBIENT, LuzAmbiente);glLightfv (GL_LIGHT0, GL_POSITION, PosLuz);glEnable (GL_LIGHT0);

glBegin (..) // Dibujar el objetoglNormal3f(...);glVertex3f(...);...glNormal3f(...);

Ejemplo con una fuente de luz especular

Combinando los tres tipos

• La luz en cada vértice se calcula con la siguiente ecuación:

( )∑ +++=luces

needdaaaA kIkIkIkII αθ coscos

N

Luz ambiente global Luz difusa Luz especularLuz ambiente

+

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])

( )∑ ++++=luces

needdaaaAe kIkIkIkIII αθ coscos

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])

NN

Si w!=0, la posición de la fuente es(a,b,c,w) (coord. Homogéneas)

NN N

Si w=0, la dirección de la luz vienedada por el vector <a,b,c>

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:

21

dkdkkf

qlcat ++=

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ónvoid glLightfv (Glenum luz, GL_SPOT_DIRECTION, GLfloat dir[3])

• Para indicar el ángulo de apertura del conovoid 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_SPOT_DIRECTION

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 azulglPushMatrix();

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();

}