Si se quiere regresar al estado de la práctica 3, hacer un git reset a la [**etiqueta p3**](https://gitlab.ujaen.es/dpp00022/PAG_p1/tree/p3).
## Respuestas a las preguntas del guión
**Q1:**
> Si redimensionas la ventana de la aplicación, verás que el triángulo no permanece igual, sino que se deforma al mismo tiempo que la ventana. ¿A qué crees que se debe este comportamiento?
**A1:**<br/>
Esto se debe a la naturaleza del renderizado de OpenGL. Como ya sabemos, en OpenGL no se renderizan ventanas, sino **"viewports"**, que son básicamente espacios reservados para que OpenGL dibuje. Una ventana puede constar solamente de un viewport, pero también puede contener espacios no OpenGL que contengan controles o cualquier otro elemento estático, e incluso varios viewport.
Sabiendo esto, la razón por la que sucede lo anteriormente descrito es porque **OpenGL siempre dibuja la imagen a renderizar en el viewport, ocupando el espacio disponible**. Hay un paso en el que se convierten las coordenadas espaciales, expresadas en el rango [-1, 1], a coordenadas viewport, en el rango [0, {w/h}], siendo w y h el ancho y alto en píxeles del viewport, respectivamente. Por tanto, **al reescalar la ventana, estamos reescalando el viewport con ella**, y por tanto, la misma imagen (nuestro triángulo) se reescala para ocupar este nuevo espacio disponible.
Como colofón, ImGui se mantiene ajeno a este comportamiento porque esta biblioteca porque esta expresa la posición y el tamaño de las ventanas en todo momento en términos de los píxeles de la ventana, y, aunque reescalemos la ventana, los píxeles siempre tendrán el mismo tamaño. La única transformación que causa cambios en el estado de las ventanas ImGui es el desplazamiento de la ventana, ya que estamos desplazando el píxel (0,0) de la ventana al hacer esto.
## Cambios
- Se agregaron las siguientes clases:
-**ShaderException**: Excepción personalizada para los Shaders. Permite especificar rápidamente qué Shader ha dado error y en qué fase del proceso se ha producido el error, además de incluir la información de error generada por OpenGL.
- Se modificaron las siguientes clases Singleton:
-**Renderer**:
- Se agregaron los atributos: `idVS`, `idFS`, `idSP`, `idVAO`, `idVBO`, `idIBO` y `idColor`.
- Se agregó el método `creaShaderProgram(.)`, que crea, carga, compila y enlaza un programa de shaders definido por un nombre.
- Se agregó el método `creaModelo()`, que crea el modelo del triángulo. En el código están incrustados los métodos para especificar la posición y el color de los vértices de forma entrelazada y no entrelazada.
- Se modificó el método `refrescar()` para activar el programa de shaders y renderizar el modelo del triángulo en la ventana.
- Se modificó el destructor para liberar los recursos asociados al Shader Program y al modelo.
- Se modificó el método `inicializar()` para activar el Multisampling.
- Se modificaron las siguientes clases:
-**LogWindow**: Ahora realiza autoscroll hasta abajo al registrar un nuevo mensaje.
- Se agregaron los siguientes archivos
-**pag03-vs.glsl**: Contiene el código fuente del Vertex Shader empleado en esta práctica, el cual lee la posición y el color de cada vértice.
-**pag03-fs.glsl**: Contiene el código fuente del Fragment Shader empleado en esta práctica, el cual devuelve el color correspondiente a cada fragmento.
- Se modificaron los siguientes archivos
-**main.cpp**:
- Se han agregado instrucciones para crear el Shader Program (con captura de excepciones) y para crear el modelo (triángulo).
- Se ha mejorado el bucle de renderizado, de forma que ahora se refresque en tiempo real.
- Se eliminó la impresión de mensajes cuando se refresca o reescala la ventana, se presiona o suelta una tecla o botón del ratón y cuando se hace scroll con la rueda del ratón.
-**CMakeLists.txt** y **conandata.yml**: Se agregó el paquete glm en Windows.
Si se quiere regresar al estado de la práctica 2, hacer un git reset a la [**etiqueta p2**](https://gitlab.ujaen.es/dpp00022/PAG_p1/tree/p2).
## Cambios
No se especificaron los cambios en su momento, pero básicamente:
- Se agregaron las clases Singleton:
-**Renderer**: Encargada del renderizado en general de la escena
-**GUI**: Encargada de la gestión de la interfaz de usuario implementada mediante la librería Dear ImGui.
- Se agregaron las clases abstactas:
-**Listener**: Siguiendo el patrón Observador, implementa el comportamiento de una clase que escucha.
-**GuiElement**: Implementa el comportamiento de una ventana de la interfaz de usuario (entre ellas, las alertas a los listeners, siguiendo el patrón Observador).
- Se agregaron las clases:
-**BackgroundWindow**: Ventana de la GUI que contiene un selector de color que cambia el color de fondo.
-**LogWindow**: Ventana de la GUI que contiene un registro de mensajes de la aplicación,
- Se modificaron los siguientes archivos
-**main.cpp**:
- Se sustituyeron varias llamadas a OpenGL por llamadas a Renderer.
- Se eliminó "yPos" y la acción de cambiar el color de fondo al hacer scroll con el ratón.
- Se modificó el bucle de render para renderizar también la GUI.
- Se agregaron llamadas a GUI para imprimir todos los mensajes también en la ventana de log.
- Se agregó compatibilidad con ImGui en los callbacks y la liberación de recursos.
-**CMakeLists.txt**: Se agregó compatibilidad con Linux.
- Se agregó la **biblioteca Dear ImGui**, ahora se halla en la carpeta "imgui".
# Práctica 1
Si se quiere regresar al estado de la práctica 1, hacer un git reset a la [**etiqueta p1**](https://gitlab.ujaen.es/dpp00022/PAG_p1/tree/p1).
## Solución a la segunda parte de la práctica 1
La solución que propongo al problema propuesto sería llamar al método de clase `PAG::Renderer::refrescarVentana()` en la función de C llamada `refresh_window_callback()` que tenemos actualmente en el archivo `main.cpp` de nuestro proyecto de C++. Así, estaríamos encapsulando un método incompatible para la orden `glSetWindowRefreshCallback()` dentro de una función compatible como la que ya hemos mencionado.
La solución que propongo al problema propuesto sería llamar al método de clase `PAG::Renderer::refrescarVentana()` en la función de C llamada `refresh_window_callback()` que tenemos actualmente en el archivo `main.cpp` de nuestro proyecto de C++. Así, estaríamos encapsulando un método incompatible para la orden `glSetWindowRefreshCallback()` dentro de una función compatible como la que ya hemos mencionado.
Se puede ver que funciona perfectamente porque ya la hemos enlazado sin problemas. Al fin y al cabo, la orden `glSetWindowRefreshCallback()` solo requiere que se le pase una función de C compatible pero, más allá de eso, no comprueba el contenido de `refresh_window_callback()`, simplemente llama a su ejecución lo mismo que haría una llamada directa en el código principal, y mientras el entorno de OpenGL/C++ pueda ejecutar su contenido (cosa que evidentemente puede hacer), no debería haber traba alguna.
Se puede ver que funciona perfectamente porque ya la hemos enlazado sin problemas. Al fin y al cabo, la orden `glSetWindowRefreshCallback()` solo requiere que se le pase una función de C compatible pero, más allá de eso, no comprueba el contenido de `refresh_window_callback()`, simplemente llama a su ejecución lo mismo que haría una llamada directa en el código principal, y mientras el entorno de OpenGL/C++ pueda ejecutar su contenido (cosa que evidentemente puede hacer), no debería haber traba alguna.