{
En esta lección, te enseñaré cómo utilizar tres métodos diferentes de filtrado de texturas.
Enseñarle cómo usar el teclado para mover objetos en la escena y también cómo aplicar iluminación simple en una escena OpenGL.
Esta lección contiene mucho contenido. Si tiene preguntas sobre las lecciones anteriores, regrese y revíselas primero.
Antes de entrar en el código detrás de esto, es importante tener una buena comprensión de los conceptos básicos.
Todavía modificamos el código de la primera lección.
La diferencia con respecto a antes es que cada vez que hay un cambio importante, escribo el código completo.
Primero tenemos que agregar la unidad SysUtils y la unidad Glaux.
}
Usos
SysUtils,
opengl,
ventanas,
mensajes,
Glaux En '../../GLAUX/Glaux.pas';
//Las siguientes líneas agregan nuevas variables.
//Añadimos tres variables booleanas.
// La variable de luz rastrea si la luz está encendida.
//Las variables lp y fp se utilizan para almacenar si se presionan las teclas 'L' y 'F'.
//Explicaré la importancia de estas variables más adelante. Por ahora, deja eso a un lado.
luz: booleano; // fuente de luz encendida/apagada
lp: Booleano; // ¿Está presionada la tecla L?
fp: booleano; // ¿Se presiona la tecla F?
//Ahora configure 5 variables para controlar el tamaño del paso del ángulo de rotación alrededor del eje x y el eje y,
//Y la velocidad de rotación alrededor del eje x y del eje y.
//Además, se crea una variable z para controlar la distancia hacia la profundidad de la pantalla.
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
// Luego configura la matriz utilizada para crear la fuente de luz.
//Utilizaremos dos luces diferentes.
//La primera se llama luz ambiental. La luz ambiental proviene de todas direcciones.
//Todos los objetos de la escena están iluminados por la luz ambiental.
//El segundo tipo de fuente de luz se llama luz difusa.
//La luz difusa es generada por una fuente de luz específica y crea reflejos en las superficies de los objetos de tu escena.
//Cualquier superficie de objeto iluminada directamente por luz difusa se vuelve muy brillante,
//Las zonas apenas iluminadas aparecen más oscuras.
//Esto producirá un muy buen efecto de sombra en los bordes de la caja de madera que creamos.
//El proceso de crear una fuente de luz es exactamente el mismo que crear un color.
// Los primeros tres parámetros son los componentes RGB de tres colores y el último es el parámetro del canal alfa.
//Por lo tanto, en el siguiente código obtenemos una luz ambiental blanca medio brillante (0,5f).
//Si no hay luz ambiental, las zonas que no llegan a la luz difusa quedarán muy oscuras.
LightAmbient: Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0); //Parámetros de luz ambiental (nuevo)
// En la siguiente línea de código generamos la luz difusa más brillante.
//Todos los valores de los parámetros se llevan al valor máximo de 1.0f.
//Brillará en el frente de nuestra caja de madera y lucirá bien.
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0); // Parámetros de luz difusa (nuevo)
//Finalmente guardamos la posición de la fuente de luz.
//Los primeros tres parámetros son los mismos que en glTranslate.
//Los desplazamientos en el eje XYZ son respectivamente.
//Como queremos que la luz brille directamente sobre el frente de la caja de madera, los desplazamientos en el eje XY son ambos 0,0.
//El tercer valor es el desplazamiento en el eje Z.
//Para garantizar que la luz esté siempre delante de la caja de madera,
// Entonces alejamos la fuente de luz de la pantalla hacia el observador (que eres tú).
// Generalmente llamamos a la posición de la pantalla, es decir, el cristal de la pantalla del monitor, el punto 0.0 del eje Z.
// Entonces, el desplazamiento en el eje Z finalmente se establece en 2.0.
//Si puedes ver la fuente de luz, flota frente a tu monitor.
//Por supuesto, no puedes ver la caja si no está detrás del cristal de la pantalla del monitor.
//『Nota del traductor: Aprecio la paciencia de NeHe.
//Para ser honesto, a veces me molesta. ¿Por qué dice tantas tonterías sobre algo tan simple?
//Pero si todo estuviera claro, ¿seguirías hojeando páginas como ésta y leyendo sin parar? 』
//El último parámetro se toma como 1.0f.
//Esto le dirá a OpenGL que las coordenadas especificadas aquí son las posiciones de la fuente de luz. Explicaré más en futuros tutoriales.
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0); // Posición de la fuente de luz (nueva)
//La variable de filtro realiza un seguimiento del tipo de textura utilizada al mostrar.
// La primera textura (textura 0) se construye utilizando el método de filtrado gl_nearest (no suave).
//La segunda textura (textura 1) utiliza el método gl_linear (filtrado lineal),
//La imagen más cercana a la pantalla se ve más suave.
//La tercera textura (textura 2) utiliza el método de filtrado mipmapped,
//Esto creará una textura muy bonita.
//Dependiendo de nuestro tipo de uso, el valor de la variable de filtro es igual a 0, 1 o 2 respectivamente.
//Empecemos con la primera textura.
//textura asigna espacio de almacenamiento para tres texturas diferentes.
//Están ubicados en textura[0], textura[1] y textura[2] respectivamente.
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';
{
Ahora carga un mapa de bits y úsalo para crear tres texturas diferentes.
Esta lección utiliza la biblioteca auxiliar glaux para cargar mapas de bits.
Por lo tanto, debes confirmar si la biblioteca glaux está incluida al compilar.
Sé que tanto Delphi como VC++ incluyen la biblioteca gaux, pero no se garantiza que otros lenguajes la tengan.
"Nota del traductor: glaux es una biblioteca auxiliar de OpenGL. Según las características multiplataforma de OpenGL,
El código debe ser común en todas las plataformas. Pero la biblioteca auxiliar no es la biblioteca estándar oficial de OpenGL.
No disponible en todas las plataformas. Pero resulta que está disponible en la plataforma Win32.
Jaja, por supuesto que BCB tampoco es un problema. 』Aquí solo anoto el código recién agregado.
Si tiene preguntas sobre una determinada línea de código, consulte el Tutorial 6.
Esa lección explica la carga y creación de texturas con gran detalle.
Después del fragmento de código anterior y antes de glResizeWnd (),
Agregamos el siguiente código. Esto es casi idéntico al código utilizado para cargar el mapa de bits en la Lección 6.
}
Función LoadBmp (nombre de archivo: pchar): PTAUX_RGBImageRec;
var
BitmapFile: Thandle // identificador de archivo
Comenzar
Si Nombre de archivo = '' Entonces // Asegúrese de que se proporcione el nombre de archivo.
resultado := Nil; // Si no se proporciona, devuelve NULL
BitmapFile := FileOpen(Filename, fmOpenWrite); //Intenta abrir el archivo.
Si BitmapFile > 0 Entonces // ¿Existe el archivo?
Comenzar
FileClose(BitmapFile); //Cerrar identificador
resultado := auxDIBImageLoadA(filename); //Carga el mapa de bits y devuelve el puntero
Fin
Demás
resultado := Nil; // Si la carga falla, devuelve NiL.
Fin;
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
//En la Lección 6 utilizamos el mapeo de texturas filtrado lineal.
//Esto requiere una cantidad bastante alta de potencia de procesamiento de la máquina, pero se ven bastante bien.
//En esta lección, la primera textura que vamos a crear utiliza el método GL_NEAREST.
// En principio, este método en realidad no realiza filtrado.
//Consume muy poca potencia de procesamiento y parece pobre.
// La única ventaja es que nuestro proyecto puede ejecutarse normalmente tanto en máquinas rápidas como lentas.
//Notarás que usamos GL_NEAREST tanto para MIN como para MAG,
//Puedes mezclar GL_NEAREST y GL_LINEAR.
//La textura se verá mejor, pero nos preocupamos más por la velocidad, por eso usamos todos los mapas de baja calidad.
//MIN_FILTER se utiliza cuando la imagen se dibuja más pequeña que el tamaño original de la textura.
//MAG_FILTER se utiliza cuando la imagen se dibuja más grande que el tamaño original de la 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);
//La siguiente textura es la misma que la de la Lección 6, filtrado lineal. La única diferencia es que esta vez se coloca
//textura[1]. Porque esta es la segunda textura. Si se coloca
//textura[0], sobrescribirá la textura GL_NEAREST creada previamente.
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);
//La siguiente es una nueva forma de crear texturas. ¡Mapeo MIP!
//『Nota del traductor: No puedo traducir esta palabra al chino, pero no importa. Después de leer este párrafo, sabrás que el significado es lo más importante. 』
//Puedes notar que cuando la imagen se vuelve muy pequeña en la pantalla, se pierden muchos detalles.
// El patrón que se veía bien hace un momento se ha vuelto feo. Cuando le dices a OpenGL que cree una textura mipmapeada,
//OpenGL intentará crear texturas de alta calidad de diferentes tamaños. Cuando dibujas una textura mipmapeada en la pantalla,
//OpenGL elegirá la textura más atractiva (con más detalle) que haya creado para dibujar,
//En lugar de simplemente escalar la imagen original (lo que resultará en una pérdida de detalles).
// Una vez dije que hay formas de sortear las limitaciones que OpenGL impone al ancho y alto de la textura: 64, 128, 256, etc.
//La solución es gluBuild2DMipmaps. Por lo que encontré, puedes usar mapas de bits arbitrarios para crear texturas.
//OpenGL lo escalará automáticamente al tamaño normal.
//Como es la tercera textura, la guardamos en la textura[2]. De esta manera, se han creado las tres texturas de esta lección.
//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)
//La siguiente línea genera una textura mipmapeada.
//Usamos tres colores (rojo, verde, azul) para generar una textura 2D.
//TextureImage[0].sizeX es el ancho del mapa de bits,
//TextureImage[0].sizeY es la altura del mapa de bits,
//(====Por alguna razón, esta función en Delphi no tiene el parámetro de altura,
//Pero está en la ayuda ya no sé qué hará Delphi, lo que me deprime...
//Finalmente, yo mismo escribí gluBuild2DMipmaps anteriormente,
//Para cargar la función gluBuild2DMipmaps en glu32.dll =====)
//GL_RGB significa que usamos colores RGB por turno.
//GL_UNSIGNED_BYTE significa que la unidad de datos de textura es bytes.
//TextureImage[0].data apunta al mapa de bits que usamos para crear la textura.
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;
// Entonces es hora de cargar la textura e inicializar la configuración de OpenGL.
// La primera línea de la función GLInit usa el código anterior para cargar la textura.
//Después de crear la textura, llamamos a glEnable(GL_TEXTURE_2D) para habilitar el mapeo de textura 2D.
// El modo de sombra está configurado en sombreado suave (sombreado suave).
// El color de fondo se establece en negro, habilitamos las pruebas de profundidad y luego habilitamos los cálculos de perspectiva optimizados.
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
//Ahora comienza a configurar la fuente de luz. La siguiente línea a continuación establece la cantidad de luz ambiental emitida,
//La fuente de luz light1 comienza a emitir luz.
//Al comienzo de esta lección, almacenamos la cantidad de luz ambiental en la matriz LightAmbient.
//Ahora usaremos esta matriz (luz ambiental de medio brillo).
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0] // Configura la luz ambiental);
//A continuación configuramos la cantidad de luz difusa. Se almacena en la matriz LightDiffuse (luz blanca de brillo total).
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0] // Establece luz difusa
// Luego establece la posición de la fuente de luz.
//La posición se almacena en la matriz LightPosition
//(exactamente ubicado en el centro del frente de la caja de madera, X-0.0, Y-0.0, se movió 2 unidades hacia el observador en la dirección Z <fuera de la pantalla>).
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // Posición de la fuente de luz
//Finalmente, habilitamos la fuente de luz número uno. Aún no hemos habilitado GL_LIGHTING.
// Entonces no puedes ver ninguna luz.
//Recuerde: simplemente configurar, posicionar o incluso habilitar la fuente de luz no funcionará.
//A menos que habilitemos GL_LIGHTING.
glEnable(GL_LIGHT1); // Habilita la fuente de luz No. 1
Fin;
//El siguiente fragmento de código dibuja el cubo texturizado. Solo anoto el nuevo código.
//Si tienes preguntas sobre el código sin anotaciones, regresa a la Lección 6.
Procedimiento glDraw(); // Todo el dibujo comienza desde aquí
Comenzar
glClear(GL_COLOR_BUFFER_BIT O GL_DEPTH_BUFFER_BIT // Borrar pantalla y búfer de profundidad);
glLoadIdentity(); //Restablecer la matriz de observación del modelo actual
//Las siguientes tres líneas de código colocan y rotan el cubo de textura.
//glTranslatef(0.0,0.0,z) mueve el cubo Z unidades a lo largo del eje Z.
//glRotatef(xrot,1.0f,0.0f,0.0f) gira el cubo alrededor del eje X xrot.
//glRotatef(yrot,0.0f,1.0f,0.0f) gira el cubo yrot alrededor del eje Y.
glTranslatef(0.0, 0.0, z); // Entrar/salir de la pantalla z unidades
glRotatef(xrot, 1.0, 0.0, 0.0); // Gira alrededor del eje X
glRotatef(yrot, 0.0, 1.0, 0.0); // Gira alrededor del eje Y
//La siguiente línea es similar a lo que hicimos en la Lección 6.
//La diferencia es que esta vez la textura que unimos es textura[filtro],
//En lugar de textura[0] en la lección anterior.
//Cada vez que presionemos la tecla F, el valor del filtro aumentará.
//Si este valor es mayor que 2, el filtro de variables se restablecerá a 0.
//Cuando se inicializa el programa, el valor del filtro variable también se establecerá en 0.
//Utilizando el filtro de variables podemos seleccionar cualquiera de las tres texturas.
glBindTexture(GL_TEXTURE_2D, textura[filtro]); //Selecciona la textura determinada por el filtro
glBegin(GL_QUADS); // Empezar a dibujar cuadriláteros
//glNormal3f es nuevo en esta lección. Normal significa normal.
//La llamada normal se refiere a una línea recta que pasa por un punto de una superficie (polígono) y es perpendicular a esta superficie (polígono).
//Cuando se utiliza una fuente de luz, se debe especificar una normal. La normal le dice a OpenGL la orientación del polígono e indica los lados frontal y posterior del polígono.
//Si no se especifican las normales, pueden suceder cosas extrañas: las superficies que no deberían iluminarse se iluminan y la parte posterior del polígono también se ilumina....
//Por cierto, la normal debería apuntar al exterior del polígono. Mirando el frente del cuadro notarás que la normal está en la misma dirección que el eje Z positivo.
//Esto significa que lo normal apunta hacia el observador: usted mismo. Esto es exactamente lo que esperamos.
//Para la parte posterior de la caja de madera, tal como queremos, lo normal está de espaldas al espectador.
//Si el cubo se gira 180 grados a lo largo del eje X o Y, la normal en el lado frontal todavía está mirando hacia el observador, y la normal en la parte posterior todavía está mirando en dirección opuesta al observador.
// En otras palabras, no importa qué superficie sea, siempre que esté frente al observador, la normal de esta superficie apunta al observador.
//Dado que la fuente de luz está inmediatamente adyacente al observador, cada vez que la normal esté frente al observador, esta superficie se iluminará.
//Y cuanto más cerca esté la normal de la fuente de luz, más brillante aparecerá.
//Si colocas el punto de observación dentro del cubo, obtendrás oscuridad dentro de lo normal.
//Porque lo normal apunta hacia afuera. Si no hay una fuente de luz dentro del cubo, por supuesto, estará completamente oscuro.
// Frente
glNormal3f(0.0, 0.0, 1.0); // puntos normales al observador
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, -1.0, 1.0); // Textura y parte inferior izquierda del quad
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, 1.0); // Textura y parte inferior derecha del quad
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0); //Textura y parte superior derecha del quad
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0); //Textura y parte superior izquierda del quad
// más tarde
glNormal3f(0.0, 0.0, -1.0); // Caras normales alejadas del espectador
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, -1.0, -1.0); // Textura y parte inferior derecha del quad
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0); //Textura y parte superior derecha del quad
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, -1.0); //Textura y parte superior izquierda del quad
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, -1.0); // Textura y parte inferior izquierda del quad
// superficie superior
glNormal3f(0.0, 1.0, 0.0); // normal hacia arriba
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0); //Textura y parte superior izquierda del quad
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, 1.0, 1.0); // Textura y parte inferior izquierda del quad
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, 1.0, 1.0); // Textura y parte inferior derecha del quad
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0); //Textura y parte superior derecha del quad
// Abajo
glNormal3f(0.0, -1.0, 0.0); // normal boca abajo
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, -1.0, -1.0); // Textura y parte superior derecha del quad
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, -1.0, -1.0); //Textura y parte superior izquierda del quad
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0); // Textura y parte inferior izquierda del quad
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, -1.0, 1.0); // Textura y parte inferior derecha del quad
// bien
glNormal3f(1.0, 0.0, 0.0); // normal a la derecha
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, -1.0); // Textura y parte inferior derecha del quad
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0); //Textura y parte superior derecha del quad
glTexCoord2f(0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0); //Textura y parte superior izquierda del quad
glTexCoord2f(0.0, 0.0);
glVertex3f(1.0, -1.0, 1.0); // Textura y parte inferior izquierda del quad
// izquierda
glNormal3f(-1.0, 0.0, 0.0); // normal a la izquierda
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, -1.0, -1.0); // Textura y parte inferior izquierda del quad
glTexCoord2f(1.0, 0.0);
glVertex3f(-1.0, -1.0, 1.0); // Textura y parte inferior derecha del quad
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0); //Textura y parte superior derecha del quad
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0); //Textura y parte superior izquierda del quad
glEnd();
xrot := xrot + xspeed; // xrot aumenta las unidades de xspeed
yrot := Yrot + yspeed; // yrot aumenta las unidades de yspeed
Fin;
//Ahora vaya a la función principal WinMain().
//Agregaremos aquí un código de control para encender y apagar la fuente de luz, rotar la caja de madera, cambiar los métodos de filtrado y acercar y alejar la caja de madera.
// Cerca del final de la función WinMain() verá la línea de código SwapBuffers(hDC).
//Luego agrega el siguiente código después de esta línea.
//El código verificará si se ha presionado la tecla L.
// Si se ha presionado la tecla L, pero el valor de lp no es falso, significa que no se ha soltado la tecla L y no pasará nada en este momento.
SwapBuffers(h_DC); // Intercambiar buffer (doble buffer)
Si (keys[ord('L')] y no lp) entonces
Comenzar
//Si el valor de lp es falso,
// Lo que significa que la tecla L aún no se ha presionado o se ha soltado, entonces lp se establecerá en TRUE.
// El motivo para verificar estas dos condiciones al mismo tiempo es para evitar que se presione la tecla L.
//Este código se ejecuta repetidamente y hace que el formulario parpadee continuamente.
//Después de que lp se establezca en verdadero, la computadora sabrá que se ha presionado la tecla L.
//Podemos encender/apagar la fuente de luz en consecuencia: la variable booleana luz controla el encendido/apagado de la fuente de luz.
lp := verdadero; // lp se establece en VERDADERO
luz := No hay luz // Cambia la fuente de luz a VERDADERO/FALSO;
Si no hay luz Entonces // Si no hay fuente de luz
glDisable(GL_LIGHTING) //Desactivar fuente de luz
Más // Otros
glEnable(GL_LIGHTING); //Habilitar fuente de luz
Fin;
Si no son teclas[ord('L')] Entonces //¿Se ha liberado la tecla L?
lp := FALSE; // En caso afirmativo, establezca lp en FALSE
//Luego haz una verificación similar para la tecla "F".
//Si se presiona la tecla "F" y la tecla "F" no se presiona o nunca se ha presionado,
//Establece la variable fp en verdadero. Esto significa que se está presionando la tecla.
// Luego agrega uno a la variable de filtro. Si la variable del filtro es mayor que 2
//(Debido a que la matriz que usamos aquí es textura [3], las texturas mayores que 2 no existen),
//Restablecemos la variable de filtro a 0.
If (keys[ord('F')] And Not fp) Then // ¿Se presiona la tecla F?
Comenzar
fp := VERDADERO; // fp se establece en VERDADERO
inc(filtro); // Agrega uno al valor del filtro
Si filtro > 2 Entonces // ¿Es mayor que 2?
filtro: = 0; // Si se restablece a 0
Fin;
Si no son teclas [ord('F')] Entonces // ¿Se ha liberado la tecla F?
fp := FALSO; // Si fp se establece en FALSO
// Estas cuatro líneas verifican si se presiona la tecla Re Pág. Si es así, disminuya el valor de la variable z. De esta forma, la llamada a glTranslatef(0.0f,0.0f,z) incluida en la función DrawGLScene alejará la caja de madera del espectador.
Si las teclas [VK_PRIOR] ¿Entonces se presiona // Re Pág?
z := z - 0.02; // Si se presiona, mueve la caja de madera hacia el interior de la pantalla.
//Las siguientes cuatro líneas verifican si se presiona la tecla PageDown. Si es así, aumenta el valor de la variable z. De esta forma, la llamada glTranslatef(0.0f,0.0f,z) incluida en la función DrawGLScene acercará la caja de madera al observador.
Si las teclas [VK_NEXT] Entonces // ¿Se presiona PageDown?
z := z + 0.02; //Si se presiona, mueve la caja de madera hacia el observador.
//Ahora revisa las teclas de flecha. Presione las teclas de dirección izquierda y derecha para disminuir o aumentar la velocidad x en consecuencia.
//Presione las teclas de dirección arriba y abajo para disminuir o aumentar la velocidad en consecuencia.
//Recuerda que en futuros tutoriales si se aumentan los valores de xspeed y yspeed, el cubo girará más rápido.
//Si sigues presionando una determinada tecla de dirección, el cubo girará más rápido en esa dirección.
Si las teclas [VK_UP] Entonces // ¿Se presiona la tecla de dirección Arriba?
xspeed := xspeed - 0.01 //Si es así, reduzca xspeed
Si las teclas [VK_DOWN] Entonces // ¿Se ha presionado la tecla de dirección Abajo?
xspeed := xspeed + 0.01 //Si es así, aumenta xspeed
Si las teclas [VK_RIGHT] Entonces // ¿Se presiona la tecla de dirección derecha?
yspeed := yspeed + 0.01 //Si es así, aumenta yspeed
Si las teclas [VK_LEFT] Entonces // ¿Se presiona la tecla de dirección izquierda?
yspeed := yspeed - 0.01 //Si es así, reduzca yspeed
If (keys[VK_ESCAPE]) Then // Si se presiona la tecla ESC
terminado := Verdadero
Ejecútelo y vea el efecto.