mirror of
https://github.com/kuhyx/engineer-thesis-WUT.git
synced 2026-07-04 16:23:14 +02:00
230 lines
8.3 KiB
C++
230 lines
8.3 KiB
C++
// "Copyright [2023] <Krzysztof Rudnicki>"
|
|
#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"
|
|
|
|
int processInput(GLFWwindow *window, const int whatToDraw) {
|
|
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);
|
|
|
|
// 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 ( !PRESSED_CHANGE_LEFT )
|
|
lockedLeft = 0;
|
|
if ( !PRESSED_CHANGE_RIGHT )
|
|
lockedRight = 0;
|
|
if ( PRESSED_CHANGE_RIGHT && lockedRight == 0 ) {
|
|
lockedRight = 1;
|
|
return (whatToDraw == constants::MAX_DRAW_CALL ? 0 : whatToDraw + 1);
|
|
}
|
|
if ( PRESSED_CHANGE_LEFT && lockedLeft == 0 ) {
|
|
lockedLeft = 1;
|
|
return (whatToDraw == 0 ? constants::MAX_DRAW_CALL : whatToDraw - 1);
|
|
}
|
|
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(
|
|
const bool colorIncluded,
|
|
const bool textureIncluded) {
|
|
/* 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), reinterpret_cast<void *>(0));
|
|
// enable vertex attribute
|
|
glEnableVertexAttribArray(0);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/* 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 */
|
|
if (colorIncluded && !textureIncluded) {
|
|
glVertexAttribPointer(
|
|
0, 3, GL_FLOAT, GL_FALSE,
|
|
6 * sizeof(float), reinterpret_cast<void *>(0));
|
|
// enable vertex attribute
|
|
glEnableVertexAttribArray(0);
|
|
|
|
glVertexAttribPointer(
|
|
1, 3, GL_FLOAT, GL_FALSE,
|
|
6 * sizeof(float), reinterpret_cast<void *>(3* sizeof(float)));
|
|
// enable vertex attribute
|
|
glEnableVertexAttribArray(1);
|
|
return;
|
|
}
|
|
|
|
// Since we've added an extra vertex
|
|
// attribute we again have to notify OpenGL of the new vertex format
|
|
// this time for textures we add just
|
|
// 2 more attributes and not 3 as with color
|
|
if (textureIncluded) {
|
|
glVertexAttribPointer(
|
|
0, 3, GL_FLOAT, GL_FALSE,
|
|
8 * sizeof(float), reinterpret_cast<void *>(0));
|
|
// enable vertex attribute
|
|
glEnableVertexAttribArray(0);
|
|
|
|
glVertexAttribPointer(
|
|
1, 3, GL_FLOAT, GL_FALSE,
|
|
8 * sizeof(float), reinterpret_cast<void *>(3* sizeof(float)));
|
|
// enable vertex attribute
|
|
glEnableVertexAttribArray(1);
|
|
|
|
glVertexAttribPointer(
|
|
2, 2, GL_FLOAT, GL_FALSE,
|
|
8 * sizeof(float), reinterpret_cast<void*>(6 * sizeof(float)));
|
|
glEnableVertexAttribArray(2);
|
|
return;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
int renderLoopInside(GLFWwindow *window, int 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);
|
|
|
|
|
|
drawFigureReturn successAndVao = drawFigure(whatToDraw);
|
|
if (successAndVao.success == -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();
|
|
|
|
glDeleteVertexArrays(1, &successAndVao.VAO);
|
|
glDeleteBuffers(1, &successAndVao.VBO);
|
|
glDeleteBuffers(1, &successAndVao.EBO);
|
|
|
|
|
|
return whatToDraw;
|
|
}
|
|
|
|
void renderLoop(GLFWwindow *window) {
|
|
int whatToDraw = 0;
|
|
// glfwWindowShouldClose checks if GLFW was instructed to close
|
|
while (!glfwWindowShouldClose(window)) {
|
|
whatToDraw = renderLoopInside(window, whatToDraw);
|
|
}
|
|
}
|
|
|
|
#endif
|