Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:ogl [2008/07/08 09:01] alfred |
fw:ogl [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 122: | Línea 122: | ||
| } | } | ||
| </code> | </code> | ||
| + | |||
| Línea 138: | Línea 139: | ||
| * ''glEnable(elemento);'' y ''glDisable(elemento);''. Activa o desactiva el elemento que se pasa por parámetro, si luego queremos saber si ese parámetro está activo tendremos que pasarselo a ''glIsEnabled(elemento);''. El parámetro puede ser cualquiera de los siguientes tipos ya definidos: | * ''glEnable(elemento);'' y ''glDisable(elemento);''. Activa o desactiva el elemento que se pasa por parámetro, si luego queremos saber si ese parámetro está activo tendremos que pasarselo a ''glIsEnabled(elemento);''. El parámetro puede ser cualquiera de los siguientes tipos ya definidos: | ||
| * GL_LINE_STIPPLE: Formato para las GL_LINES. | * GL_LINE_STIPPLE: Formato para las GL_LINES. | ||
| - | * GL_CULL_FACE: Hace que se pinte sólo por la cara de delante. Con esto hacemos uso del //culling//, la técnica de eliminar los polígonos que no van a verse permitiendo así una mejora significante de rendimiento; pero cuidado al dibujar, has de tener en cuenta si has de dibujar en el sentido de las agujas del reloj ''glFrontFace(GL_CCW)'' o no ''glFrontFace(GL_CW)''. | + | * GL_CULL_FACE: Hace que se pinte sólo por la cara de delante. Con esto hacemos uso del //culling//, la técnica de eliminar los polígonos que no van a verse permitiendo así una mejora significante de rendimiento; pero cuidado al dibujar, has de tener en cuenta si has de dibujar en el sentido de las agujas del reloj ''glFrontFace(GL_CCW)'' o no ''glFrontFace(GL_CW)''. Por defecto se dibuja en sentido contrario a las agujas del reloj. |
| * GL_DEPTH_TEST: Elimina las caras ocultas por otras, si no se pone las últimas caras dibujadas (aunque estén por debajo de otras) saldrán por encima. Necesita del parámetro GL_DEPTH_BUFFER_BIT en el glClear. Por lo visto no hay feeling con el GL_CULL_FACE activado. | * GL_DEPTH_TEST: Elimina las caras ocultas por otras, si no se pone las últimas caras dibujadas (aunque estén por debajo de otras) saldrán por encima. Necesita del parámetro GL_DEPTH_BUFFER_BIT en el glClear. Por lo visto no hay feeling con el GL_CULL_FACE activado. | ||
| * GL_LIGHTING: Activa los parámetros de iluminación. | * GL_LIGHTING: Activa los parámetros de iluminación. | ||
| Línea 226: | Línea 227: | ||
| * **Viewport**: El render 2d sobre la ventana. | * **Viewport**: El render 2d sobre la ventana. | ||
| * **Modelview**: La combinación entre las transformaciones de la vista y los modelos (la matriz del modelador). | * **Modelview**: La combinación entre las transformaciones de la vista y los modelos (la matriz del modelador). | ||
| + | |||
| + | |||
| Línea 231: | Línea 234: | ||
| OpenGL utiliza matrices para manejar los datos, existen tres tipos\modos y la elección de este "modo de matriz" se lleva a cabo según el parámetro que le pasemos a ''glMatrixMode'': | OpenGL utiliza matrices para manejar los datos, existen tres tipos\modos y la elección de este "modo de matriz" se lleva a cabo según el parámetro que le pasemos a ''glMatrixMode'': | ||
| * GL_MODELVIEW: Pila de matrices del modelador (para dibujar en escena). | * GL_MODELVIEW: Pila de matrices del modelador (para dibujar en escena). | ||
| - | * GL_PROJECTION: Pila de matrices de la proyección (para definir el volumen de trabajo). | + | * GL_PROJECTION: Pila de matrices de la proyección (para definir el volumen de trabajo). En este modo utilizaremos únicamente las siguientes funciones, no más (la cámara (''gluLookAt'') se utiliza en la MODELVIEW): ''glLoadIdentity, gluPerspective, glFrustum, glOrtho, gluOrtho2''. |
| * GL_TEXTURE: Pila de matrices de textura (coordenadas de textura). | * GL_TEXTURE: Pila de matrices de textura (coordenadas de textura). | ||
| - | |||
| - | |||
| - | |||
| ==== Matriz del modelador (o matriz general) ==== | ==== Matriz del modelador (o matriz general) ==== | ||
| Línea 241: | Línea 241: | ||
| * **Movimiento** con las funciones tipo ''glTranslatef(X,Y,Z);'' | * **Movimiento** con las funciones tipo ''glTranslatef(X,Y,Z);'' | ||
| * **Rotacion** con las funciones tipo ''glRotatef(Angulo, X, Y, Z);'' | * **Rotacion** con las funciones tipo ''glRotatef(Angulo, X, Y, Z);'' | ||
| - | * **Escalado** con las funciones tipo ''glScalef(X,Y,Z);'' \\ | + | * **Escalado** con las funciones tipo ''glScalef(X,Y,Z);''. Esta función no hace nada si se le llama como ''glScalef(1,1,1);'', ya que deja tal cual los polígonos, pero los puedes escalar a la mitad llamandola ''glScalef(0.5,0.5,0.5);'' o invertirla verticalmente ''glScalef(1,-1,1);'' |
| Para reiniciarla, es decir, antes de empezar a dibujar la escena (piena que esta matriz se "deforma" al ir dibujando y colocando los elementos) llamaremos a ''glLoadIdentity()'' que carga la matriz identidad (la inicial). Por lo tanto, para mover dos figuras hacia distinto lugar, aunque generalmente se utiliza la pila de matrices también podemos, primero mover una con glTranslatef y antes de mover la otra reiniciaremos la matriz con ''glLoadIdentity();'' y luego moveremos la otra. | Para reiniciarla, es decir, antes de empezar a dibujar la escena (piena que esta matriz se "deforma" al ir dibujando y colocando los elementos) llamaremos a ''glLoadIdentity()'' que carga la matriz identidad (la inicial). Por lo tanto, para mover dos figuras hacia distinto lugar, aunque generalmente se utiliza la pila de matrices también podemos, primero mover una con glTranslatef y antes de mover la otra reiniciaremos la matriz con ''glLoadIdentity();'' y luego moveremos la otra. | ||
| Línea 323: | Línea 323: | ||
| ===== Proyecciones ===== | ===== Proyecciones ===== | ||
| + | |||
| Línea 328: | Línea 329: | ||
| ==== glOrtho ==== | ==== glOrtho ==== | ||
| - | En el modo de coordenadas ortogonal modo no existe profundidad y los objetos no están dispuestos como si hubiese un punto de fuga. Es decir, los más cercanos no se dibujan más grandes que los más lejanos sino que todos se dibujan con el mismo tamaño, y ni siquiera se dibujan los más cercanos sobre los lejanos, sino por orden de dibujo :?:. El control de coordenadas se hace definiendo la vista con una llamada a ''glOrtho''. \\ | + | En el modo de coordenadas ortogonal modo no existe profundidad y los objetos no están dispuestos como si hubiese un punto de fuga. Es decir, los más cercanos no se dibujan más grandes que los más lejanos sino que todos se dibujan con el mismo tamaño. El control de coordenadas se hace definiendo la vista con una llamada a ''glOrtho''. \\ |
| Su sintaxis es: ''glOrtho(-x,x,-y,y,-z,z);'' y estos parámetros significan: | Su sintaxis es: ''glOrtho(-x,x,-y,y,-z,z);'' y estos parámetros significan: | ||
| * Bits que hay a la izquierda del punto 0,0. | * Bits que hay a la izquierda del punto 0,0. | ||
| Línea 340: | Línea 341: | ||
| <code cpp>glOrtho (0, 3.0f, 0, 3.0f, 0, 3.0f);</code> | <code cpp>glOrtho (0, 3.0f, 0, 3.0f, 0, 3.0f);</code> | ||
| En este el centro de la vista estará en la esquina derecha de la parte de debajo de la ventana (Para OpenGL ese es el punto (0,0)). Sin haber ningún pixel de profundidad entre el usuario y la vista pero desde la vista al fondo de la ventana habrían 3. | En este el centro de la vista estará en la esquina derecha de la parte de debajo de la ventana (Para OpenGL ese es el punto (0,0)). Sin haber ningún pixel de profundidad entre el usuario y la vista pero desde la vista al fondo de la ventana habrían 3. | ||
| + | |||
| + | |||
| + | |||
| Línea 347: | Línea 351: | ||
| Esta proyección se consigue sustituyendo el ''glOrtho'' (proyección ortogonal) por ''gluPerspective'' (habiendo hecho el include a <gl\glu.h>). \\ | Esta proyección se consigue sustituyendo el ''glOrtho'' (proyección ortogonal) por ''gluPerspective'' (habiendo hecho el include a <gl\glu.h>). \\ | ||
| ''gluPerspective'' tiene como parámetros: | ''gluPerspective'' tiene como parámetros: | ||
| - | * angulo visual vertical | + | * angulo visual vertical, a más pequeño más será la relación cerca-grande de los objetos (si está muy bajo, sería como si mirases con unos primáticos). |
| * GLfloat que representa la proporción de altura con anchura (ancho de la vista entre alto). | * GLfloat que representa la proporción de altura con anchura (ancho de la vista entre alto). | ||
| * Comienzo de la vista | * Comienzo de la vista | ||
| Línea 358: | Línea 362: | ||
| gluPerspective(60.0, fAspect, 1.0, 500.0); | gluPerspective(60.0, fAspect, 1.0, 500.0); | ||
| </code> | </code> | ||
| - | Ver [[fw:ogl:xtra#movimiento_de_camaras|relación con la cámara]]. | + | Ver [[fw:ogl:xtra#movimiento_de_camaras|relación con la cámara]]. \\ |
| - | + | Cuando iniciamos el programa y lo configuramos en perspectiva, deberemos definir la cámara con ''gluLookAt''. Si la ventana donde estamos trabajando se reinicia deberemos volver a configurar la perspectiva. Aquí el código para reiniciar la vista: | |
| + | <code cpp> | ||
| + | glMatrixMode(GL_PROJECTION); | ||
| + | glLoadIdentity(); | ||
| + | gluPerspective(this->angle, (float)w / (float)h, 0.1f, lengthView + 0.1f); | ||
| + | glMatrixMode(GL_MODELVIEW); | ||
| + | glLoadIdentity(); | ||
| + | gluLookAt(0.0f, 0.0, -0.2f, 0.0f, 0.0f, lengthView, 0.0f, 1.0f, 0.0f); | ||
| + | </code> | ||
| ===== Iluminación ===== | ===== Iluminación ===== | ||
| Línea 407: | Línea 418: | ||
| - Se la pasamos a la función ''glLightModelfv'' indicandole que es la luz ambiente (GL_LIGHT_MODEL_AMBIENT): ''GlLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbient);'' | - Se la pasamos a la función ''glLightModelfv'' indicandole que es la luz ambiente (GL_LIGHT_MODEL_AMBIENT): ''GlLightModelfv(GL_LIGHT_MODEL_AMBIENT, LuzAmbient);'' | ||
| - Si hemos configurado los materiales correctamente podremos ver la escena como anteriormente la habíamos visto. | - Si hemos configurado los materiales correctamente podremos ver la escena como anteriormente la habíamos visto. | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| Línea 422: | Línea 438: | ||
| Para encontrar la normal de un vértice (normalizar ese vértice), lo que se hace es hacer el [[numbers:maths#producto_cruzado_de_dos_vectores_3d|producto cruzado]] con los otros dos vértices contiguos. \\ | Para encontrar la normal de un vértice (normalizar ese vértice), lo que se hace es hacer el [[numbers:maths#producto_cruzado_de_dos_vectores_3d|producto cruzado]] con los otros dos vértices contiguos. \\ | ||
| {{ fw:ogl:normalizar.png |}} | {{ fw:ogl:normalizar.png |}} | ||
| - | :!: cómo normalizar | ||
| - | === OpenGL y las normales === | ||
| - | Para que OpenGL pueda usa aplicar la normal todas las normales que indiquemos deberán ser vectores unidad (unit normal), esto es, una normal que tenga longitud 1. Para saber qué longitud tiene un vector buscaremos su [[numbers:maths#magnitud_de_un_vector|magnitud]], si queremos conseguir un vector unidad únicamente deberemos dividir cada coordenada del vector entre su magnitud, el vector resultante apuntará al mismo sitio pero tendrá longitud 1. \\ | ||
| + | === Normalizar === | ||
| + | Para un triangulo de 3 puntos (p1, p2 y p3). Para el vector ''U = p2 - p1'' y para el vector ''V = p3 - p1'', el vectro normal sería ''N = U x V'' calculado como: \\ | ||
| + | <m>N_x = (U_y · V_z) - (U_z · V_y)</m> \\ | ||
| + | <m>N_y = (U_z · V_x) - (U_x · V_z)</m> \\ | ||
| + | <m>N_z = (U_x · V_y) - (U_y · V_x)</m> \\ | ||
| + | <code cpp> | ||
| + | void findNormal (floa result[3], float point1[3], float point2[3], float point3[3]) { | ||
| + | GLfloat v1[3],v2[3]; | ||
| + | v1[0] = point1[0] - point2[0]; | ||
| + | v1[1] = point1[1] - point2[1]; | ||
| + | v1[2] = point1[2] - point2[2]; | ||
| + | v2[0] = point2[0] - point3[0]; | ||
| + | v2[1] = point2[1] - point3[1]; | ||
| + | v2[2] = point2[2] - point3[2]; | ||
| + | |||
| + | result[0] = v1[1]*v2[2] - v2[1]*v1[2]; | ||
| + | result[1] = -v1[0]*v2[2] + v2[0]*v1[2]; | ||
| + | result[2] = v1[0]*v2[1] - v2[0]*v1[1]; | ||
| + | } | ||
| + | |||
| + | </code> | ||
| + | Hay que tener especial cuidado en el orden de cálculo, sobretodo si los polígonos han sido dibujados en el orden de las agujas del reloj o no. | ||
| + | === OpenGL y las normales === | ||
| + | Para que OpenGL pueda usa aplicar la normal todas las normales que indiquemos deberán ser vectores unidad (unit normal), esto es, una normal que tenga longitud 1. Para saber qué longitud tiene un vector buscaremos su [[numbers:maths#magnitud_de_un_vector|magnitud]], si queremos conseguir un vector unidad únicamente deberemos dividir cada coordenada del vector entre su magnitud, el vector resultante apuntará al mismo sitio pero tendrá longitud 1. \\ \\ | ||
| + | Aún así, podemos hacer que OpenGL convierta todas las normales a vectores unidad automáticamente utilizando ''glEnable(GL_NORMALIZE);''. Pero esto tiene un problema, si las figuras a las que hemos calculado las normales son escaladas las normales cambiarán, debemos decir a OpenGL que también active el reescalado automático de las normales mediante una función alternativa: ''glEnable(GL_RESCALE_NORMALS);''. \\ \\ | ||
| + | Es decir, lo mejor es indicar, al crear un vértice, la unit normal y activar GL_RESCALE_NORMALS. | ||
| ==== Crear fuentes de luz ==== | ==== Crear fuentes de luz ==== | ||
| Línea 541: | Línea 580: | ||
| ===== Texturas ===== | ===== Texturas ===== | ||
| + | |||
| + | |||
| + | |||
| Línea 608: | Línea 650: | ||
| Una vez tengamos las texturas definidas, ahora debemos de indicar las coordenadas que tendrá la textura. En un cuadrado estas coordenadas son: | Una vez tengamos las texturas definidas, ahora debemos de indicar las coordenadas que tendrá la textura. En un cuadrado estas coordenadas son: | ||
| * Parte alta izquierda: 0.0,1.0 | * Parte alta izquierda: 0.0,1.0 | ||
| - | * Parte alta derecha: 1.0, 1.0 | ||
| * Parte baja izquierda: 0.0, 0.0 | * Parte baja izquierda: 0.0, 0.0 | ||
| - | * Parte baja derecha: 1.0, 0.0 \\ | + | * Parte baja derecha: 1.0, 0.0 |
| + | * Parte alta derecha: 1.0, 1.0 | ||
| Por lo tanto, si a estos valores damos parte alta izquierda (ai) 0.25 0.75, ad 0.75 0.75, bi 0.25 0.25, bd 0.75 0.25, veremos sólo el centro de la textura. \\ | Por lo tanto, si a estos valores damos parte alta izquierda (ai) 0.25 0.75, ad 0.75 0.75, bi 0.25 0.25, bd 0.75 0.25, veremos sólo el centro de la textura. \\ | ||
| Para aplicar estas coordenadas usaremos la función ''glTexCoord2f'' de la siguiente forma: | Para aplicar estas coordenadas usaremos la función ''glTexCoord2f'' de la siguiente forma: | ||
| Línea 628: | Línea 670: | ||
| * GL_TEXTURE_ENV_MODE | * GL_TEXTURE_ENV_MODE | ||
| * Cómo afecta el color: | * Cómo afecta el color: | ||
| - | * GL_MODULATE, a color más claro en la textura más color que se deja ver del polígono. | + | * GL_MODULATE, a color más claro en la textura más color que se deja ver del polígono. Si utilizamos texturas con alpha este flag será necesario. |
| * GL_DECAL, hace que el color de la textura se sobreponga al del polígono (como GL_REPLACE) | * GL_DECAL, hace que el color de la textura se sobreponga al del polígono (como GL_REPLACE) | ||
| * GL_BLEND, hace que los puntos blancos de la textura hagan que esa parte del polígono se transparente, los negros que se vea. Es decir, la textura actua como alfa sobre el polígono. | * GL_BLEND, hace que los puntos blancos de la textura hagan que esa parte del polígono se transparente, los negros que se vea. Es decir, la textura actua como alfa sobre el polígono. | ||
| + | |||
| + | <code cpp> | ||
| + | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); | ||
| + | </code> | ||
| === Uso de mipmaps === | === Uso de mipmaps === | ||
| Línea 789: | Línea 835: | ||
| ===== Efectos ===== | ===== Efectos ===== | ||
| + | |||
| + | |||
| + | |||
| Línea 805: | Línea 854: | ||
| </code> | </code> | ||
| Para que las transparencias surjan efecto GL_DEPTH_TEST y la iluminación, han de estar desactivadas. | Para que las transparencias surjan efecto GL_DEPTH_TEST y la iluminación, han de estar desactivadas. | ||
| + | === La ecuación de Blending === | ||
| + | Para configurar el blending existen varias rutinas, entre ellas: | ||
| + | * ''glBlendFunc'', a la que se le pasan dos parámetros que representan la funciones de blending. GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE | ||
| + | * ''glBlendEquation'' sólo se le pasa un parámetro, correspondiente a la ecuación de blending. | ||
| + | * ''glBlendFuncSeparate'' como ''glBlendFunc'', pero esta última al indicar las funciones estas se aplican a los valores RGBA por igual, con ''glBlendFuncSeparate'' se indican por separado. | ||
| + | * ''glBlendColor'', para indicar el color que OpenGL tomará por valor de alpha (por defecto el 0000). | ||
| + | |||
| + | === Alpha Testing === | ||
| + | Utilizado para decir a OpenGL qué alpha será efectiva y cual no según el color, para que su uso sea efectivo deberemos activar ''GL_ALPHA_TEST'' (cuidado, a veces dará problemas con el blending). Y utilizaremos la función ''glAlphaFunc'' a la cual se le pasa el modo en que actuará y un valor entre 0.0 y 1.0. El modo puede ser: | ||
| + | * GL_NEVER, el color nunca será transparaente. | ||
| + | * GL_ALWAYS, el color siempre será transparente. | ||
| + | * GL_LESS, el color será transparente si es menor al valor dado. | ||
| + | * GL_LEQUAL, el color será transparente si es menor o igual al valor dado. | ||
| + | * GL_EQUAL, el color será transparente si es igual al valor dado. | ||
| + | * GL_GEQUAL, el color será transparente si es mayor o igual al valor dado. | ||
| + | * GL_GREATER, el color será transparente si es mayor al valor dado. | ||
| + | * GL_NOTEQUAL, el color será transparente si no es igual al valor dado. | ||
| ==== Niebla ==== | ==== Niebla ==== | ||
| Línea 920: | Línea 986: | ||
| </code> | </code> | ||
| Define el tamaño del buffer de estarcido. | Define el tamaño del buffer de estarcido. | ||
| + | |||
| Línea 935: | Línea 1002: | ||
| * Tenemos que tener en cuenta que los objetos a los que vaya a transparentar han de haber sido dibujados antes que el transparente. | * Tenemos que tener en cuenta que los objetos a los que vaya a transparentar han de haber sido dibujados antes que el transparente. | ||
| * Sobre qué hacer al cerrar, liberar las propiedades definidas, o cambiar de ventana en OpenGL existe un [[fw:ogl:xtra#fullscreen_y_cambio_de_resolucion|artículo que habla de ello]]. | * Sobre qué hacer al cerrar, liberar las propiedades definidas, o cambiar de ventana en OpenGL existe un [[fw:ogl:xtra#fullscreen_y_cambio_de_resolucion|artículo que habla de ello]]. | ||
| + | * En windows las texturas están enlazadas a la ventana, si la ventana es destruida o no se ha creado todavía, las texturas no se cargarán correctamente. | ||