2022-09-05 20:17:25 +02:00
# ifndef RENDER_LOOP_CPP
# define RENDER_LOOP_CPP
# include <glad/glad.h>
# include <GLFW/glfw3.h>
# include <iostream>
# include "renderLoop.hpp"
# include "draw.hpp"
# include "shaders.hpp"
# include "constants.hpp"
# include "misc.hpp"
2022-09-17 14:14:08 +02:00
int processInput ( GLFWwindow * window , const int whatToDraw )
2022-09-05 20:17:25 +02:00
{
2022-10-19 15:51:07 +02:00
static bool lockedLeft = false ;
static bool lockedRight = false ;
const bool PRESSED_CHANGE_LEFT = ( glfwGetKey ( window , GLFW_KEY_LEFT ) = = GLFW_PRESS ) ;
const bool PRESSED_CHANGE_RIGHT = ( glfwGetKey ( window , GLFW_KEY_RIGHT ) = = GLFW_PRESS ) ;
2022-09-17 14:14:08 +02:00
2022-09-07 18:54:59 +02:00
// glfwGetKey takes window and key as an input and checks is currently being pressed
2022-09-05 20:17:25 +02:00
// if the user pressed escape we close window
2022-09-07 18:54:59 +02:00
if ( glfwGetKey ( window , GLFW_KEY_ESCAPE ) = = GLFW_PRESS )
2022-09-05 20:17:25 +02:00
glfwSetWindowShouldClose ( window , true ) ;
2022-09-07 18:54:59 +02:00
if ( glfwGetKey ( window , GLFW_KEY_C ) = = GLFW_PRESS )
2022-09-05 20:17:25 +02:00
glfwSetWindowShouldClose ( window , true ) ;
2022-10-19 15:51:07 +02:00
if ( ! PRESSED_CHANGE_LEFT )
lockedLeft = 0 ;
if ( ! PRESSED_CHANGE_RIGHT )
lockedRight = 0 ;
if ( PRESSED_CHANGE_RIGHT & & lockedRight = = 0 )
2022-09-17 14:14:08 +02:00
{
2022-10-19 15:51:07 +02:00
lockedRight = 1 ;
2022-09-10 13:40:58 +02:00
return ( whatToDraw = = constants : : MAX_DRAW_CALL ? 0 : whatToDraw + 1 ) ;
2022-10-19 15:51:07 +02:00
}
if ( PRESSED_CHANGE_LEFT & & lockedLeft = = 0 )
{
lockedLeft = 1 ;
return ( whatToDraw = = 0 ? constants : : MAX_DRAW_CALL : whatToDraw - 1 ) ;
2022-09-17 14:14:08 +02:00
}
2022-09-05 20:17:25 +02:00
return whatToDraw ;
}
2022-09-06 21:52:06 +02:00
// https://stackoverflow.com/a/25680092
unsigned int copyVerticesMemory ( const float vertices [ ] , const size_t sizeOfVertices , const GLenum boundBufferTarget )
2022-09-05 20:17:25 +02:00
{
2022-09-06 21:52:06 +02:00
// stores vertices in gpu memory
unsigned int vertexBufferObject ;
// this is open gl object so we refer it by its ID generated here and stored in vertexBufferObject variable
glGenBuffers ( 1 , & vertexBufferObject ) ;
// buffer type of vertex buffer object is GL_ARRAY_BUFFER
glBindBuffer ( boundBufferTarget , vertexBufferObject ) ;
// now whenever we change GL_ARRAY_BUFFER we change bound buffer vertexBufferObject
/* we copy vertex data into buffer memory
GL_STREAM_DRAW : the data is set only once and used by the GPU at most a few times .
GL_STATIC_DRAW : the data is set only once and used many times .
GL_DYNAMIC_DRAW : the data is changed a lot and used many times .
*/
glBufferData ( boundBufferTarget , sizeOfVertices , vertices , GL_STATIC_DRAW ) ;
return vertexBufferObject ;
2022-09-05 20:17:25 +02:00
}
2022-09-06 21:52:06 +02:00
unsigned int copyVerticesMemory ( const unsigned int vertices [ ] , const size_t sizeOfVertices , const GLenum boundBufferTarget )
2022-09-05 20:17:25 +02:00
{
// stores vertices in gpu memory
unsigned int vertexBufferObject ;
// this is open gl object so we refer it by its ID generated here and stored in vertexBufferObject variable
glGenBuffers ( 1 , & vertexBufferObject ) ;
// buffer type of vertex buffer object is GL_ARRAY_BUFFER
glBindBuffer ( boundBufferTarget , vertexBufferObject ) ;
// now whenever we change GL_ARRAY_BUFFER we change bound buffer vertexBufferObject
/* we copy vertex data into buffer memory
GL_STREAM_DRAW : the data is set only once and used by the GPU at most a few times .
GL_STATIC_DRAW : the data is set only once and used many times .
GL_DYNAMIC_DRAW : the data is changed a lot and used many times .
*/
glBufferData ( boundBufferTarget , sizeOfVertices , vertices , GL_STATIC_DRAW ) ;
return vertexBufferObject ;
}
2022-10-19 15:51:07 +02:00
void configureVertexAttribute ( const bool colorIncluded )
2022-09-05 20:17:25 +02:00
{
2022-10-19 15:51:07 +02:00
/* specify how OGL interprets vertex data
From left :
which vertex attribute we configure ( from shader source code layout ( location = 0 ) )
size of vertex attribute ( we use vec3 so it contains 3 values )
type of data of which vec consists of
should data be normalized , ( useful when we use integer data )
space between vertex attributes , each position data is 3 times the size of float
offset of where position data begins in buffer
see : https : //learnopengl.com/img/getting-started/vertex_attribute_pointer.png
vertex attribute data take data from memory managed by VBO bound to GL_ARRAY_BUFFER */
if ( ! colorIncluded ) {
glVertexAttribPointer ( 0 , 3 , GL_FLOAT , GL_FALSE , 3 * sizeof ( float ) , ( void * ) 0 ) ;
// enable vertex attribute
glEnableVertexAttribArray ( 0 ) ;
return ;
}
glVertexAttribPointer ( 0 , 3 , GL_FLOAT , GL_FALSE , 6 * sizeof ( float ) , ( void * ) 0 ) ;
2022-09-05 20:17:25 +02:00
// enable vertex attribute
glEnableVertexAttribArray ( 0 ) ;
2022-10-19 15:51:07 +02:00
/* we change attribute location, color values have size of 3 floats
we do not normalize values , in order to get the next attribute value in data array we need to move 6 floats , ( 3 for position and 3 for color ) , we also need to specify an offset , first we have position then after 3 floats we have color
https : //learnopengl.com/img/getting-started/vertex_attribute_pointer_interleaved.png */
glVertexAttribPointer ( 1 , 3 , GL_FLOAT , GL_FALSE , 6 * sizeof ( float ) , ( void * ) ( 3 * sizeof ( float ) ) ) ;
// enable vertex attribute
glEnableVertexAttribArray ( 1 ) ;
2022-09-05 20:17:25 +02:00
}
unsigned int generateBindVAO ( )
{
// vertex array object is used to draw objects by binding them to vao
// generate vao
unsigned int vertexArrayObject ;
glGenVertexArrays ( 1 , & vertexArrayObject ) ;
2022-09-07 18:54:59 +02:00
// bind vao
2022-09-05 20:17:25 +02:00
glBindVertexArray ( vertexArrayObject ) ;
return vertexArrayObject ;
}
2022-09-10 13:07:13 +02:00
void copyVerticesArray ( const unsigned int vertexBufferObject , const float vertices [ ] , const size_t sizeOfVertices , const GLenum boundBufferTarget )
2022-09-05 20:17:25 +02:00
{
// copy vertices array in array useful for OGL
glBindBuffer ( boundBufferTarget , vertexBufferObject ) ;
glBufferData ( boundBufferTarget , sizeOfVertices , vertices , GL_STATIC_DRAW ) ;
}
2022-09-17 14:14:08 +02:00
int renderLoopInside ( GLFWwindow * window , int whatToDraw )
2022-09-05 20:17:25 +02:00
{
2022-09-07 18:54:59 +02:00
// input
whatToDraw = processInput ( window , whatToDraw ) ;
// We specify the color to clear the screen with
// RGB and alpha value
glClearColor ( constants : : LEARN_OPEN_GL_COLOR . red , constants : : LEARN_OPEN_GL_COLOR . green , constants : : LEARN_OPEN_GL_COLOR . blue , constants : : LEARN_OPEN_GL_COLOR . alpha ) ;
// There is GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT and GL_STENCIL_BUFFER_BIT
glClear ( GL_COLOR_BUFFER_BIT ) ;
if ( drawFigure ( whatToDraw ) = = - 1 )
{
print ( " error with drawing! " ) ;
glfwSetWindowShouldClose ( window , true ) ;
} ;
2022-09-05 20:17:25 +02:00
2022-09-07 18:54:59 +02:00
// swaps buffer containing color values of each pixel in window
// there is front buffer (final image) and back buffer (where all rendering commands draw to)
// when back buffer is ready we swap it with front buffer to eliminate flickering
glfwSwapBuffers ( window ) ;
2022-09-05 20:17:25 +02:00
2022-09-07 18:54:59 +02:00
// glfwPollEvents checks if any event (like mouse/keyboard input was triggered), updates window state and calls functions (which we register via callback methods)
glfwPollEvents ( ) ;
2022-09-17 14:14:08 +02:00
2022-09-07 18:54:59 +02:00
return whatToDraw ;
2022-09-05 20:17:25 +02:00
}
2022-09-07 18:54:59 +02:00
void renderLoop ( GLFWwindow * window )
2022-09-05 20:17:25 +02:00
{
2022-09-10 13:40:58 +02:00
int whatToDraw = 0 ;
2022-09-05 20:17:25 +02:00
// glfwWindowShouldClose checks if GLFW was instructed to close
2022-09-07 18:54:59 +02:00
while ( ! glfwWindowShouldClose ( window ) )
2022-09-05 20:17:25 +02:00
{
whatToDraw = renderLoopInside ( window , whatToDraw ) ;
}
}
2022-09-07 18:54:59 +02:00
# endif