mirror of
https://github.com/kuhyx/engineer-thesis-WUT.git
synced 2026-07-04 16:43:15 +02:00
feat: divide into files
This commit is contained in:
parent
c8e6f37165
commit
68cd8c3cf7
92
Engine/engine/beforeRender.cpp
Normal file
92
Engine/engine/beforeRender.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef BEFORE_RENDER_CPP
|
||||
#define BEFORE_RENDER_CPP
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include "beforeRender.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "misc.hpp"
|
||||
|
||||
void configureGLFW(const int GLFWMajorVersion, const int GLFWMinorVersion) {
|
||||
// first argument tells us what option to configure
|
||||
// second is to what we set the value of this option
|
||||
// see: https://www.glfw.org/docs/latest/window.html#window_hints
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GLFWMajorVersion);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GLFWMinorVersion);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
// we set GLFW to 3.3 CORE
|
||||
// core profile gives us access to smaller subset of OGL without backwards compatible features
|
||||
|
||||
// if we are on Mac OS X we need this for our code to work
|
||||
#ifdef __APPLE__
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void instantiateGLFWwindow() {
|
||||
// Initialize GLFW
|
||||
glfwInit();
|
||||
configureGLFW(constants::GLFW_MAJOR_VERSION, constants::GLFW_MINOR_VERSION);
|
||||
}
|
||||
|
||||
GLFWwindow* createWindowObject() {
|
||||
// First two arguments are width and height
|
||||
// Third is the name of the window
|
||||
// We ignore last two
|
||||
GLFWwindow* window = glfwCreateWindow(constants::MAIN_WINDOW_WIDTH, constants::MAIN_WINDOW_HEIGHT, constants::MAIN_WINDOW_NAME, NULL, NULL);
|
||||
return window;
|
||||
}
|
||||
|
||||
int initializeGLAD()
|
||||
{
|
||||
// we load address of OGL OS-specific function pointers
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
print("Failed to initialize GLAD");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// resizes viewport when user resizes window
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
void viewPort(GLFWwindow* window)
|
||||
{
|
||||
// We tell OGL size of rendering window
|
||||
// First two define left corner of window
|
||||
// 3th and 4th width and height of rendering window
|
||||
// we could set them to be smaller than window dimension, ogl rendering will be then displayed in smaller window
|
||||
glViewport(0, 0, constants::MAIN_WINDOW_WIDTH, constants::MAIN_WINDOW_HEIGHT);
|
||||
// processed coordinates are between -1 and 1 so here we map:
|
||||
// (-1 to 1) to (0, constants::MAIN_WINDOW_WIDTH) and (0, constants::MAIN_WINDOW_HEIGHT)
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
// we call framebuffer_size_callback on every window resize
|
||||
}
|
||||
|
||||
GLFWwindow* prepareForRender()
|
||||
{
|
||||
instantiateGLFWwindow();
|
||||
|
||||
GLFWwindow* window = createWindowObject();
|
||||
// function returns GLFWWindow object
|
||||
|
||||
if (window == NULL)
|
||||
{
|
||||
print("Failed to create GLFW window");
|
||||
glfwTerminate();
|
||||
return window;
|
||||
}
|
||||
// we make context of this window main context of current thread
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
if(initializeGLAD() == -1) return NULL;
|
||||
viewPort(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
#endif
|
||||
13
Engine/engine/beforeRender.hpp
Normal file
13
Engine/engine/beforeRender.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef BEFORE_RENDER_HPP
|
||||
#define BEFORE_RENDER_HPP
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
void configureGLFW(const int GLFWMajorVersion, const int GLFWMinorVersion);
|
||||
void instantiateGLFWwindow();
|
||||
GLFWwindow* createWindowObject();
|
||||
int initializeGLAD();
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
|
||||
void viewPort(GLFWwindow* window);
|
||||
GLFWwindow* prepareForRender();
|
||||
|
||||
#endif
|
||||
@ -1,10 +1,13 @@
|
||||
#ifndef CONSTANTS_HPP
|
||||
#define CONSTANTS_HPP
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
|
||||
namespace constants
|
||||
{
|
||||
inline constexpr int GLFW_MAJOR_VERSION { 3 };
|
||||
inline constexpr int GLFW_MINOR_VERSION { 3 };
|
||||
// best practice is to use inline constexpr std::string_view but glfwCreateWindow takes only char* as input
|
||||
inline const char* MAIN_WINDOW_NAME { "Match" };
|
||||
inline constexpr int MAIN_WINDOW_WIDTH { 800 };
|
||||
|
||||
93
Engine/engine/draw.cpp
Normal file
93
Engine/engine/draw.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef DRAW_CPP
|
||||
#define DRAW_CPP
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
#include "draw.hpp"
|
||||
#include "renderLoop.hpp"
|
||||
#include "shaders.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "misc.hpp"
|
||||
|
||||
int drawFigure(const bool whatToDraw)
|
||||
{
|
||||
if(whatToDraw)
|
||||
{
|
||||
if(drawTriangle() == -1)
|
||||
{
|
||||
print("Error with drawing triangle! ");
|
||||
return -1;
|
||||
}
|
||||
}else
|
||||
{
|
||||
if(drawSquare() == -1)
|
||||
{
|
||||
print("Error with drawing square! ");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drawSquare()
|
||||
{
|
||||
std::pair<unsigned int, unsigned int> shaders = compileShaders();
|
||||
if(shaders.first == 0 || shaders.second == 0) return -1;
|
||||
|
||||
unsigned int shaderProgram = linkShaderObjectsShaderProgram(shaders.first, shaders.second);
|
||||
if(shaderProgram == 0) return -1;
|
||||
|
||||
unsigned int VAO = generateBindVAO();
|
||||
copyVerticesMemory<float>(constants::SQUARE_VERTICES, constants::SQUARE_VERTICES_SIZE, GL_ARRAY_BUFFER);
|
||||
copyVerticesMemory<unsigned int>(constants::SQUARE_INDICES, constants::SQUARE_INDICES_SIZE, GL_ELEMENT_ARRAY_BUFFER);
|
||||
|
||||
// set vertex attribute pointers
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
doDrawElements(shaderProgram, VAO, GL_TRIANGLES, GL_UNSIGNED_INT, std::size(constants::SQUARE_INDICES));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void doDrawElements(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const GLenum drawType, const int numberOfElementsToDraw)
|
||||
{
|
||||
glUseProgram(shaderProgram);
|
||||
glBindVertexArray(vertexArrayObject);
|
||||
glDrawElements(drawArrayMode, numberOfElementsToDraw, drawType, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
int drawTriangle()
|
||||
{
|
||||
unsigned int vertexBufferObject = copyVerticesMemory(constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, GL_ARRAY_BUFFER);
|
||||
|
||||
std::pair<unsigned int, unsigned int> shaders = compileShaders();
|
||||
if(shaders.first == 0 || shaders.second == 0) return -1;
|
||||
|
||||
unsigned int shaderProgram = linkShaderObjectsShaderProgram(shaders.first, shaders.second);
|
||||
if(shaderProgram == 0) return -1;
|
||||
|
||||
configureVertexAttribute();
|
||||
unsigned int vertexArrayObject = generateBindVAO();
|
||||
copyVerticesArray(vertexBufferObject, constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, GL_ARRAY_BUFFER);
|
||||
|
||||
// set vertex attribute pointers
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
doDrawArrays(shaderProgram, vertexArrayObject, GL_TRIANGLES, 0, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void doDrawArrays(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const int firstIndex, const unsigned int numberOfIndicesToBeRendered )
|
||||
{
|
||||
// use shader program to render an object
|
||||
glUseProgram(shaderProgram);
|
||||
glBindVertexArray(vertexArrayObject);
|
||||
// From left:
|
||||
// primitive type we want to draw
|
||||
// starting index of vertex array
|
||||
// how many vertices we want to draw
|
||||
glDrawArrays(drawArrayMode, firstIndex, numberOfIndicesToBeRendered);
|
||||
}
|
||||
|
||||
#endif
|
||||
12
Engine/engine/draw.hpp
Normal file
12
Engine/engine/draw.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef DRAW_HPP
|
||||
#define DRAW_HPP
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
int drawFigure(const bool whatToDraw);
|
||||
int drawSquare();
|
||||
void doDrawElements(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const GLenum drawType, const int numberOfElementsToDraw);
|
||||
int drawTriangle();
|
||||
void doDrawArrays(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const int firstIndex, const unsigned int numberOfIndicesToBeRendered );
|
||||
|
||||
#endif
|
||||
BIN
Engine/engine/match
Executable file → Normal file
BIN
Engine/engine/match
Executable file → Normal file
Binary file not shown.
@ -1,375 +1,23 @@
|
||||
#ifndef MAIN_CPP
|
||||
|
||||
#define MAIN_CPP
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <random> // I am using standart library RNG because I am lazy and wanted to create quick code snippet
|
||||
// upgrade to this: https://arvid.io/2018/06/30/on-cxx-random-number-generator-quality/ whenever, if ever I feel like it
|
||||
#include <chrono> // for std::chrono
|
||||
|
||||
#include "constants.hpp"
|
||||
|
||||
void configureGLFW() {
|
||||
// first argument tells us what option to configure
|
||||
// second is to what we set the value of this option
|
||||
// see: https://www.glfw.org/docs/latest/window.html#window_hints
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
// we set GLFW to 3.3 CORE
|
||||
// core profile gives us access to smaller subset of OGL without backwards compatible features
|
||||
|
||||
// if we are on Mac OS X we need this for our code to work
|
||||
#ifdef __APPLE__
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void instantiateGLFWwindow() {
|
||||
// Initialize GLFW
|
||||
glfwInit();
|
||||
configureGLFW();
|
||||
}
|
||||
|
||||
GLFWwindow* createWindowObject() {
|
||||
// First two arguments are width and height
|
||||
// Third is the name of the window
|
||||
// We ignore last two
|
||||
GLFWwindow* window = glfwCreateWindow(constants::MAIN_WINDOW_WIDTH, constants::MAIN_WINDOW_HEIGHT, constants::MAIN_WINDOW_NAME, NULL, NULL);
|
||||
return window;
|
||||
}
|
||||
|
||||
int initializeGLAD()
|
||||
{
|
||||
// we load address of OGL OS-specific function pointers
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
|
||||
{
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// resizes viewport when user resizes window
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||
{
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
void viewPort(GLFWwindow* window)
|
||||
{
|
||||
// We tell OGL size of rendering window
|
||||
// First two define left corner of window
|
||||
// 3th and 4th width and height of rendering window
|
||||
// we could set them to be smaller than window dimension, ogl rendering will be then displayed in smaller window
|
||||
glViewport(0, 0, constants::MAIN_WINDOW_WIDTH, constants::MAIN_WINDOW_HEIGHT);
|
||||
// processed coordinates are between -1 and 1 so here we map:
|
||||
// (-1 to 1) to (0, constants::MAIN_WINDOW_WIDTH) and (0, constants::MAIN_WINDOW_HEIGHT)
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
// we call framebuffer_size_callback on every window resize
|
||||
}
|
||||
|
||||
bool processInput(GLFWwindow *window, 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;
|
||||
}
|
||||
|
||||
int shaderProgramLinkingSuccessful(const unsigned int shaderProgram)
|
||||
{
|
||||
// check if compilation was successful
|
||||
// int because glGetShaderiv requires int
|
||||
int successfulLinking;
|
||||
// here we store info about compilation
|
||||
char infoLog[512];
|
||||
// check if compilation was successful
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successfulLinking);
|
||||
// if not display compilation log
|
||||
if(!successfulLinking)
|
||||
{
|
||||
glGetProgramInfoLog(shaderProgram, sizeof(infoLog) / sizeof(infoLog[0]), NULL, infoLog);
|
||||
std::cout << "ERROR shaderProgram compilation failed \n" << infoLog << std::endl;
|
||||
}
|
||||
return successfulLinking;
|
||||
}
|
||||
|
||||
|
||||
int shaderCompilationSuccessful(const unsigned int shader)
|
||||
{
|
||||
// check if compilation was successful
|
||||
// int because glGetShaderiv requires int
|
||||
int successfulCompilation;
|
||||
// here we store info about compilation
|
||||
char infoLog[512];
|
||||
// check if compilation was successful
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &successfulCompilation);
|
||||
// if not display compilation log
|
||||
if(!successfulCompilation)
|
||||
{
|
||||
glGetShaderInfoLog(shader, sizeof(infoLog) / sizeof(infoLog[0]), NULL, infoLog);
|
||||
std::cout << "ERROR vertex shader compilation failed \n" << infoLog << std::endl;
|
||||
}
|
||||
return successfulCompilation;
|
||||
}
|
||||
|
||||
unsigned int compileShader(const GLenum shaderType, const char * shaderSource)
|
||||
{
|
||||
// we create vertex shader and assign its id to shader variable
|
||||
unsigned int shaderID;
|
||||
shaderID = glCreateShader(shaderType);
|
||||
|
||||
// attach shader source code to shader object
|
||||
// from left: shader object to compile, how many strings as source code, actual source code (we leave the 4th as NULL)
|
||||
glShaderSource(shaderID, 1, &shaderSource, NULL);
|
||||
// compile shader
|
||||
glCompileShader(shaderID);
|
||||
if(!shaderCompilationSuccessful(shaderID)) return 0;
|
||||
return shaderID;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
// https://stackoverflow.com/a/25680092
|
||||
unsigned int copyVerticesMemory(const T 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;
|
||||
}
|
||||
|
||||
std::pair<unsigned int, unsigned int> compileShaders()
|
||||
{
|
||||
unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, constants::vertexShaderSource);
|
||||
if(vertexShader == 0)
|
||||
{
|
||||
std::cout << "Vertex Shader Compilation Failed" << std::endl;
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, constants::fragmentShaderSource);
|
||||
if(fragmentShader == 0)
|
||||
{
|
||||
std::cout << "Fragment Shader Compilation Failed" << std::endl;
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
return std::make_pair(vertexShader, fragmentShader);
|
||||
}
|
||||
|
||||
unsigned int linkShaderObjectsShaderProgram(unsigned int vertexShaders, unsigned int fragmentShader)
|
||||
{
|
||||
// link shader objects into shader program
|
||||
// will store shader program id
|
||||
unsigned int shaderProgram;
|
||||
// creates program
|
||||
shaderProgram = glCreateProgram();
|
||||
|
||||
// attachShaders
|
||||
glAttachShader(shaderProgram, vertexShaders);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
|
||||
// link shaders
|
||||
glLinkProgram(shaderProgram);
|
||||
if(!shaderProgramLinkingSuccessful(shaderProgram)) return 0;
|
||||
|
||||
// activate program
|
||||
// after that every shader and rendering call will use this program object
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
// delete shaders (they are linked into shaderProgram and we do not need them anymore)
|
||||
glDeleteShader(vertexShaders);
|
||||
glDeleteShader(fragmentShader);
|
||||
if(shaderProgram == 0) std::cout << "Shader Program Linking Failed" << std::endl;
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
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(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);
|
||||
}
|
||||
|
||||
void doDrawArrays(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const int firstIndex, const unsigned int numberOfIndicesToBeRendered )
|
||||
{
|
||||
// use shader program to render an object
|
||||
glUseProgram(shaderProgram);
|
||||
glBindVertexArray(vertexArrayObject);
|
||||
// From left:
|
||||
// primitive type we want to draw
|
||||
// starting index of vertex array
|
||||
// how many vertices we want to draw
|
||||
glDrawArrays(drawArrayMode, firstIndex, numberOfIndicesToBeRendered);
|
||||
}
|
||||
|
||||
int drawTriangle()
|
||||
{
|
||||
unsigned int vertexBufferObject = copyVerticesMemory(constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, GL_ARRAY_BUFFER);
|
||||
|
||||
std::pair<unsigned int, unsigned int> shaders = compileShaders();
|
||||
if(shaders.first == 0 || shaders.second == 0) return -1;
|
||||
|
||||
unsigned int shaderProgram = linkShaderObjectsShaderProgram(shaders.first, shaders.second);
|
||||
if(shaderProgram == 0) return -1;
|
||||
|
||||
configureVertexAttribute();
|
||||
unsigned int vertexArrayObject = generateBindVAO();
|
||||
copyVerticesArray(vertexBufferObject, constants::TRIANGLE_VERTICES, constants::TRIANGLE_VERTICES_SIZE, GL_ARRAY_BUFFER);
|
||||
|
||||
// set vertex attribute pointers
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
doDrawArrays(shaderProgram, vertexArrayObject, GL_TRIANGLES, 0, 3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void doDrawElements(const unsigned int shaderProgram, const unsigned int vertexArrayObject, const GLenum drawArrayMode, const GLenum drawType, const int numberOfElementsToDraw)
|
||||
{
|
||||
glUseProgram(shaderProgram);
|
||||
glBindVertexArray(vertexArrayObject);
|
||||
glDrawElements(drawArrayMode, numberOfElementsToDraw, drawType, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
int drawSquare()
|
||||
{
|
||||
std::pair<unsigned int, unsigned int> shaders = compileShaders();
|
||||
if(shaders.first == 0 || shaders.second == 0) return -1;
|
||||
|
||||
unsigned int shaderProgram = linkShaderObjectsShaderProgram(shaders.first, shaders.second);
|
||||
if(shaderProgram == 0) return -1;
|
||||
|
||||
unsigned int VAO = generateBindVAO();
|
||||
copyVerticesMemory<float>(constants::SQUARE_VERTICES, constants::SQUARE_VERTICES_SIZE, GL_ARRAY_BUFFER);
|
||||
copyVerticesMemory<unsigned int>(constants::SQUARE_INDICES, constants::SQUARE_INDICES_SIZE, GL_ELEMENT_ARRAY_BUFFER);
|
||||
|
||||
// set vertex attribute pointers
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
doDrawElements(shaderProgram, VAO, GL_TRIANGLES, GL_UNSIGNED_INT, std::size(constants::SQUARE_INDICES));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drawFigure(const bool whatToDraw)
|
||||
{
|
||||
if(whatToDraw)
|
||||
{
|
||||
if(drawTriangle() == -1)
|
||||
{
|
||||
std::cout << "Error with drawing triangle! " << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}else
|
||||
{
|
||||
if(drawSquare() == -1)
|
||||
{
|
||||
std::cout << "Error with drawing square! " << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void renderLoop(GLFWwindow* window)
|
||||
{
|
||||
bool whatToDraw = true;
|
||||
// glfwWindowShouldClose checks if GLFW was instructed to close
|
||||
while(!glfwWindowShouldClose(window))
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
std::cout << "error with drawing!" << std::endl;
|
||||
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();
|
||||
}
|
||||
}
|
||||
#include "beforeRender.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "renderLoop.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
instantiateGLFWwindow();
|
||||
|
||||
GLFWwindow* window = createWindowObject();
|
||||
// function returns GLFWWindow object
|
||||
|
||||
if (window == NULL)
|
||||
{
|
||||
std::cout << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
// we make context of this window main context of current thread
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
if(initializeGLAD() == -1) return -1;
|
||||
viewPort(window);
|
||||
|
||||
GLFWwindow* window = prepareForRender();
|
||||
if(window == NULL) return -1;
|
||||
renderLoop(window);
|
||||
|
||||
// clean GLFW resources
|
||||
|
||||
10
Engine/engine/misc.cpp
Normal file
10
Engine/engine/misc.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef MISC_CPP
|
||||
#define MISC_CPP
|
||||
#include <iostream>
|
||||
#include "misc.hpp"
|
||||
void print(const std::string s)
|
||||
{
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
6
Engine/engine/misc.hpp
Normal file
6
Engine/engine/misc.hpp
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef MISC_HPP
|
||||
#define MISC_HPP
|
||||
#include <iostream>
|
||||
|
||||
void print(const std::string s);
|
||||
#endif
|
||||
131
Engine/engine/renderLoop.cpp
Normal file
131
Engine/engine/renderLoop.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#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, 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;
|
||||
}
|
||||
|
||||
unsigned int compileShader(const GLenum shaderType, const char * shaderSource)
|
||||
{
|
||||
// we create vertex shader and assign its id to shader variable
|
||||
unsigned int shaderID;
|
||||
shaderID = glCreateShader(shaderType);
|
||||
|
||||
// attach shader source code to shader object
|
||||
// from left: shader object to compile, how many strings as source code, actual source code (we leave the 4th as NULL)
|
||||
glShaderSource(shaderID, 1, &shaderSource, NULL);
|
||||
// compile shader
|
||||
glCompileShader(shaderID);
|
||||
if(!shaderCompilationSuccessful(shaderID)) return 0;
|
||||
return shaderID;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
// https://stackoverflow.com/a/25680092
|
||||
unsigned int copyVerticesMemory(const T 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(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
|
||||
18
Engine/engine/renderLoop.hpp
Normal file
18
Engine/engine/renderLoop.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef RENDER_LOOP_HPP
|
||||
#define RENDER_LOOP_HPP
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
|
||||
void renderLoop(GLFWwindow* window);
|
||||
bool renderLoopInside(GLFWwindow* window, bool whatToDraw);
|
||||
void copyVerticesArray(unsigned int vertexBufferObject, const float vertices[], const size_t sizeOfVertices, const GLenum boundBufferTarget);
|
||||
unsigned int generateBindVAO();
|
||||
void configureVertexAttribute();
|
||||
bool processInput(GLFWwindow *window, bool whatToDraw);
|
||||
|
||||
template <class T> unsigned int copyVerticesMemory(const T vertices[], const size_t sizeOfVertices, const GLenum boundBufferTarget);
|
||||
|
||||
|
||||
#endif
|
||||
91
Engine/engine/shaders.cpp
Normal file
91
Engine/engine/shaders.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef SHADERS_CPP
|
||||
#define SHADERS_CPP
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "shaders.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "misc.hpp"
|
||||
|
||||
|
||||
unsigned int linkShaderObjectsShaderProgram(unsigned int vertexShaders, unsigned int fragmentShader)
|
||||
{
|
||||
// link shader objects into shader program
|
||||
// will store shader program id
|
||||
unsigned int shaderProgram;
|
||||
// creates program
|
||||
shaderProgram = glCreateProgram();
|
||||
|
||||
// attachShaders
|
||||
glAttachShader(shaderProgram, vertexShaders);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
|
||||
// link shaders
|
||||
glLinkProgram(shaderProgram);
|
||||
if(!shaderProgramLinkingSuccessful(shaderProgram)) return 0;
|
||||
|
||||
// activate program
|
||||
// after that every shader and rendering call will use this program object
|
||||
glUseProgram(shaderProgram);
|
||||
|
||||
// delete shaders (they are linked into shaderProgram and we do not need them anymore)
|
||||
glDeleteShader(vertexShaders);
|
||||
glDeleteShader(fragmentShader);
|
||||
if(shaderProgram == 0) print("Shader Program Linking Failed");
|
||||
return shaderProgram;
|
||||
}
|
||||
|
||||
std::pair<unsigned int, unsigned int> compileShaders()
|
||||
{
|
||||
unsigned int vertexShader = compileShader(GL_VERTEX_SHADER, constants::vertexShaderSource);
|
||||
if(vertexShader == 0)
|
||||
{
|
||||
print("Vertex Shader Compilation Failed");
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
unsigned int fragmentShader = compileShader(GL_FRAGMENT_SHADER, constants::fragmentShaderSource);
|
||||
if(fragmentShader == 0)
|
||||
{
|
||||
print("Fragment Shader Compilation Failed");
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
return std::make_pair(vertexShader, fragmentShader);
|
||||
}
|
||||
|
||||
int shaderCompilationSuccessful(const unsigned int shader)
|
||||
{
|
||||
// check if compilation was successful
|
||||
// int because glGetShaderiv requires int
|
||||
int successfulCompilation;
|
||||
// here we store info about compilation
|
||||
char infoLog[512];
|
||||
// check if compilation was successful
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &successfulCompilation);
|
||||
// if not display compilation log
|
||||
if(!successfulCompilation)
|
||||
{
|
||||
glGetShaderInfoLog(shader, sizeof(infoLog) / sizeof(infoLog[0]), NULL, infoLog);
|
||||
std::cout << "ERROR vertex shader compilation failed \n" << infoLog << std::endl;
|
||||
}
|
||||
return successfulCompilation;
|
||||
}
|
||||
|
||||
int shaderProgramLinkingSuccessful(const unsigned int shaderProgram)
|
||||
{
|
||||
// check if compilation was successful
|
||||
// int because glGetShaderiv requires int
|
||||
int successfulLinking;
|
||||
// here we store info about compilation
|
||||
char infoLog[512];
|
||||
// check if compilation was successful
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &successfulLinking);
|
||||
// if not display compilation log
|
||||
if(!successfulLinking)
|
||||
{
|
||||
glGetProgramInfoLog(shaderProgram, sizeof(infoLog) / sizeof(infoLog[0]), NULL, infoLog);
|
||||
std::cout << "ERROR shaderProgram compilation failed \n" << infoLog << std::endl;
|
||||
}
|
||||
return successfulLinking;
|
||||
}
|
||||
|
||||
#endif
|
||||
14
Engine/engine/shaders.hpp
Normal file
14
Engine/engine/shaders.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef SHADERS_HPP
|
||||
#define SHADERS_HPP
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
|
||||
unsigned int linkShaderObjectsShaderProgram(unsigned int vertexShaders, unsigned int fragmentShader);
|
||||
std::pair<unsigned int, unsigned int> compileShaders();
|
||||
unsigned int compileShader(const GLenum shaderType, const char * shaderSource);
|
||||
int shaderCompilationSuccessful(const unsigned int shader);
|
||||
int shaderProgramLinkingSuccessful(const unsigned int shaderProgram);
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user