2022-08-29 21:01:55 +02:00
# ifndef MAIN_CPP
2022-08-28 19:20:00 +02:00
# include <glad/glad.h>
2022-08-27 21:43:58 +02:00
# include <GLFW/glfw3.h>
2022-08-28 19:20:00 +02:00
2022-08-29 19:53:36 +02:00
# include <iostream>
2022-08-30 20:02:22 +02:00
# 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
2022-08-29 21:01:55 +02:00
# 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
2022-08-29 19:53:36 +02:00
glfwWindowHint ( GLFW_CONTEXT_VERSION_MAJOR , 3 ) ;
2022-08-28 19:20:00 +02:00
glfwWindowHint ( GLFW_CONTEXT_VERSION_MINOR , 3 ) ;
glfwWindowHint ( GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE ) ;
2022-08-29 21:01:55 +02:00
// 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
}
2022-08-28 19:20:00 +02:00
2022-08-29 21:01:55 +02:00
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 ( )
2022-08-29 19:53:36 +02:00
{
2022-08-29 21:01:55 +02:00
// 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 ;
2022-08-28 19:20:00 +02:00
}
2022-08-27 21:43:58 +02:00
2022-08-29 21:01:55 +02:00
// resizes viewport when user resizes window
void framebuffer_size_callback ( GLFWwindow * window , int width , int height )
{
glViewport ( 0 , 0 , width , height ) ;
}
2022-08-29 19:53:36 +02:00
2022-08-29 21:01:55 +02:00
void viewPort ( GLFWwindow * window )
2022-08-28 19:20:00 +02:00
{
2022-08-29 21:01:55 +02:00
// 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
}
2022-08-30 20:02:22 +02:00
void processInput ( GLFWwindow * window )
{
// 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 ) ;
}
2022-08-31 20:40:41 +02:00
void drawTriangle ( )
2022-08-30 20:02:22 +02:00
{
2022-08-31 20:40:41 +02:00
// we specify three vertices
// each of them with position in 3d space
// x y z
const float triangleVertices [ ] = {
- 0.5f , - 0.5f , 0.0f ,
0.5f , - 0.5f , 0.0f ,
0.0f , 0.5f , 0.0f
} ;
// 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 ( GL_ARRAY_BUFFER , 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 ( GL_ARRAY_BUFFER , sizeof ( triangleVertices ) , triangleVertices , GL_STATIC_DRAW ) ;
// we write vertex shader
// version of glsl (since ogl 3.3 same as ogl so we pick 330)
// in this shader we just forward input data to shader output
const char * vertexShaderSource = " #version 330 core \n "
" layout (location = 0) in vec3 aPos; \n "
" void main() \n "
" { \n "
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); \n "
" } \0 " ;
2022-08-30 20:02:22 +02:00
}
2022-08-29 21:01:55 +02:00
void renderLoop ( GLFWwindow * window )
{
2022-08-30 20:02:22 +02:00
// glfwWindowShouldClose checks if GLFW was instructed to close
2022-08-29 21:01:55 +02:00
while ( ! glfwWindowShouldClose ( window ) )
{
2022-08-30 20:02:22 +02:00
// input
processInput ( window ) ;
2022-08-31 20:40:41 +02:00
// 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
2022-08-30 20:02:22 +02:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
// 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
2022-08-29 21:01:55 +02:00
glfwSwapBuffers ( window ) ;
2022-08-30 20:02:22 +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)
2022-08-29 21:01:55 +02:00
glfwPollEvents ( ) ;
2022-08-30 20:02:22 +02:00
2022-08-29 21:01:55 +02:00
}
}
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 ) ;
renderLoop ( window ) ;
2022-08-30 20:02:22 +02:00
// clean GLFW resources
glfwTerminate ( ) ;
2022-08-28 19:20:00 +02:00
return 0 ;
2022-08-29 21:01:55 +02:00
}
# endif