{
Jaja, estas dos lecciones se tradujeron hace mucho tiempo, pero aún no se han publicado. Todos han estado esperando durante mucho tiempo (¿Alguien está esperando más?)
transparencia simple
La gran mayoría de los efectos especiales en OpenGL están relacionados con algún tipo de mezcla (de colores).
La mezcla de colores se define como combinar el color de un determinado píxel con el color de su correspondiente píxel dibujado en la pantalla.
La forma en que se combinan los dos colores depende de los valores de los componentes del canal alfa del color y/o de la función de mezcla de colores utilizada.
Alfa suele ser el cuarto componente de color al final del valor del color.
En las lecciones anteriores usamos GL_RGB para especificar los tres componentes del color.
El GL_RGBA correspondiente puede especificar el valor del componente alfa.
Yendo un paso más allá, podemos usar glColor4f() en lugar de glColor3f().
La mayoría de la gente está de acuerdo en que el componente Alfa representa la transparencia de un material.
Esto significa que un valor alfa de 0,0 representa un material completamente transparente.
Un valor alfa de 1,0 representa un material completamente opaco.
fórmula de mezcla de colores
Si no estás interesado en las matemáticas y solo quieres ver cómo lograr transparencia, omite esta sección.
Si desea comprender mejor cómo funciona la mezcla (de colores), esta sección debería ser para usted.
『Adición de CKER: En realidad no es difícil^-^. La fórmula del artículo original es la siguiente, dejemos que CKER hable de ello nuevamente.
De hecho, el principio básico de la mezcla es separar el color de cada píxel y el color de fondo de la imagen de acuerdo con las reglas RGB.
Según - componente de color RGB de la imagen * valor alfa + componente de color RGB del fondo * (valor 1-alfa)
-Después de mezclar con una fórmula tan simple, los componentes RGB obtenidos mediante la mezcla finalmente se vuelven a fusionar. 』
La fórmula es la siguiente:
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL calcula el resultado de la mezcla de colores de estos dos píxeles de acuerdo con la fórmula anterior.
La s y la r minúsculas representan los píxeles de origen y los píxeles de destino, respectivamente. La S y la D mayúsculas son los factores de mezcla de colores correspondientes.
Estos determinan cómo se mezclan los colores de esos píxeles.
En la mayoría de los casos, los valores de mezcla alfa de cada canal de color son los mismos.
De esta manera, tenemos (As, As, As, As) para el píxel de origen,
Los píxeles de destino son 1, 1, 1, 1) - (As, As, As, As).
La fórmula anterior se convierte en la siguiente:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))
Esta fórmula produce un efecto transparente/translúcido.
Mezcla de colores en OpenGL
Los pasos para implementar la mezcla de colores en OpenGL son similares al proceso OpenGL que mencionamos antes.
Luego configure la fórmula y desactive el caché de profundidad de escritura al dibujar objetos transparentes.
Porque queremos dibujar el objeto detrás de una forma semitransparente.
Esta no es la forma correcta de mezclar colores, pero la mayoría de las veces funciona bien en proyectos simples.
Añadido de Rui Martins: El proceso correcto de mezcla de colores debería ser dibujar primero la escena completa y luego dibujar los gráficos transparentes.
Y se dibujan en orden inverso al búfer de profundidad (los objetos más lejanos se dibujan primero).
Considere la combinación alfa de dos polígonos (1 y 2). Diferentes órdenes de dibujo darán resultados diferentes.
(Aquí se supone que el polígono 1 está más cerca del observador, entonces el proceso correcto debería dibujar el polígono 2 primero y luego el polígono 1.
Como puedes ver en la realidad,
La luz que viene detrás de estos dos polígonos <transparentes> siempre pasa primero por el polígono 2.
Luego pasa por el polígono 1 y finalmente llega a los ojos del observador. )
Cuando el almacenamiento en caché de profundidad está habilitado, debe ordenar los gráficos transparentes por profundidad,
Y dibuje estos objetos transparentes después de dibujar todas las escenas. De lo contrario obtendrá resultados incorrectos.
Sé que algunas veces es doloroso hacer esto, pero es la forma correcta de hacerlo.
Usaremos el código de la Lección 7.
Comience agregando dos nuevas variables al comienzo del código. Reescribí todo el código para mayor claridad.
}
var
h_RC: HGLRC; // Contexto de representación (tabla de descripción de sombreado).
h_DC: HDC // Contexto del dispositivo (tabla de descripción del dispositivo)
h_Wnd: HWND // identificador de ventana
h_Instance: HINST; // Instancia del programa (instancia).
teclas: Array[0..255] Of Boolean; // Matriz para rutinas de teclado
luz: booleano; // fuente de luz encendida/apagada
mezcla: booleano; // ¿Mezcla desactivada/activada (nueva)
lp: Booleano; // ¿Está presionada la tecla L?
fp: booleano; // ¿Se presiona la tecla F?
bp: booleano; // ¿Se presiona la tecla B? (Nuevo)
xrot: GLfloat; // rotación X
yrot: GLfloat; // rotación Y
xspeed: GLfloat; // X velocidad de rotación
yspeed: GLfloat; // velocidad de rotación Y
z : GLfloat = -5.0 f // Distancia profunda en la pantalla
LightAmbient: Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0); //Parámetros de luz ambiental (nuevo)
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0); // Parámetros de luz difusa (nuevo)
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0); // Posición de la fuente de luz (nueva)
filtro: GLuint; // tipo de filtro
textura: Array[0..2] de GLuint // Espacio de almacenamiento para 3 texturas
Procedimiento glGenTextures(n: GLsizei; Var texturas: GLuint external);
opengl32;
Procedimiento glBindTexture(destino: GLenum; textura: GLuint externo);
opengl32;
Función gluBuild2DMipmaps(objetivo: GLenum; componentes, ancho, alto: GLint;
formato, tipo a: GLenum; datos: Puntero): Entero; nombre estándar de glu32;
'gluBuild2DMipmaps';
{
Luego baje a LoadGLTextures().
Buscar si (TextureImage[0]=LoadBMP('Data/Crate.bmp'))
Esta línea. Ahora estamos usando una textura de vidrio tintado en lugar de la textura de caja de madera de la lección anterior.
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // Cargar mapa de bits de vidrio (modificado)
}
Función LoadTexture: boolean; //Carga el mapa de bits y lo convierte en una textura.
var
Estado: booleano; // Indicador de estado
TextureImage: Array[0..1] Of PTAUX_RGBImageRec // Crea espacio de almacenamiento de texturas;
Comenzar
Estado: = falso;
ZeroMemory(@TextureImage, sizeof(TextureImage) // Establece el puntero en NULL
TextureImage[0] := LoadBMP('Walls.bmp');
Si TextureImage[0] <> Nil entonces
Comenzar
Estado := VERDADERO // Establecer estado en VERDADERO;
glGenTextures(1, textura[0]); // Crear textura
// Crear mapa de filtro más cercano
glBindTexture(GL_TEXTURE_2D, textura[0]);
// Generar textura
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // (nuevo)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
ImagenTextura[0].datos);
glBindTexture(GL_TEXTURE_2D, textura[1]); //Usa una textura típica generada a partir de datos de mapa de bits.
// Generar textura
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
ImagenTextura[0].datos);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//Crear textura MipMapped
glBindTexture(GL_TEXTURE_2D, textura[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST); // (nuevo)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,
TextureImage[0].data); //(nuevo) }
Fin;
Si está asignado (TextureImage[0]) Entonces // Si la textura existe
Si está asignado (TextureImage[0].data) Entonces // Si la imagen de textura existe
TextureImage[0].data := Nil; // Libera la memoria ocupada por la imagen de textura.
TextureImage[0] := Nil; // Liberar la estructura de la imagen.
resultado := Estado; // Estado de devolución
Fin;
{
Agregue las dos líneas siguientes a la sección de código glInit().
La primera línea dibuja este objeto con el brillo máximo y le da un 50% de fusión alfa (semitransparente).
Cuando la opción de fusión está activada, este objeto será 50% transparente.
La segunda línea establece el tipo de combinación utilizada.
Agregado por Rui Martins:
Un valor de canal alfa de 0,0 significa que el material del objeto es completamente transparente.
1.0 significa completamente opaco.
}
Procedimiento glInit(); // Inicie todas las configuraciones para OpenGL aquí
Comenzar
If (Not LoadTexture) Then // Llama a la subrutina de carga de texturas
salir; // Si no se pudo cargar, salga
glEnable(GL_TEXTURE_2D); // Habilitar mapeo de textura
glShadeModel(GL_SMOOTH); // Habilitar suavizado de sombras
glClearColor(0.0, 0.0, 0.0, 0.0); // fondo negro
glClearDepth(1.0); //Establece el búfer de profundidad
glEnable(GL_DEPTH_TEST); // Habilitar pruebas de profundidad
glDepthFunc(GL_LESS); // Tipo de prueba de profundidad realizada
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Cálculo de proyección en perspectiva altamente optimizado
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0] // Configura la luz ambiental);
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0] // Establece luz difusa
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // Posición de la fuente de luz
glEnable(GL_LIGHT1); // Habilita la fuente de luz No. 1
glColor4f(1.0, 1.0, 1.0, 0.5); // Brillo total, 50% de fusión alfa (nuevo)
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Función de fusión translúcida basada en el valor del canal alfa del píxel de origen (nuevo)
Fin;
{Encuentre el siguiente fragmento de código cerca del final de la Lección 7.
Si las teclas [VK_LEFT] Entonces // ¿Se presiona la tecla de dirección izquierda?
yspeed := yspeed - 0.01 //Si es así, reduzca yspeed
Siguiendo el código anterior, agregamos el siguiente código.
Estas líneas monitorean si se presiona la tecla B.
Si es así, la computadora verifica si la opción de fusión está activada.
Luego configúrelo en el estado opuesto.
}
Si (keys[ord('B')] y no bp) Entonces // ¿Se presiona la tecla B y bp es FALSO?
Comenzar
pb := VERDADERO; // En caso afirmativo, pb se establece en VERDADERO
mezclar := No mezclar // Cambiar las opciones de combinación a VERDADERO / FALSO
Si (mezclar) Entonces // ¿Se está mezclando?
Comenzar
glEnable(GL_BLEND); // Activa la combinación
glDisable(GL_DEPTH_TEST); // Desactivar las pruebas de profundidad
Fin
Si no // si no
Comenzar
glDisable(GL_BLEND); // Desactivar la combinación
glEnable(GL_DEPTH_TEST); // Activar la prueba de profundidad
Fin;
Fin;
If (Notkeys[ord('B')]) Then // ¿Se suelta la tecla B?
Comenzar
bp := FALSE; // Si es así, establezca bp en FALSE
Fin;
{
Pero, ¿cómo se puede especificar el color de la mezcla cuando se utiliza el mapeo de texturas?
Al ajustar el modo de textura, el color de cada píxel de la textura de la textura está determinado por el parámetro del canal alfa.
Se obtiene multiplicando el color del píxel actual.
Por ejemplo, el color dibujado es (0,5, 0,6, 0,4),
Multiplicaremos los colores para obtener (0,5, 0,6, 0,4, 0,2)
(Cuando no se especifica el parámetro alfa, el valor predeterminado es cero).
¡Eso es todo! ¡Implementar la combinación Alpha en OpenGL es realmente muy simple!
}
{
Nota original (13/11/99)
Mi código de mezcla de colores (NeHe) se modificó para que los objetos mostrados parecieran más realistas.
El uso del parámetro alfa para combinar los píxeles de origen y los píxeles de destino al mismo tiempo hará que los rastros artificiales del objeto parezcan obvios.
Esto hará que la parte posterior del objeto parezca más oscura en los lados.
Básicamente el objeto se verá raro.
Puede que el método de mezcla de colores que utilicé no sea el mejor, pero funciona.
Con las luces habilitadas, los objetos parecen realistas.
Gracias a Tom por proporcionar el código original. El método de mezcla de colores que utilizó es correcto.
Pero el objeto no parece tan atractivo como se esperaba :)
El código se modificó nuevamente debido a problemas con la función glDepthMask() en algunas tarjetas gráficas.
Este comando no parece ser muy efectivo al habilitar o deshabilitar la prueba de búfer de profundidad en algunas tarjetas.
Así que convertí el código para habilitar o deshabilitar la prueba de búfer de profundidad a los antiguos glEnable y glDisable.
Mezcla alfa de mapas de texturas.
El parámetro alfa utilizado para el mapa de textura se puede leer en el mapa del problema al igual que el color.
El método es el siguiente, es necesario cargar el material requerido y obtener su parámetro alfa al mismo tiempo.
Luego use el formato de color de GL_RGBA cuando llame a glTexImage2D().
}