Initial Commit

This commit is contained in:
jstefanelli 2025-05-13 15:33:42 +02:00
commit 913950478c
Signed by: jstefanelli
GPG key ID: 60EDE2437640D2AA
10 changed files with 775 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
cmake-build-debug

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "contrib/imgui"]
path = contrib/imgui
url = git@github.com:ocornut/imgui.git

29
CMakeLists.txt Normal file
View file

@ -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)

4
contrib/CMakeLists.txt Normal file
View file

@ -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)

1
contrib/imgui Submodule

@ -0,0 +1 @@
Subproject commit f9cda1fa245b361a0e98428d88470eebaa187e5b

80
gl_debug.cpp Normal file
View file

@ -0,0 +1,80 @@
#include <iostream>
#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

7
gl_debug.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef GL_DEBUG_H
#define GL_DEBUG_H
#include <GL/glew.h>
extern void GLAPIENTRY debug_func(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* msg, const void*);
#endif //GL_DEBUG_H

614
main.cpp Normal file
View file

@ -0,0 +1,614 @@
#include <iostream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/vec_swizzle.hpp>
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include <set>
#include <unordered_set>
#include <fstream>
#include <unistd.h>
#include <vector>
#include <imgui.h>
#include <backends/imgui_impl_sdl2.h>
#include <backends/imgui_impl_opengl3.h>
#include <filesystem>
#include <algorithm>
#ifdef __DEBUG
#include "gl_debug.h"
#endif
template<typename T>
bool contains(const std::vector<T>& 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<char> 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<GLchar> 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<GLchar>(stream), std::istreambuf_iterator<GLchar>());
auto id = glCreateShader(type);
const auto* data = bytes.data();
auto len = static_cast<GLint>(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<std::string> extensions;
for(auto i = 0; i < count; i++) {
const char* ext = reinterpret_cast<const char*>(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<in_vertex> loaded_vertices;
std::vector<out_vertex> 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<in_vertex> 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<std::string> 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<std::string>(indices, "o4.x") && contains<std::string>(indices, "o4.y") && !contains<std::string>(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>();
glm::mat4 display_view = glm::identity<glm::mat4>();
glm::mat4 display_model = glm::identity<glm::mat4>();
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<glm::mat4>(), -camera_position);
camera_orientation = glm::identity<glm::quat>();
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::mat4>(), 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<float>(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<float>(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;
}

15
shaders/base.frag Normal file
View file

@ -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;
}

21
shaders/base.vert Normal file
View file

@ -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;
}