engineer-thesis-WUT/Engine/engine/renderLoop.cpp

135 lines
5.5 KiB
C++

#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"
bool processInput(GLFWwindow *window, const bool whatToDraw)
{
// glfwGetKey takes window and key as an input and checks is currently being pressed
// if the user pressed escape we close window
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_C) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS || glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
return !whatToDraw;
return whatToDraw;
}
// https://stackoverflow.com/a/25680092
unsigned int copyVerticesMemory(const float vertices[], const size_t sizeOfVertices, const GLenum boundBufferTarget)
{
// 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;
}
unsigned int copyVerticesMemory(const unsigned int vertices[], const size_t sizeOfVertices, const GLenum boundBufferTarget)
{
// 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;
}
void configureVertexAttribute()
{
// 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
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
// enable vertex attribute
glEnableVertexAttribArray(0);
}
unsigned int generateBindVAO()
{
// vertex array object is used to draw objects by binding them to vao
// generate vao
unsigned int vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
// bind vao
glBindVertexArray(vertexArrayObject);
return vertexArrayObject;
}
void copyVerticesArray(const unsigned int vertexBufferObject, const float vertices[], const size_t sizeOfVertices, const GLenum boundBufferTarget)
{
// copy vertices array in array useful for OGL
glBindBuffer(boundBufferTarget, vertexBufferObject);
glBufferData(boundBufferTarget, sizeOfVertices, vertices, GL_STATIC_DRAW);
}
bool renderLoopInside(GLFWwindow *window, bool whatToDraw)
{
// 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);
};
// 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);
// glfwPollEvents checks if any event (like mouse/keyboard input was triggered), updates window state and calls functions (which we register via callback methods)
glfwPollEvents();
return whatToDraw;
}
void renderLoop(GLFWwindow *window)
{
bool whatToDraw = true;
// glfwWindowShouldClose checks if GLFW was instructed to close
while (!glfwWindowShouldClose(window))
{
whatToDraw = renderLoopInside(window, whatToDraw);
}
}
#endif