diff --git a/CMakeLists.txt b/CMakeLists.txt index da5e962..c987ee2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,9 @@ file(GLOB IMGUI_SOURCES "${CMAKE_SOURCE_DIR}/imgui/backends/imgui_impl_opengl3.cpp" ) +message(STATUS "Sources: ${SOURCES}") + + # Add the executable add_executable(TerraVisor ${SOURCES} ${HEADERS} ${IMGUI_SOURCES}) diff --git a/include/Callbacks.h b/include/Callbacks.h new file mode 100644 index 0000000..e07440b --- /dev/null +++ b/include/Callbacks.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace Callbacks +{ + void Register(GLFWwindow* window); + + void Keyboard(GLFWwindow* window, int key, int scancode, int action, int mods); + void MouseCursor(GLFWwindow* window, double x, double y); + void MouseButton(GLFWwindow* window, int button, int action, int mods); + void Resize(GLFWwindow* window, int width, int height); +}; diff --git a/include/DebugCallback.h b/include/DebugCallback.h new file mode 100644 index 0000000..ecad42c --- /dev/null +++ b/include/DebugCallback.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + + +/* +OpenGL debug message callbacks are a more convenient and performant alternative to glGetError(...). +When you register a debug message callback the openglCallbackFunction() below will be automatically called +by OpenGL when errors or warnings are detected. + +More details about this feature are at: https://blog.nobel-joergensen.com/2013/02/17/debugging-opengl-part-2-using-gldebugmessagecallback/ +*/ + +//Follow the following steps to add the debug callback to your application: + +/* 1. Create an OpenGL context with debugging enabled in debug builds of the application. +(Check Preprocessor options - _DEBUG should be defined in debug builds) +Include the following before the window is created. + +#ifdef _DEBUG + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); +#endif +*/ + +/* 2. Register the debug callback function when you are running a debug build. +You can do this by calling RegisterDebugCallback(); after glewInit(). Be sure to include this header file. + +*/ + +/* 3. You will see a lot of output on the text console when it is working. Not only errors are reported +by default. You will also see a lot of performance warnings and other messages (specifics depend on driver). +*/ +void RegisterDebugCallback(); + +void APIENTRY openglCallbackFunction(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam); \ No newline at end of file diff --git a/include/InitShader.h b/include/InitShader.h new file mode 100644 index 0000000..a04638e --- /dev/null +++ b/include/InitShader.h @@ -0,0 +1,12 @@ +#ifndef __INITSHADER_H__ +#define __INITSHADER_H__ + +#include +#include + +GLuint InitShader( const char* computeShaderFile); +GLuint InitShader( const char* vertexShaderFile, const char* fragmentShaderFile ); +GLuint InitShader( const char* vertexShaderFile, const char* geometryShader, const char* fragmentShaderFile ); + + +#endif \ No newline at end of file diff --git a/include/Uniforms.h b/include/Uniforms.h new file mode 100644 index 0000000..1cc2552 --- /dev/null +++ b/include/Uniforms.h @@ -0,0 +1,57 @@ +#pragma once + +#include +#include + +namespace Uniforms +{ + void Init(); + void BufferSceneData(); + + //This structure mirrors the uniform block declared in the shader + struct SceneUniforms + { + glm::mat4 PV; //camera projection * view matrix + glm::vec4 eye_w = glm::vec4(0.0f, 0.0f, 3.0f, 1.0f); //world-space eye position + }; + + struct LightUniforms + { + glm::vec4 La = glm::vec4(0.5f, 0.5f, 0.55f, 1.0f); //ambient light color + glm::vec4 Ld = glm::vec4(0.5f, 0.5f, 0.25f, 1.0f); //diffuse light color + glm::vec4 Ls = glm::vec4(0.3f); //specular light color + glm::vec4 light_w = glm::vec4(0.0f, 1.2, 1.0f, 1.0f); //world-space light position + }; + + struct MaterialUniforms + { + glm::vec4 ka = glm::vec4(1.0f); //ambient material color + glm::vec4 kd = glm::vec4(1.0f); //diffuse material color + glm::vec4 ks = glm::vec4(1.0f); //specular material color + float shininess = 20.0f; //specular exponent + }; + + extern SceneUniforms SceneData; + extern LightUniforms LightData; + extern MaterialUniforms MaterialData; + + //IDs for the buffer objects holding the uniform block data + extern GLuint scene_ubo; + extern GLuint light_ubo; + extern GLuint material_ubo; + + namespace UboBinding + { + //These values come from the binding value specified in the shader block layout + extern int scene; + extern int light; + extern int material; + }; + + //Locations for the uniforms which are not in uniform blocks + namespace UniformLocs + { + extern int M; //model matrix + extern int time; + }; +}; diff --git a/include/scene.h b/include/scene.h index 6928dea..8c4bc23 100644 --- a/include/scene.h +++ b/include/scene.h @@ -1,8 +1,9 @@ namespace Scene { - void DrawGUI(GLFWwindow* window); void Display(GLFWwindow* window); + void DrawGUI(GLFWwindow* window); void Idle(); + void ReloadShader(); void Init(); extern const int InitWindowWidth; diff --git a/source/Callbacks.cpp b/source/Callbacks.cpp new file mode 100644 index 0000000..5a6ab15 --- /dev/null +++ b/source/Callbacks.cpp @@ -0,0 +1,55 @@ +#include "Callbacks.h" +#include "Scene.h" +#include + +void Callbacks::Register(GLFWwindow* window) +{ + glfwSetKeyCallback(window, Keyboard); + glfwSetCursorPosCallback(window, MouseCursor); + glfwSetMouseButtonCallback(window, MouseButton); + glfwSetFramebufferSizeCallback(window, Resize); +} + +//This function gets called when a key is pressed +void Callbacks::Keyboard(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + //std::cout << "key : " << key << ", " << char(key) << ", scancode: " << scancode << ", action: " << action << ", mods: " << mods << std::endl; + + if (action == GLFW_PRESS) + { + switch (key) + { + case 'r': + case 'R': + //Scene::ReloadShader(); + break; + + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(window, GLFW_TRUE); + break; + } + } +} + +//This function gets called when the mouse moves over the window. +void Callbacks::MouseCursor(GLFWwindow* window, double x, double y) +{ + //std::cout << "cursor pos: " << x << ", " << y << std::endl; +} + +//This function gets called when a mouse button is pressed. +void Callbacks::MouseButton(GLFWwindow* window, int button, int action, int mods) +{ + //std::cout << "button : "<< button << ", action: " << action << ", mods: " << mods << std::endl; +} + +void Callbacks::Resize(GLFWwindow* window, int width, int height) +{ + width = glm::max(1, width); + height = glm::max(1, height); + //Set viewport to cover entire framebuffer + glViewport(0, 0, width, height); + //Set aspect ratio used in view matrix calculation + //Scene::Camera::Aspect = float(width) / float(height); + //Scene::Camera::UpdateP(); +} \ No newline at end of file diff --git a/source/DebugCallback.cpp b/source/DebugCallback.cpp new file mode 100644 index 0000000..8b6a8bc --- /dev/null +++ b/source/DebugCallback.cpp @@ -0,0 +1,208 @@ +#include "DebugCallback.h" +#include + +void RegisterDebugCallback() +{ +#if _DEBUG + if (glDebugMessageCallback) + { + std::cout << "Register OpenGL debug callback " << std::endl; + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(openglCallbackFunction, nullptr); + GLuint unusedIds = 0; + glDebugMessageControl(GL_DONT_CARE, + GL_DONT_CARE, + GL_DONT_CARE, + 0, + &unusedIds, + true); + } + else + { + std::cout << "glDebugMessageCallback not available" << std::endl; + } +#endif +} + + +#ifdef WIN32 +/* Only run this code on WindowsAPI systems, otherwise use cout */ + +// C-based callback implementation + +/* Reverse of SetConsoleTextAttribute */ +WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + GetConsoleScreenBufferInfo(hConsoleOutput, &csbi); + return csbi.wAttributes; +} + +/* Basic colors */ +#define FMT_BLACK 0 +#define FMT_BLUE FOREGROUND_BLUE|FOREGROUND_INTENSITY +#define FMT_RED FOREGROUND_RED|FOREGROUND_INTENSITY +#define FMT_MAROON FOREGROUND_RED +#define FMT_GREEN FOREGROUND_BLUE|FOREGROUND_INTENSITY +/* Combination colors */ +#define FMT_MAGENTA FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY +#define FMT_CYAN FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY +#define FMT_YELLOW FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY +#define FMT_GOLD FOREGROUND_RED|FOREGROUND_GREEN +#define FMT_WHITE FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY +#define FMT_GRAY FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE + +/* Simplified windows API for color console printing */ +#define WriteConsoleColorA(hConsoleOutput, lpBuffer, numberOfCharsToWrite, color) \ +SetConsoleTextAttribute(hConsoleOutput, color), \ +WriteConsoleA(hConsoleOutput, lpBuffer, numberOfCharsToWrite, NULL, NULL) + +/* This macro makes it less verbose */ +#define WriteConsoleNewlineA() WriteConsoleA(hStdOut, "\r\n", 2, NULL, NULL) + +void APIENTRY openglCallbackFunction(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const GLvoid* userParam) +{ + if (id == 0x8dc) return; + + static const char format[][58] = { + "---------------------OpenGL-callback-start------------\n", + "Message: ", + "Type: ", + "Id: ", + "Severity: ", + "---------------------OpenGL-callback-end--------------\n" }; + static const char eTypes[][24] = { "ERROR", "DEPRECATED_BEHAVIOR", + "UNDEFINED_BEHAVIOR", "PORTABILITY", "PERFORMANCE", "OTHER" }; + static const unsigned short eTypesC[] = { FMT_RED, FMT_GRAY, + FMT_MAROON, FMT_GOLD, FMT_GREEN, FMT_MAGENTA }; + static const char eSeverities[][16] = { "HIGH", + "MEDIUM", "LOW", }; + static const unsigned short eSeveritiesC[] = { FMT_RED, + FMT_GOLD, FMT_GREEN }; + + unsigned char eTypeIdx, eSeverityIdx; + HANDLE hStdOut; + WORD hStdOutAttr; + char buffer[8]; + + eTypeIdx = type - GL_DEBUG_TYPE_ERROR; + eSeverityIdx = severity - GL_DEBUG_SEVERITY_HIGH; + + /* Do not close this handle with CloseHandle, it's process-wide */ + hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + /* Save previous colors/attributes to not distrub existing colors */ + hStdOutAttr = GetConsoleTextAttribute(hStdOut); + + WriteConsoleColorA(hStdOut, format[0], sizeof(*format), FMT_YELLOW); + + /* Message: */ + WriteConsoleColorA(hStdOut, format[1], sizeof(*format), FMT_YELLOW); + WriteConsoleColorA(hStdOut, message, strlen(message), FMT_CYAN); + WriteConsoleNewlineA(); + + /* Type: */ + WriteConsoleColorA(hStdOut, format[2], sizeof(*format), FMT_YELLOW); + WriteConsoleColorA(hStdOut, eTypes[eTypeIdx], + sizeof(*eTypes), eTypesC[eTypeIdx]); + WriteConsoleNewlineA(); + + /* Id: */ + WriteConsoleColorA(hStdOut, format[3], sizeof(*format), FMT_YELLOW); + buffer[0] = '0', buffer[1] = 'x'; + itoa(id, buffer + 2, 16); + WriteConsoleColorA(hStdOut, buffer, strlen(buffer), FMT_CYAN); + WriteConsoleNewlineA(); + + /* Severity: */ + WriteConsoleColorA(hStdOut, format[4], sizeof(*format), FMT_YELLOW); + if (eSeverityIdx < sizeof(eSeverities)/sizeof(eSeverities[0])) { + WriteConsoleColorA(hStdOut, eSeverities[eSeverityIdx], + sizeof(*eSeverities), eSeveritiesC[eSeverityIdx]); + } + else { + WriteConsoleColorA(hStdOut, "N/A", 3, FMT_MAGENTA); + } + WriteConsoleNewlineA(); + + WriteConsoleColorA(hStdOut, format[5], sizeof(*format), FMT_YELLOW); + + /* Restore previous colors so other functions can continue printing */ + SetConsoleTextAttribute(hStdOut, hStdOutAttr); + + if(severity == GL_DEBUG_SEVERITY_HIGH || + type == GL_DEBUG_TYPE_ERROR) + { + static bool previous_break = false; + if (previous_break == false) + { + DebugBreak(); //Check text console for error messages + previous_break = true; //This allows execution to continue after the break. Breaks won't happen for subsequent errors + } + } + +} + +#undef WriteConsoleColorA +#undef WriteConsoleNewlineA + +#else /* WIN32 */ + +void APIENTRY openglCallbackFunction(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + GLvoid* userParam) +{ + using namespace std; + + cout << "---------------------opengl-callback-start------------" << endl; + cout << "message: " << message << endl; + cout << "type: "; + switch (type) { + case GL_DEBUG_TYPE_ERROR: + cout << "ERROR"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + cout << "DEPRECATED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + cout << "UNDEFINED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + cout << "PORTABILITY"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + cout << "PERFORMANCE"; + break; + case GL_DEBUG_TYPE_OTHER: + cout << "OTHER"; + break; + } + cout << endl; + + cout << "id: " << id << endl; + cout << "severity: "; + switch (severity) { + case GL_DEBUG_SEVERITY_LOW: + cout << "LOW"; + break; + case GL_DEBUG_SEVERITY_MEDIUM: + cout << "MEDIUM"; + break; + case GL_DEBUG_SEVERITY_HIGH: + cout << "HIGH"; + break; + } + cout << endl; + cout << "---------------------opengl-callback-end--------------" << endl; +} + +#endif /* WIN32 */ \ No newline at end of file diff --git a/source/InitShader.cpp b/source/InitShader.cpp new file mode 100644 index 0000000..83e42d1 --- /dev/null +++ b/source/InitShader.cpp @@ -0,0 +1,271 @@ +#include + +#include +#include +#include +using namespace std; + +//Adapted from Edward Angels InitShader code + +// Create a NULL-terminated string by reading the provided file +static char* readShaderSource(const char* shaderFile) +{ + ifstream ifs(shaderFile, ios::in | ios::binary | ios::ate); + if (ifs.is_open()) + { + unsigned int filesize = static_cast(ifs.tellg()); + ifs.seekg(0, ios::beg); + char* bytes = new char[filesize + 1]; + memset(bytes, 0, filesize + 1); + ifs.read(bytes, filesize); + ifs.close(); + return bytes; + } + return NULL; +} + +void printShaderCompileError(GLuint shader) +{ + GLint logSize; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); + char* logMsg = new char[logSize]; + glGetShaderInfoLog(shader, logSize, NULL, logMsg); + std::cerr << logMsg << std::endl; + delete[] logMsg; + +} + +void printProgramLinkError(GLuint program) +{ + GLint logSize; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logSize); + char* logMsg = new char[logSize]; + glGetProgramInfoLog(program, logSize, NULL, logMsg); + std::cerr << logMsg << std::endl; + delete[] logMsg; +} + +GLuint InitShader(const char* computeShaderFile) +{ + bool error = false; + struct Shader + { + const char* filename; + GLenum type; + GLchar* source; + } shaders[1] = + { + { computeShaderFile, GL_COMPUTE_SHADER, NULL } + }; + + GLuint program = glCreateProgram(); + + for (int i = 0; i < 1; ++i) + { + Shader& s = shaders[i]; + s.source = readShaderSource(s.filename); + if (shaders[i].source == NULL) + { + std::cerr << "Failed to read " << s.filename << std::endl; + error = true; + } + + GLuint shader = glCreateShader(s.type); + glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + std::cerr << s.filename << " failed to compile:" << std::endl; + printShaderCompileError(shader); + error = true; + } + + delete[] s.source; + + glAttachShader(program, shader); + } + + /* link and error check */ + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (!linked) + { + std::cerr << "Shader program failed to link" << std::endl; + printProgramLinkError(program); + + error = true; + } + + if (error == true) + { + return -1; + } + + /* use program object */ + glUseProgram(program); + + return program; +} + + +// Create a GLSL program object from vertex and fragment shader files +GLuint InitShader(const char* vShaderFile, const char* fShaderFile) +{ + + bool error = false; + struct Shader + { + const char* filename; + GLenum type; + GLchar* source; + } shaders[2] = + { + { vShaderFile, GL_VERTEX_SHADER, NULL }, + { fShaderFile, GL_FRAGMENT_SHADER, NULL } + }; + + GLuint program = glCreateProgram(); + + for (int i = 0; i < 2; ++i) + { + Shader& s = shaders[i]; + s.source = readShaderSource(s.filename); + if (shaders[i].source == NULL) + { + std::cerr << "Failed to read " << s.filename << std::endl; + error = true; + } + + GLuint shader = glCreateShader(s.type); + glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + std::cerr << s.filename << " failed to compile:" << std::endl; + printShaderCompileError(shader); + error = true; + } + + delete[] s.source; + + glAttachShader(program, shader); + } + + //set shader attrib locations + const int pos_loc = 0; + const int tex_coord_loc = 1; + const int normal_loc = 2; + + glBindAttribLocation(program, pos_loc, "pos_attrib"); + glBindAttribLocation(program, tex_coord_loc, "tex_coord_attrib"); + glBindAttribLocation(program, normal_loc, "normal_attrib"); + + /* link and error check */ + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (!linked) + { + std::cerr << "Shader program failed to link" << std::endl; + printProgramLinkError(program); + + error = true; + } + + if (error == true) + { + return -1; + } + + /* use program object */ + glUseProgram(program); + return program; +} + +// Create a GLSL program object from vertex and fragment shader files +GLuint InitShader(const char* vShaderFile, const char* gShaderFile, const char* fShaderFile) +{ + bool error = false; + struct Shader + { + const char* filename; + GLenum type; + GLchar* source; + } shaders[3] = + { + { vShaderFile, GL_VERTEX_SHADER, NULL }, + { gShaderFile, GL_GEOMETRY_SHADER, NULL }, + { fShaderFile, GL_FRAGMENT_SHADER, NULL } + }; + + GLuint program = glCreateProgram(); + + for (int i = 0; i < 3; ++i) + { + Shader& s = shaders[i]; + s.source = readShaderSource(s.filename); + if (shaders[i].source == NULL) + { + std::cerr << "Failed to read " << s.filename << std::endl; + error = true; + } + + GLuint shader = glCreateShader(s.type); + glShaderSource(shader, 1, (const GLchar**)&s.source, NULL); + glCompileShader(shader); + + GLint compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) + { + std::cerr << s.filename << " failed to compile:" << std::endl; + printShaderCompileError(shader); + error = true; + } + + delete[] s.source; + + glAttachShader(program, shader); + } + + //set shader attrib locations + const int pos_loc = 0; + const int tex_coord_loc = 1; + const int normal_loc = 2; + + glBindAttribLocation(program, pos_loc, "pos_attrib"); + glBindAttribLocation(program, tex_coord_loc, "tex_coord_attrib"); + glBindAttribLocation(program, normal_loc, "normal_attrib"); + + /* link and error check */ + glLinkProgram(program); + + GLint linked; + glGetProgramiv(program, GL_LINK_STATUS, &linked); + if (!linked) + { + std::cerr << "Shader program failed to link" << std::endl; + printProgramLinkError(program); + + error = true; + } + + if (error == true) + { + return -1; + } + + /* use program object */ + glUseProgram(program); + + return program; +} diff --git a/source/Uniforms.cpp b/source/Uniforms.cpp new file mode 100644 index 0000000..e88588b --- /dev/null +++ b/source/Uniforms.cpp @@ -0,0 +1,57 @@ +#include "Uniforms.h" +#include + +namespace Uniforms +{ + SceneUniforms SceneData; + LightUniforms LightData; + MaterialUniforms MaterialData; + + //IDs for the buffer objects holding the uniform block data + GLuint scene_ubo = -1; + GLuint light_ubo = -1; + GLuint material_ubo = -1; + + namespace UboBinding + { + //These values come from the binding value specified in the shader block layout + int scene = 0; + int light = 1; + int material = 2; + }; + + //Locations for the uniforms which are not in uniform blocks + namespace UniformLocs + { + int M = 0; //model matrix + int time = 1; + }; + + void Init() + { + //Create and initialize uniform buffers + glGenBuffers(1, &Uniforms::scene_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(SceneUniforms), nullptr, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). + glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::scene, scene_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. + + glGenBuffers(1, &light_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, light_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightUniforms), &LightData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). + glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::light, light_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. + + glGenBuffers(1, &material_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, material_ubo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(MaterialUniforms), &MaterialData, GL_STREAM_DRAW); //Allocate memory for the buffer, but don't copy (since pointer is null). + glBindBufferBase(GL_UNIFORM_BUFFER, UboBinding::material, material_ubo); //Associate this uniform buffer with the uniform block in the shader that has the same binding. + + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + void BufferSceneData() + { + glBindBuffer(GL_UNIFORM_BUFFER, scene_ubo); //Bind the OpenGL UBO before we update the data. + glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SceneData), &SceneData); //Upload the new uniform values. + glBindBuffer(GL_UNIFORM_BUFFER, 0); //unbind the ubo + } +}; diff --git a/source/main.cpp b/source/main.cpp index 5dc1b2d..fe12259 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -46,6 +46,10 @@ int main(){ return -1; } + #ifdef _DEBUG + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); + #endif + GLFWwindow* window = glfwCreateWindow(1280, 720, "TerraVisor", nullptr, nullptr); if(!window) { std::cerr << "Failed to create GLFW window" << std::endl; diff --git a/source/scene.cpp b/source/scene.cpp index e678250..20c4f80 100644 --- a/source/scene.cpp +++ b/source/scene.cpp @@ -1,6 +1,12 @@ #include #include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + #include #include #include @@ -11,6 +17,52 @@ #include #include "scene.h" +#include "Uniforms.h" +#include "InitShader.h" //Functions for loading shaders from text files +//#include "LoadMesh.h" //Functions for creating OpenGL buffers from mesh files +//#include "LoadTexture.h" //Functions for creating OpenGL textures from image files +//#include "VideoRecorder.h" //Functions for saving videos +#include "DebugCallback.h" + +static const std::string vertex_shader("shaders/vertex.glsl"); +static const std::string fragment_shader("shaders/fragment.glsl"); +GLuint shader_program = -1; + +float angle = 0.0f; +float scale = 1.0f; + +namespace Camera { + glm::mat4 V, P; + + float Aspect = 1.0f; + float NearZ = 0.1f; + float FarZ = 100.0f; + float Fov = glm::pi() / 4.0f; + + void UpdateP() { + P = glm::perspective(Fov, Aspect, NearZ, FarZ); + } +} + +void Scene::Display(GLFWwindow* window) { + glClear(GL_COLOR_BUFFER_BIT); + + Camera::V = glm::lookAt(glm::vec3(Uniforms::SceneData.eye_w), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); + Uniforms::SceneData.PV = Camera::P * Camera::V; + Uniforms::BufferSceneData(); + + glUseProgram(shader_program); + + glm::mat4 M = glm::rotate(angle, glm::vec3(0.0f, 1.0f, 0.0f)) * glm::scale(glm::vec3(scale)); + glUniformMatrix4fv(Uniforms::UniformLocs::M, 1, false, glm::value_ptr(M)); + + //glBindVertexArray(mesh_data.mVao); + //glDrawElements(GL_TRIANGLES, mesh_data.mSubmesh[0].mNumIndices, GL_UNSIGNED_INT, 0); + + Scene::DrawGUI(window); + + glfwSwapBuffers(window); +} void Scene::DrawGUI(GLFWwindow* window) { // Begin ImGui frame @@ -78,15 +130,28 @@ void Scene::DrawGUI(GLFWwindow* window) { ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } -void Scene::Display(GLFWwindow* window) { - glClear(GL_COLOR_BUFFER_BIT); - - Scene::DrawGUI(window); - - glfwSwapBuffers(window); +void Scene::Idle() { } -void Scene::Idle() { +void Scene::ReloadShader() +{ + GLuint new_shader = InitShader(vertex_shader.c_str(), fragment_shader.c_str()); + + if (new_shader == -1) // loading failed + { + DebugBreak(); //alert user by breaking and showing debugger + glClearColor(1.0f, 0.0f, 1.0f, 0.0f); //change clear color if shader can't be compiled + } + else + { + glClearColor(0.35f, 0.35f, 0.35f, 0.0f); + + if (shader_program != -1) + { + glDeleteProgram(shader_program); + } + shader_program = new_shader; + } } void Scene::Init() { @@ -94,4 +159,6 @@ void Scene::Init() { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); + + ReloadShader(); }