diff --git a/App/App/CMakeLists.txt b/App/App/CMakeLists.txt index ef03082..3d34afb 100644 --- a/App/App/CMakeLists.txt +++ b/App/App/CMakeLists.txt @@ -12,14 +12,18 @@ add_executable(App ) find_package(SDL2 CONFIG REQUIRED) -find_package(OpenGL REQUIRED) +find_package(OpenGL REQUIRED COMPONENTS OpenGL) find_package(GLEW REQUIRED) +find_package(GLUT REQUIRED) +find_package(glad CONFIG REQUIRED) target_link_libraries(App PRIVATE AppLib SDL2::SDL2 SDL2::SDL2main OpenGL::GL GLEW::GLEW + GLUT::GLUT + glad::glad ) target_include_directories(App PUBLIC "${CMAKE_SOURCE_DIR}/App/include/") diff --git a/App/App/include/App.hh b/App/App/include/App.hh index 84f0939..8e36491 100644 --- a/App/App/include/App.hh +++ b/App/App/include/App.hh @@ -2,8 +2,8 @@ #include "GL/glew.h" #include "SDL2/SDL.h" -// #include "SDL2/SDL_vulkan.h" #include "SDL2/SDL_opengl.h" +// #include "SDL2/SDL_vulkan.h" #include "Logger.hh" #include "Controller.hh" @@ -25,6 +25,9 @@ namespace App SDL_GLContext m_glContext; bool m_Quit; bool m_VSync; + GLuint m_vbo; + GLuint m_vao; + GLuint m_prog; public: App(/* args */); int getReturnCode() const; diff --git a/App/App/src/App.cpp b/App/App/src/App.cpp index 57ef6d9..157a688 100644 --- a/App/App/src/App.cpp +++ b/App/App/src/App.cpp @@ -9,9 +9,40 @@ #endif -//TODO (Eero): https://github.com/theandrew168/sdl2-opengl-demo/blob/master/src/main.c +//TODO (Eero): https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/2.2.hello_triangle_indexed/hello_triangle_indexed.cpp namespace App { + const float SQUARE[] = { + -1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, 1.0f, + 1.0f, -1.0f + }; + + static bool + opengl_shader_compile_source(GLuint shader, const GLchar* source) + { + glShaderSource(shader, 1, &source, NULL); + glCompileShader(shader); + + GLint success; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (success != GL_TRUE) { + GLint info_log_length; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length); + + // GLchar* info_log = malloc(info_log_length); + // glGetShaderInfoLog(shader, info_log_length, NULL, info_log); + + fprintf(stderr, "failed to compile shader:\n%s\n", "asd"); + // free(info_log); + + return false; + } + + return true; + } + App::App() : m_ReturnCode(0), m_WindowWidth(800), m_WindowHeight(600), m_Quit(false), m_VSync(false) { float vertices[] = { @@ -20,86 +51,73 @@ namespace App 0.0f, 0.5f, 0.0f }; - // printf("OpenGL Vendor: %s\n", glGetString(GL_VENDOR)); - // printf("OpenGL Renderer: %s\n", glGetString(GL_RENDERER)); - // printf("OpenGL Version: %s\n", glGetString(GL_VERSION)); - // printf("GLSL Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); - // Vertex Shader Part - unsigned int VBO; - glGenBuffers(1, &VBO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - 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"; - unsigned int vertexShader; - vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); - glCompileShader(vertexShader); - - int success; - char infoLog[512]; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); - if(!success) - { - glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; - } - - // Fragment Shader Part - unsigned int fragmentShader; - fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); - glCompileShader(fragmentShader); - - - glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); - if(!success) { - glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::FRAGMET::COMPILATION_FAILED\n" << infoLog << std::endl; - } - - unsigned int shaderProgram; - shaderProgram = glCreateProgram(); - glAttachShader(shaderProgram, vertexShader); - glAttachShader(shaderProgram, fragmentShader); - glLinkProgram(shaderProgram); - - glUseProgram(shaderProgram); - - // Oh yeah, and don't forget to delete the shader objects once we've linked them into the program object; we no longer need them anymore: - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - glEnableVertexAttribArray(0); + // int success; + // char infoLog[512]; + // glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + // if(!success) + // { + // glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); + // std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; + // } + // glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); + // if(!success) { + // glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); + // std::cout << "ERROR::SHADER::FRAGMET::COMPILATION_FAILED\n" << infoLog << std::endl; + // } - // // 0. copy our vertices array in a buffer for OpenGL to use - // glBindBuffer(GL_ARRAY_BUFFER, VBO); - // glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - // // 1. then set the vertex attributes pointers - // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - // glEnableVertexAttribArray(0); - // // 2. use our shader program when we want to render an object - // glUseProgram(shaderProgram); - // // 3. now draw the object - // someOpenGLFunctionThatDrawsOurTriangle(); + // Do modern OpenGL stuff + const GLchar *vs_source = + "#version 330\n" + "layout(location = 0) in vec2 point;\n" + "uniform float angle;\n" + "void main() {\n" + " mat2 rotate = mat2(cos(angle), -sin(angle),\n" + " sin(angle), cos(angle));\n" + " gl_Position = vec4(0.75 * rotate * point, 0.0, 1.0);\n" + "}\n"; + const GLchar *fs_source = + "#version 330\n" + "out vec4 color;\n" + "void main() {\n" + " color = vec4(1, 0.15, 0.15, 0);\n" + "}\n"; + + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + opengl_shader_compile_source(vs, vs_source); + opengl_shader_compile_source(fs, fs_source); + + m_prog = glCreateProgram(); + opengl_shader_link_program(m_prog, vs, fs); + + GLint uniform_angle = glGetUniformLocation(m_prog, "angle"); + + glDeleteShader(fs); + glDeleteShader(vs); + + + glGenBuffers(1, &m_vbo); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(SQUARE), SQUARE, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glGenVertexArrays(1, &m_vao); + glBindVertexArray(m_vao); + glBindBuffer(GL_ARRAY_BUFFER, m_vbo); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + std::cout << "Eternity Engine" << std::endl; m_Logger = std::make_shared(); m_Controller = std::make_shared(); - //Use OpenGL 3.1 core - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - if(SDL_Init(SDL_INIT_VIDEO) < 0) { std::cout << "SDL could not be initialized!" << std::endl @@ -108,6 +126,18 @@ namespace App return; } + // Request at least 32-bit color + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + // Request a double-buffered, OpenGL 3.3 (or higher) core profile + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + // SDL_Vulkan_LoadLibrary(nullptr); m_Window = SDL_CreateWindow("App", SDL_WINDOWPOS_UNDEFINED, @@ -133,6 +163,10 @@ namespace App } else { + long frame_count = 0; + unsigned long last_frame = 0; + unsigned long last_second = 0; + double angle = 0.0; // Event loop exit flag m_Quit = false; Uint32 command = 0; @@ -156,14 +190,39 @@ namespace App command = m_Controller->HandleEvent(&e); handleCommand(command); - // Set background color as cornflower blue - glClearColor(0.39f, 0.58f, 0.93f, 1.f); - // Clear color buffer - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glUseProgram(shaderProgram); - glBindVertexArray(VAO); - // someOpenGLFunctionThatDrawsOurTriangle(); - // Update window with OpenGL rendering + // // Set background color as cornflower blue + // glClearColor(0.39f, 0.58f, 0.93f, 1.f); + // // Clear color buffer + // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // glUseProgram(shaderProgram); + // glBindVertexArray(m_VAO); + // // someOpenGLFunctionThatDrawsOurTriangle(); + // // Update window with OpenGL rendering + // SDL_GL_SwapWindow(m_Window); + + glClearColor(0.15f, 0.15f, 0.15f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glUseProgram(m_prog); + glUniform1f(uniform_angle, angle); + glBindVertexArray(m_vao); + glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(SQUARE) / sizeof(*SQUARE) / 2); + glBindVertexArray(0); + glUseProgram(0); + unsigned long now = SDL_GetTicks(); + unsigned long diff = now - last_frame; + last_frame = now; + + angle += diff / 1000.0; + if (angle > 2 * M_PI) angle -= 2 * M_PI; + + if (now - last_second >= 1000) { + printf("FPS: %ld\n", frame_count); + frame_count = 0; + last_second = now; + } + + frame_count++; SDL_GL_SwapWindow(m_Window); } } @@ -174,9 +233,9 @@ namespace App App::~App() { - glDeleteVertexArrays(1, &VAO); - glDeleteBuffers(1, &VBO); - glDeleteProgram(shaderProgram); + glDeleteVertexArrays(1, &m_vao); + glDeleteBuffers(1, &m_vbo); + glDeleteProgram(m_prog); SDL_DestroyWindow(m_Window); SDL_Quit(); m_Logger.reset();