commit 913950478c2ee6f1c4d2c5cd2b780ceec1c9229b Author: jstefanelli Date: Tue May 13 15:33:42 2025 +0200 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bf797c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +cmake-build-debug \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..42e400a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "contrib/imgui"] + path = contrib/imgui + url = git@github.com:ocornut/imgui.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..13a649e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.28) +project(ModelExtractor) + +set(CMAKE_CXX_STANDARD 20) + +find_package(SDL2 CONFIG REQUIRED) +find_package(glm CONFIG REQUIRED) +find_package(GLEW REQUIRED) + +add_subdirectory(contrib) + +add_executable(ModelExtractor main.cpp + gl_debug.cpp + gl_debug.h) +target_link_libraries(ModelExtractor SDL2::SDL2 GLEW::GLEW GL imgui glm) +if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") + target_compile_definitions(ModelExtractor PRIVATE __DEBUG) +endif() +target_compile_options(ModelExtractor PUBLIC -Wall -Wextra) + +add_custom_command(TARGET ModelExtractor + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/base.vert + ${CMAKE_CURRENT_BINARY_DIR}/shaders/base.vert) + +add_custom_command(TARGET ModelExtractor + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/base.frag + ${CMAKE_CURRENT_BINARY_DIR}/shaders/base.frag) \ No newline at end of file diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt new file mode 100644 index 0000000..0675501 --- /dev/null +++ b/contrib/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(imgui STATIC imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/backends/imgui_impl_sdl2.cpp imgui/backends/imgui_impl_opengl3.cpp) +target_link_libraries(imgui SDL2::SDL2 GL) +target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui) +target_compile_options(imgui PUBLIC -Wall -Wextra) \ No newline at end of file diff --git a/contrib/imgui b/contrib/imgui new file mode 160000 index 0000000..f9cda1f --- /dev/null +++ b/contrib/imgui @@ -0,0 +1 @@ +Subproject commit f9cda1fa245b361a0e98428d88470eebaa187e5b diff --git a/gl_debug.cpp b/gl_debug.cpp new file mode 100644 index 0000000..2bad2bf --- /dev/null +++ b/gl_debug.cpp @@ -0,0 +1,80 @@ +#include +#include "gl_debug.h" + +#ifdef __DEBUG +void GLAPIENTRY debug_func(GLenum source, GLenum type, GLuint, GLenum severity, GLsizei, const GLchar* msg, const void*) { + const char* src; + switch(source) { + case GL_DEBUG_SOURCE_API: + src = "[SOURCE_API]"; + break; + case GL_DEBUG_SOURCE_OTHER: + src = "[SOURCE_OTHER]"; + break; + case GL_DEBUG_SOURCE_THIRD_PARTY: + src = "[SOURCE_THIRD_PARTY]"; + break; + case GL_DEBUG_SOURCE_APPLICATION: + src = "[SOURCE_APP]"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + src = "[SOURCE_SHADER_COMPILER]"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + src = "[SOURCE_WIN_SYS]"; + break; + default: + src = "[SOURCE_UNKNOWN]"; + break; + } + + const char* tp; + switch(type) { + case GL_DEBUG_TYPE_ERROR: + tp = "[TYPE_ERROR]"; + break; + case GL_DEBUG_TYPE_OTHER: + tp = "[TYPE_OTHER]"; + break; + case GL_DEBUG_TYPE_MARKER: + tp = "[TYPE_MARKER]"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + tp = "[TYPE_PERF]"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + tp = "[TYPE_PORT]"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + tp = "[TYPE_DEPRECATED]"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + tp = "[TYPE_UB]"; + break; + default: + tp = "[TYPE_UNKNOWN]"; + break; + } + + const char* sv; + switch(severity) { + case GL_DEBUG_SEVERITY_LOW: + sv = "[SEV_LOW]"; + break; + case GL_DEBUG_SEVERITY_MEDIUM: + sv = "[SEV_MED]"; + break; + case GL_DEBUG_SEVERITY_HIGH: + sv = "[SEV_HIGH]"; + break; + case GL_DEBUG_SEVERITY_NOTIFICATION: + return; + sv = "[SEV_NOTIF]"; + break; + default: + sv = "[SEV_UNKNOWN]"; + } + + std::cerr << "[GL]" << sv << tp << src << ": " << msg << std::endl; +} +#endif diff --git a/gl_debug.h b/gl_debug.h new file mode 100644 index 0000000..488dfbd --- /dev/null +++ b/gl_debug.h @@ -0,0 +1,7 @@ +#ifndef GL_DEBUG_H +#define GL_DEBUG_H +#include + +extern void GLAPIENTRY debug_func(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* msg, const void*); + +#endif //GL_DEBUG_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..8c2f3c0 --- /dev/null +++ b/main.cpp @@ -0,0 +1,614 @@ +#include +#include +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __DEBUG +#include "gl_debug.h" +#endif + +template +bool contains(const std::vector& vec, const T& val) { + return std::find(vec.cbegin(), vec.cend(), val) != vec.cend(); +} + +void print_info_log(GLuint object, bool is_program) { + + GLint info_len = 0; + if (is_program) { + glGetProgramiv(object, GL_INFO_LOG_LENGTH, &info_len); + } else { + glGetShaderiv(object, GL_INFO_LOG_LENGTH, &info_len); + } + + if (info_len > 0) { + std::vector buffer; + buffer.resize(info_len); + GLint actual_len; + + if (is_program) { + glGetProgramInfoLog(object, buffer.size(), &actual_len, buffer.data()); + } else { + glGetShaderInfoLog(object, buffer.size(), &actual_len, buffer.data()); + } + + std::cout << "[GL] Info log: " << std::endl << buffer.data() << std::endl; + } +} + +GLuint compile_shader(GLenum type, const char* file) { + + std::vector bytes; + std::ifstream stream(file); + if (!stream.is_open()) { + std::cerr << "[GL] Failed to open file: " << file << std::endl; + exit(1); + return 0; + } + + bytes.assign(std::istreambuf_iterator(stream), std::istreambuf_iterator()); + + auto id = glCreateShader(type); + const auto* data = bytes.data(); + auto len = static_cast(bytes.size()); + glShaderSource(id, 1, &data, &len); + glCompileShader(id); + + print_info_log(id, false); + + GLint status = 0; + glGetShaderiv(id, GL_COMPILE_STATUS, &status); + + if (status != GL_TRUE) { + std::cerr << "[GL] Failed to compile shader" << std::endl; + exit(1); + return 0; + } + + return id; +} + +GLuint program = 0; +GLuint vao = 0; + +void init_gl(SDL_Window* window, SDL_GLContext context) { +#ifdef __DEBUG + int count = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &count); + + std::set extensions; + for(auto i = 0; i < count; i++) { + const char* ext = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); + + extensions.emplace(ext); + } + + if (extensions.contains("GL_KHR_debug")) { + std::cout << "[GL] Enabling debug output..." << std::endl; + std::cout.flush(); + glEnable(GL_DEBUG_OUTPUT); + glDebugMessageCallback(debug_func, nullptr); + + std::string msg = "Debug output test"; + glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 494949, GL_DEBUG_SEVERITY_NOTIFICATION, msg.length(), msg.c_str()); + } +#endif + + glClearColor(0.2, 0.2, 0.23, 1.0); + + auto vsId = compile_shader(GL_VERTEX_SHADER, "shaders/base.vert"); + std::cout << "[GL] VS Ok." << std::endl; + auto fsId = compile_shader(GL_FRAGMENT_SHADER, "shaders/base.frag"); + std::cout << "[GL] FS Ok." << std::endl; + + program = glCreateProgram(); + glAttachShader(program, vsId); + glAttachShader(program, fsId); + glLinkProgram(program); + + print_info_log(program, true); + + GLint link_status = 0; + glGetProgramiv(program, GL_LINK_STATUS, &link_status); + if (link_status != GL_TRUE) { + std::cerr << "[GL] Failed to link program." << std::endl; + exit(1); + return; + } + + glDeleteShader(vsId); + glDeleteShader(fsId); + + std::cout << "[GL] Program Ok." << std::endl; + + glUseProgram(program); + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGui::StyleColorsDark(); + ImGui_ImplSDL2_InitForOpenGL(window, context); + ImGui_ImplOpenGL3_Init("#version 460"); + + glCreateVertexArrays(1, &vao); + glBindVertexArray(vao); +} + +char file_input[PATH_MAX]; +char file_output[PATH_MAX]; +int resolution[2] = { 1280, 720 }; +float near = 0.001f; +float far = 100.0f; +float fov = 30.0f; +bool update_render = false; + +float adjust_orientation[2] = {0, 0}; + +void load_data(const std::string&); +void save_obj(const std::string& path); + +void run_ui() { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); + + bool open_open = false; + bool open_save = false; + + ImGui::Begin("Camera settings", nullptr, ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoResize); + ImVec2 size = {0, 0}; + ImGui::SetWindowSize("Camera settings", size, 1); + if (ImGui::BeginMenuBar()) { + if (ImGui::BeginMenu("File")) { + if (ImGui::MenuItem("Open", "Ctrl+O")) { + open_open = true; + } + + if (ImGui::MenuItem("Save", "Ctrl+S")) { + open_save = true; + } + + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + + if(ImGui::InputInt2("Resolution", resolution)) { + update_render = true; + } + if(ImGui::InputFloat("Near", &near, 0, 0, "%.5f")) { + update_render = true; + } + if(ImGui::InputFloat("Far", &far, 0, 0, "%.3f")) { + update_render = true; + } + if (ImGui::InputFloat("FoV", &fov, 0, 0, "%.1f")) { + update_render = true; + } + + ImGui::End(); + + ImGui::Begin("Adjustments", nullptr, ImGuiWindowFlags_NoResize); + ImGui::SetWindowSize("Adjustments", size, 1); + ImGui::InputFloat2("Rotation adjust", adjust_orientation, "%.1f"); + ImGui::End(); + + if (open_open) { + ImGui::OpenPopup("file_input"); + } + + if(ImGui::BeginPopup("file_input", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Modal)) { + ImGui::Text("Open File"); + ImGui::Separator(); + ImGui::InputTextWithHint("Directory Path", "Should contain a bunch of .csv", file_input, PATH_MAX, ImGuiInputTextFlags_None, nullptr, nullptr); + + if (ImGui::Button("Ok")) { + ImGui::CloseCurrentPopup(); + load_data(file_input); + } + + ImGui::SameLine(); + if (ImGui::Button("Cancel")) { + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + + if (open_save) { + ImGui::OpenPopup("file_save"); + } + + if(ImGui::BeginPopup("file_save", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Modal)) { + ImGui::Text("Save File"); + ImGui::Separator(); + ImGui::InputTextWithHint("File Path", "Should end with .obj", file_output, PATH_MAX, ImGuiInputTextFlags_None, nullptr, nullptr); + + if (ImGui::Button("Ok")) { + ImGui::CloseCurrentPopup(); + std::filesystem::path target_path(file_output); + if (std::filesystem::is_directory(target_path)) { + target_path /= "out.obj"; + } + save_obj(target_path.string()); + } + + ImGui::SameLine(); + if (ImGui::Button("Cancel")) { + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); +} + + +struct in_vertex { + float position[4]; + float uv[2]; +}; + +struct out_vertex { + float position[3]; + float uv[2]; +}; + +std::vector loaded_vertices; +std::vector out_vertices; +GLuint data_buffer = 0; +bool camera_centered = false; + +void load_data(const std::string& path) { + std::cout << "[Main] Loading data via: " << path << std::endl; + if (!std::filesystem::is_directory(path)) { + std::cerr << "[Main] Could not open path." << std::endl; + //TODO: Report error + return; + } + + std::vector vertices; + std::filesystem::directory_iterator dir(path); + while(dir != std::filesystem::directory_iterator()) { + auto entry = *(dir++); + if (!entry.is_regular_file() || (entry.path().filename().extension() != ".csv")) { + std::cout << "[Main] Invalid file: " << entry.path() << std::endl; + continue; + } + + std::ifstream fs(entry.path()); + + std::stringstream line_stream; + + std::string def; + std::getline(fs, def); + + line_stream.str(def); + + std::vector indices; + while(!line_stream.eof()) { + std::string idx; + line_stream >> idx; + + if (!idx.empty()) { + if (idx.ends_with(',')) { + idx = idx.substr(0, idx.length() - 1); + } + indices.push_back(idx); + } + } + + std::string target_uvx, target_uvy; + + if (contains(indices, "o4.x") && contains(indices, "o4.y") && !contains(indices, "04.z")) { + target_uvx = "o4.x"; + target_uvy = "o4.y"; + } + + std::string line; + + while(std::getline(fs, line) && !line.empty()) { + size_t i = 0; + + std::stringstream line_stream(line); + in_vertex vertex {}; + bool found_x = false, found_y = false, found_z = false, found_w = false; + bool found_uvx = false, found_uvy = false; + + while(i < indices.size()) { + std::string data; + line_stream >> data; + + if (data.empty()) { + continue; + } + + if (data.ends_with(',')) { + data = data.substr(0, data.length() - 1); + } + + auto val = std::stof(data); + auto& index = indices[i]; + if (index == "out_position.x") { + found_x = true; + vertex.position[0] = val; + } + if (index == "out_position.y") { + found_y = true; + vertex.position[1] = val; + } + if (index == "out_position.z") { + found_z = true; + vertex.position[2] = val; + } + if (index == "out_position.w") { + found_w = true; + vertex.position[3] = val; + } + if (index == target_uvx) { + found_uvx = true; + vertex.uv[0] = val; + } + if (index == target_uvy) { + found_uvy = true; + vertex.uv[1] = val; + } + ++i; + } + + if (found_x && found_y && found_z + && found_w && found_uvx && found_uvy) { + vertices.push_back(vertex); + } + } + } + + loaded_vertices = std::move(vertices); + std::cout << "[Main] Loaded " << loaded_vertices.size() << " vertoces." << std::endl; + update_render = true; + camera_centered = false; +} + +float mouse_sensitivity = 0.005; +float camera_yaw = 0, camera_pitch = 0; +glm::vec3 camera_position {}; +glm::quat camera_orientation {}; + + +glm::mat4 display_proj = glm::identity(); +glm::mat4 display_view = glm::identity(); +glm::mat4 display_model = glm::identity(); +glm::vec3 center = {}; +float size = 0.f; + + +void save_obj(const std::string& path) { + std::ofstream out(path); + + if (out_vertices.size() % 3 != 0) { + std::cerr << "Critical error" << std::endl; + exit(1); + return; + } + + for(auto&[position, uv] : out_vertices) { + glm::vec4 original_pos = glm::vec4(position[0], position[1], position[2], 1.0); + glm::vec3 target_pos = glm::xyz(display_model * original_pos); + + out << "v " << target_pos.x << " " << target_pos.y << " " << target_pos.z << "\n"; + out << "vt " << uv[0] << " " << (1.0f - uv[1]) << "\n"; + } + + for(size_t i = 1; i <= out_vertices.size(); i += 3) { + out << "f " << i + 2 << "/" << i + 2 << " " << i + 1 << "/" << i + 1 << " " << i << "/" << i << "\n"; + } +} + +void update_camera() { + glm::mat4 m = glm::translate(glm::identity(), -camera_position); + camera_orientation = glm::identity(); + camera_orientation = glm::rotate(camera_orientation, camera_pitch, {1, 0, 0}); + camera_orientation = glm::rotate(camera_orientation, camera_yaw, {0, 1, 0}); + + display_view = glm::mat4(camera_orientation) * m; +} + +void update_adjustments() { + display_model = glm::rotate(glm::identity(), glm::radians(adjust_orientation[0]), {1, 0, 0}); + display_model = glm::rotate(display_model, glm::radians(adjust_orientation[1]), {0, 1, 0}); +} + +bool validate_params() { + return fov > 0 && resolution[0] > 0 && resolution[1] > 0 && near > 0 && far > 0; +} + +void run_gl(SDL_Window* window) { + glUseProgram(program); + + + if (update_render && !loaded_vertices.empty() && validate_params()) { + + std::cout << "[Main] Params: " << fov << " " << resolution[0] << "x" << resolution[1] << " " << near << " " << far << std::endl; + glm::mat4 proj = glm::perspectiveFov(glm::radians(fov), resolution[0], resolution[1], near, far); + glm::mat4 inv = glm::inverse(proj); + + std::cout << "[Main] Generating data..." << std::endl; + out_vertices.clear(); + glm::vec3 max(-100000, -10000, -10000); + glm::vec3 min(10000, 10000, 10000); + for(auto& in : loaded_vertices) { + glm::vec4 pos = { in.position[0], in.position[1], in.position[2], in.position[3] }; + glm::vec4 reverse = inv * pos; + reverse /= reverse.w; + + min = glm::min(glm::xyz(reverse), min); + max = glm::max(glm::xyz(reverse), max); + + out_vertices.push_back({{reverse.x, reverse.y, reverse.z}, {in.uv[0], in.uv[1]}}); + } + + center = glm::mix(min, max, 0.5f); + auto dist = glm::length(max - min) / 2; + size = dist; + if (!camera_centered) { + camera_yaw = 0; + camera_pitch = 0; + camera_centered = true; + } + + for(auto& v : out_vertices) { + v.position[0] -= center.x; + v.position[1] -= center.y; + v.position[2] -= center.z; + } + + if (data_buffer != 0) { + glDeleteBuffers(1, &data_buffer); + } + + glGenBuffers(1, &data_buffer); + glBindBuffer(GL_ARRAY_BUFFER, data_buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(out_vertex) * out_vertices.size(), out_vertices.data(), GL_STATIC_DRAW); + update_render = false; + } + + if (data_buffer != 0) { + update_camera(); + update_adjustments(); + + int size_x = 0, size_y = 0; + SDL_GetWindowSize(window, &size_x, &size_y); + display_proj = glm::perspectiveFov(glm::radians(90.0f), size_x, size_y, 0.01f, 1000.0f); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(out_vertex), nullptr); + glUniformMatrix4fv(0, 1, false, glm::value_ptr(display_model)); + glUniformMatrix4fv(1, 1, false, glm::value_ptr(display_view)); + glUniformMatrix4fv(2, 1, false, glm::value_ptr(display_proj)); + glUniform4f(3, 0.9f, 0.9f, 0.9f, 1.0f); + glDrawArrays(GL_TRIANGLES, 0, out_vertices.size()); + } + + run_ui(); +} + +glm::vec3 camera_movement { 0, 0, 0}; +bool rotating = false; + +int main(int argc, char** argv) { + setenv("SDL_VIDEODRIVER", "wayland", 1); + + SDL_Init(SDL_INIT_VIDEO); + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); +#ifdef __DEBUG + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); +#endif + + auto* win = SDL_CreateWindow("ModelExtractor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1290, 720, SDL_WINDOW_OPENGL); + auto* ctx = SDL_GL_CreateContext(win); + + SDL_ShowWindow(win); + SDL_GL_MakeCurrent(win, ctx); + + glewInit(); + + init_gl(win, ctx); + + SDL_Event ev; + bool alive = true; + while(alive) { + camera_movement = {0, 0, 0}; + while(SDL_PollEvent(&ev)) { + ImGui_ImplSDL2_ProcessEvent(&ev); + switch(ev.type) { + case SDL_EventType::SDL_QUIT: + alive = false; + break; + case SDL_EventType::SDL_MOUSEMOTION: + if (rotating) { + float rot_y = mouse_sensitivity * ev.motion.xrel; + float rot_x = mouse_sensitivity * ev.motion.yrel; + camera_yaw += rot_y; + camera_pitch += rot_x; + } + break; + case SDL_EventType::SDL_MOUSEBUTTONDOWN: + if (!ImGui::GetIO().WantCaptureMouse) { + rotating = true; + SDL_CaptureMouse(SDL_TRUE); + SDL_SetWindowMouseGrab(win, SDL_TRUE); + } + break; + case SDL_EventType::SDL_KEYDOWN: + if (!ImGui::GetIO().WantCaptureKeyboard) { + switch(ev.key.keysym.sym) { + case SDL_KeyCode::SDLK_w: + camera_movement.z -= 1.0f; + break; + case SDL_KeyCode::SDLK_s: + camera_movement.z += 1.0f; + break; + case SDL_KeyCode::SDLK_a: + camera_movement.x -= 1.0f; + break; + case SDL_KeyCode::SDLK_d: + camera_movement.x += 1.0f; + break; + case SDL_KeyCode::SDLK_ESCAPE: + rotating = false; + SDL_CaptureMouse(SDL_FALSE); + SDL_SetWindowMouseGrab(win, SDL_FALSE); + break; + } + } + break; + } + } + + if (!ImGui::IsAnyItemFocused()) { + camera_position += glm::xyz(glm::vec4((camera_movement * 0.05f * size), 0.0) * glm::mat4(camera_orientation)); + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + run_gl(win); + + SDL_GL_SwapWindow(win); + } + + if (data_buffer != 0) { + glDeleteBuffers(1, &data_buffer); + } + + glDeleteVertexArrays(1, &vao); + + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + SDL_GL_MakeCurrent(win, nullptr); + SDL_GL_DeleteContext(ctx); + + SDL_DestroyWindow(win); + + SDL_Quit(); + return 0; +} diff --git a/shaders/base.frag b/shaders/base.frag new file mode 100644 index 0000000..bf1ea6f --- /dev/null +++ b/shaders/base.frag @@ -0,0 +1,15 @@ +#version 460 + +layout (location = 3) uniform vec4 color; + +in vec4 pos; +//in vec3 normal; +//in vec2 uv; + +out vec4 out_color; + +void main() { + //vec3 norm = normalize(normal); + //out_color = vec4(dot(normalize(-pos.xyz), norm) * color.rgb, color.a); + out_color = color; +} \ No newline at end of file diff --git a/shaders/base.vert b/shaders/base.vert new file mode 100644 index 0000000..ffc5c1a --- /dev/null +++ b/shaders/base.vert @@ -0,0 +1,21 @@ +#version 460 + +layout (location = 0) in vec3 in_pos; +//layout (location = 1) in vec3 in_normal; +//layout (location = 2) in vec2 in_uv; + +layout(location = 0) uniform mat4 model; +layout(location = 1) uniform mat4 view; +layout(location = 2) uniform mat4 proj; + +out vec4 pos; +//out vec3 normal; +//out vec2 uv; + +void main() { + pos = view * model * vec4(in_pos, 1.0); + gl_Position = proj * pos; + pos /= pos.w; + //normal = in_normal; + //uv = in_uv; +} \ No newline at end of file