diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..bcb2903 --- /dev/null +++ b/.clang-format @@ -0,0 +1,8 @@ +# Format Style Options - Created with Clang Power Tools +--- +BasedOnStyle: WebKit +BreakBeforeBraces: Attach +ColumnLimit: 110 +SortIncludes: false +SpaceAfterTemplateKeyword: false +... diff --git a/.gitignore b/.gitignore index 2d84e6d..82c309d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ x64** **.idb **.pdb **.exe +.cache** diff --git a/LivePlotter.vcxproj b/LivePlotter.vcxproj index ca2b0d7..4c85fdf 100644 --- a/LivePlotter.vcxproj +++ b/LivePlotter.vcxproj @@ -73,6 +73,9 @@ $(SolutionDir)ext\glfw\build\src\Debug;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) $(SolutionDir)ext\glfw\include;$(SolutionDir)inc;$(IncludePath) + $(SolutionDir)bin\$(Platform)\$(Configuration)\ + $(SolutionDir)obj\$(Platform)\$(Configuration)\ + $(SolutionDir)src;$(SourcePath) @@ -135,6 +138,8 @@ + + diff --git a/LivePlotter.vcxproj.filters b/LivePlotter.vcxproj.filters index bead6d0..7d52e7e 100644 --- a/LivePlotter.vcxproj.filters +++ b/LivePlotter.vcxproj.filters @@ -21,5 +21,11 @@ Source Files + + Source Files + + + Source Files + \ No newline at end of file diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..ead1093 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,13 @@ +[ + { + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c \"C:/Users/seth/Documents/repos/LivePlotter/glad.c\" -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/glad.c" + } + , + { + "directory": "C:/Users/seth/Documents/repos/LivePlotter/", + "command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/main.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"", + "file": "C:/Users/seth/Documents/repos/LivePlotter/src/main.cpp" + } +] diff --git a/inc/shaders.hpp b/inc/shaders.hpp new file mode 100644 index 0000000..470f530 --- /dev/null +++ b/inc/shaders.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include "util.hpp" + +namespace shader { + +// Reads shader source files, compiles, and links +bool load(uint* out_id, const char *vertex_filepath, const char *fragment_filepath); + +// Sets shader as active on the gpu +void use(uint id); + +// Set uniform value +typedef std::variant uniform_variant; +void set_uniform(uint id, const char *name, uniform_variant value); + +} // namespace shaders diff --git a/inc/util.hpp b/inc/util.hpp new file mode 100644 index 0000000..9c46f73 --- /dev/null +++ b/inc/util.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include + +template struct Array { + T* _data; + size_t len; + + T& operator[](int i); +}; + +typedef unsigned int uint; + +bool read_file(Array* out, const char* filepath); diff --git a/src/main.cpp b/src/main.cpp index 5754432..64c48e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,26 +1,13 @@ #include #include #include -#include #include #include +#include "shaders.hpp" + using namespace std; -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"; - -const char* fragmentShaderSource = "#version 330 core\n" - "out vec4 FragColor;\n" - "void main()\n" - "{\n" - " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);" - "} "; - static GLFWwindow* window; template @@ -62,9 +49,9 @@ enum class ParserState { FACE, FACE_SKIP, }; -optional, SimpleArray>> load_iconsphere() { +optional, SimpleArray>> load_icosphere() { std::FILE* f = NULL; - + if (fopen_s(&f, "Icosphere.obj", "r")) { return {}; } @@ -133,7 +120,7 @@ int main() { if (!glfw_window_setup()) return -1; - auto data = load_iconsphere(); + auto data = load_icosphere(); if (!data) { std::cout << "ERROR loading the icosphere obj file failed" << std::endl; return -1; @@ -156,12 +143,6 @@ int main() glfwSwapBuffers(window); // front buffer is now back glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer again (former front buf) - /*float vertices[] = { - -0.5f, -0.5f, 0.0f, - 0.5f, -0.5f, 0.0f, - 0.0f, 0.5f, 0.0f - };*/ - unsigned int VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); @@ -175,54 +156,10 @@ int main() glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size * sizeof(unsigned int), indices.data, GL_STATIC_DRAW); - - // Vertex shader - unsigned int vertexShader; - vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); - glCompileShader(vertexShader); - - // Verify vertex shader compilation - 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 - unsigned int fragmentShader; - fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); - glCompileShader(fragmentShader); - - // Verify fragment shader compilation - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); - if (!success) - { - glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; - } - - // Link shader programs together - unsigned int shaderProgram; - shaderProgram = glCreateProgram(); - glAttachShader(shaderProgram, vertexShader); - glAttachShader(shaderProgram, fragmentShader); - glLinkProgram(shaderProgram); - glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); - if (!success) { - glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); - std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; - } - glUseProgram(shaderProgram); // Set shaderProgram as active shader - - // Delete shader program parts (like deleting obj files). - // We want this memory back - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); + uint program_id; + if (!shader::load(&program_id, "src/shaders/vertex.vs", "src/shaders/fragment.fs")) return -1; + shader::use(program_id); // Tell opengl which attribute our data is for (i.e. location) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); @@ -242,4 +179,4 @@ int main() } glfwTerminate(); return 0; -} \ No newline at end of file +} diff --git a/src/shaders.cpp b/src/shaders.cpp new file mode 100644 index 0000000..e5ece76 --- /dev/null +++ b/src/shaders.cpp @@ -0,0 +1,88 @@ +#include +#include + +#include "util.hpp" +#include "shaders.hpp" + +#define MAX_ERR_MSG_LEN 256 + + +// Visit/Variant overload pattern +// https://www.modernescpp.com/index.php/visiting-a-std-variant-with-the-overload-pattern/ +template +struct overload : Ts ... { + using Ts::operator() ...; +}; +template overload(Ts...) -> overload; + +namespace shader { + +bool _compile_shader(uint *out_id, const char* filepath, int shader_type); + +bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepath) { + uint vertex_id; + if (!_compile_shader(&vertex_id, vertex_filepath, GL_VERTEX_SHADER)) + return false; + + uint fragment_id; + if (!_compile_shader(&fragment_id, fragment_filepath, GL_FRAGMENT_SHADER)) + return false; + + uint program_id = glCreateProgram(); + glAttachShader(program_id, vertex_id); + glAttachShader(program_id, fragment_id); + glLinkProgram(program_id); + + int status; + glGetProgramiv(program_id, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + char err_msg[MAX_ERR_MSG_LEN]; + glGetProgramInfoLog(program_id, MAX_ERR_MSG_LEN, NULL, err_msg); + printf("Error linking shaders %s and %s\n", vertex_filepath, fragment_filepath); + printf("Error msg: %s\n", err_msg); + return false; + } + + glDeleteShader(vertex_id); + glDeleteShader(fragment_id); + + *out_id = program_id; + return true; +} + +void use(uint id) { glUseProgram(id); } + +void set_uniform(uint id, const char* name, uniform_variant value) { + const auto visitor = overload { + [id, name](int i) { glUniform1i(glGetUniformLocation(id, name), i); }, + [id, name](float f) { glUniform1f(glGetUniformLocation(id, name), f); }, + [id, name](bool b) { glUniform1i(glGetUniformLocation(id, name), b); }, + }; + visit(visitor, value); +} + +// Privates + +bool _compile_shader(uint *out_id, const char* filepath, int shader_type) { + Array source; + if (!read_file(&source, filepath)) + return false; + + uint id = glCreateShader(shader_type); + glShaderSource(id, 1, &source._data, (int*)&source.len); + glCompileShader(id); + + int status; + glGetShaderiv(id, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + char err_msg[MAX_ERR_MSG_LEN]; + glGetShaderInfoLog(id, MAX_ERR_MSG_LEN, NULL, err_msg); + printf("Error compiling shader %s\n", filepath); + printf("%.*s\n", (int)source.len, source._data); + printf("Error msg: %s\n", err_msg); + } + *out_id = id; + return status == GL_TRUE; +} + +} // namespace shader diff --git a/src/shaders/fragment.fs b/src/shaders/fragment.fs new file mode 100644 index 0000000..d7b1433 --- /dev/null +++ b/src/shaders/fragment.fs @@ -0,0 +1,7 @@ +#version 330 core + +out vec4 frag_color; + +void main() { + frag_color = vec4(1.0f, 0.5f, 0.2f, 1.0f); +} diff --git a/src/shaders/vertex.vs b/src/shaders/vertex.vs new file mode 100644 index 0000000..e390af0 --- /dev/null +++ b/src/shaders/vertex.vs @@ -0,0 +1,6 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +void main() { + gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0); +} diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..af994b3 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,23 @@ +#include +#include + +#include "util.hpp" + +bool read_file(Array* out, const char* filepath) { + FILE* fp = NULL; + if (fopen_s(&fp, filepath, "r") != 0) { + printf("ERROR Failed to open file %s\n", filepath); + return false; + } + + fseek(fp, 0L, SEEK_END); + size_t sz = ftell(fp); + fseek(fp, 0L, 0L); + + char *data = (char*)malloc(sizeof(char)*sz); + fread(data, sizeof(char), sz, fp); + fclose(fp); + out->_data = data; + out->len = sz; + return true; +}