aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-02-22 08:55:48 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-18 15:22:10 +0100
commit9ab59b76c0ece5e261c0152af3f830f48532e103 (patch)
treeae66d456fa58d4f98ea74759bcc2bb9e2f50efae
parentf2f8ccc1c24ab372ffe5e932780eeb1c49a4d277 (diff)
Fix rendering of character
-rw-r--r--README.md3
-rw-r--r--include/RenderBackend/OpenGL/ShaderFrame.hpp4
-rw-r--r--shaders/fragment_no_texture.frag7
-rw-r--r--shaders/vertex_no_texture.vert11
-rw-r--r--src/RenderBackend/OpenGL/ShaderFrame.cpp30
-rw-r--r--src/RenderBackend/OpenGL/Texture2D.cpp2
-rw-r--r--src/main.cpp147
-rw-r--r--src/model_loader/ObjModelLoader.cpp96
8 files changed, 202 insertions, 98 deletions
diff --git a/README.md b/README.md
index 2168a8a..d7dcf18 100644
--- a/README.md
+++ b/README.md
@@ -5,4 +5,5 @@ glm
sibs (https://github.com/DEC05EBA/sibs)
# TODO
-Make use shader a no-op if already in use \ No newline at end of file
+* Make use shader a no-op if already in use.
+* Render vertices using glDrawElements instead of glDrawArrays. \ No newline at end of file
diff --git a/include/RenderBackend/OpenGL/ShaderFrame.hpp b/include/RenderBackend/OpenGL/ShaderFrame.hpp
index da0918e..01cec92 100644
--- a/include/RenderBackend/OpenGL/ShaderFrame.hpp
+++ b/include/RenderBackend/OpenGL/ShaderFrame.hpp
@@ -16,8 +16,8 @@ namespace amalgine {
friend class ShaderProgram;
public:
~ShaderFrame();
- ShaderFrame(ShaderFrame &&other) = default;
- ShaderFrame& operator=(ShaderFrame &&other) = default;
+ ShaderFrame(ShaderFrame &&other);
+ ShaderFrame& operator=(ShaderFrame &&other);
DeviceMemory* get_input_by_name(const char *name);
Result<Uniform> get_uniform_by_name(const char *name);
diff --git a/shaders/fragment_no_texture.frag b/shaders/fragment_no_texture.frag
new file mode 100644
index 0000000..f6d7bf1
--- /dev/null
+++ b/shaders/fragment_no_texture.frag
@@ -0,0 +1,7 @@
+#version 330 core
+
+out vec4 out_color;
+
+void main() {
+ out_color = vec4(1.0, 1.0, 1.0, 1.0);
+} \ No newline at end of file
diff --git a/shaders/vertex_no_texture.vert b/shaders/vertex_no_texture.vert
new file mode 100644
index 0000000..a44217b
--- /dev/null
+++ b/shaders/vertex_no_texture.vert
@@ -0,0 +1,11 @@
+#version 330 core
+
+in vec3 position;
+
+uniform mat4 proj;
+uniform mat4 view;
+uniform mat4 model;
+
+void main() {
+ gl_Position = proj * view * model * vec4(position, 1.0);
+} \ No newline at end of file
diff --git a/src/RenderBackend/OpenGL/ShaderFrame.cpp b/src/RenderBackend/OpenGL/ShaderFrame.cpp
index 3f7ff01..dc2653c 100644
--- a/src/RenderBackend/OpenGL/ShaderFrame.cpp
+++ b/src/RenderBackend/OpenGL/ShaderFrame.cpp
@@ -7,7 +7,22 @@ namespace amalgine {
}
ShaderFrame::~ShaderFrame() {
- glDeleteVertexArrays(1, &vertex_array_object_id);
+ if(vertex_array_object_id != -1)
+ glDeleteVertexArrays(1, &vertex_array_object_id);
+ }
+
+ ShaderFrame::ShaderFrame(ShaderFrame &&other) {
+ this->operator=(std::move(other));
+ }
+
+ ShaderFrame& ShaderFrame::operator=(ShaderFrame &&other) {
+ shader_program_id = other.shader_program_id;
+ vertex_array_object_id = other.vertex_array_object_id;
+ shader_inputs = std::move(other.shader_inputs);
+
+ other.shader_program_id = -1;
+ other.vertex_array_object_id = -1;
+ return *this;
}
DeviceMemory* ShaderFrame::get_input_by_name(const char *name) {
@@ -44,10 +59,23 @@ namespace amalgine {
glUseProgram(shader_program_id);
glBindVertexArray(vertex_array_object_id); // Set the active shader to use the data encapsulated by the vertex array object
// TODO: Cache this num_vertices count (and reset it when device memory has changed)
+#if 0
int num_vertices = 0;
for(const auto &it : shader_inputs) {
num_vertices = std::max(num_vertices, it.second->get_num_vertices());
}
+#endif
+ int num_vertices = 0;
+ for(const auto &it : shader_inputs) {
+ int new_num_vertices = std::max(num_vertices, it.second->get_num_vertices());
+#if 0
+ if(num_vertices != 0 && new_num_vertices != num_vertices) {
+ fprintf(stderr, "All inputs for shaders need to be of the same size!\n");
+ abort();
+ }
+#endif
+ num_vertices = new_num_vertices;
+ }
// TODO: Allow specifying mode different than GL_TRIANGLES
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
}
diff --git a/src/RenderBackend/OpenGL/Texture2D.cpp b/src/RenderBackend/OpenGL/Texture2D.cpp
index 7d1b83c..089a5f1 100644
--- a/src/RenderBackend/OpenGL/Texture2D.cpp
+++ b/src/RenderBackend/OpenGL/Texture2D.cpp
@@ -72,9 +72,9 @@ namespace amalgine {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glGenerateMipmap(GL_TEXTURE_2D);
}
Texture2D::~Texture2D()
diff --git a/src/main.cpp b/src/main.cpp
index 33488bb..f2b2c3f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -54,8 +54,13 @@ static std::vector<Triangle3D> generate_sand() {
return vertices;
}
+struct Model {
+ ShaderFrame frame;
+ Texture2D texture;
+};
+
static void create_sand(DeviceMemory *triangles, DeviceMemory *texcoords, Texture2D *texture);
-static DeviceMemory* load_model(const char *filepath);
+static Model load_model(const char *filepath, ShaderProgram *shader_program);
int main() {
initGlfw();
@@ -65,7 +70,7 @@ int main() {
int window_height = 1;
glfwGetWindowSize(window, &window_width, &window_height);
- glm::mat4 proj = glm::perspective(glm::radians(75.0f), (float)window_width / (float)window_height, 0.2f, 1000.0f);
+ glm::mat4 proj = glm::perspective(glm::radians(75.0f), (float)window_width / (float)window_height, 0.01f, 1000.0f);
std::unique_ptr<Shader> sand_vertex_shader = load_shader_from_file("shaders/sand_vertex.vert", Shader::Type::VERTEX);
std::unique_ptr<Shader> sand_pixel_shader = load_shader_from_file("shaders/sand_fragment.frag", Shader::Type::PIXEL);
@@ -91,30 +96,44 @@ int main() {
std::unique_ptr<Shader> vertex_shader = load_shader_from_file("shaders/vertex.vert", Shader::Type::VERTEX);
std::unique_ptr<Shader> pixel_shader = load_shader_from_file("shaders/fragment.frag", Shader::Type::PIXEL);
std::unique_ptr<ShaderProgram> shader_program = build_shader_program_from_shaders({ vertex_shader.get(), pixel_shader.get() });
- ShaderFrame model_frame = shader_program->create_frame();
-
- std::vector<Triangle3D> triangles;
- std::vector<vec2f> texture_coords;
- Image *image;
- ObjModelLoader::load_from_file("/home/dec05eba/Downloads/ELI4OS.obj", triangles, texture_coords, &image);
- DeviceMemory *gpuModel = model_frame.get_input_by_name("position");
- gpuModel->set({triangles.data(), triangles.size()}, DeviceMemory::StorageType::STATIC);
+ Model buddha_model = load_model("/home/dec05eba/Downloads/ELI4OS.obj", shader_program.get());
+ buddha_model.frame.get_uniform_by_name("proj")->set(proj);
+ Result<Uniform> view_uniform = buddha_model.frame.get_uniform_by_name("view");
+ Result<Uniform> model_uniform = buddha_model.frame.get_uniform_by_name("model");
+
+ std::unique_ptr<Shader> vertex_no_texture_shader = load_shader_from_file("shaders/vertex_no_texture.vert", Shader::Type::VERTEX);
+ std::unique_ptr<Shader> pixel_no_texture_shader = load_shader_from_file("shaders/fragment_no_texture.frag", Shader::Type::PIXEL);
+ std::unique_ptr<ShaderProgram> no_texture_shader_program = build_shader_program_from_shaders({ vertex_no_texture_shader.get(), pixel_no_texture_shader.get() });
+ Model character_model = load_model("/home/dec05eba/Downloads/FinalBaseMesh.obj", no_texture_shader_program.get());
+ character_model.frame.get_uniform_by_name("proj")->set(proj);
+ Result<Uniform> char_view_uniform = character_model.frame.get_uniform_by_name("view");
+ Result<Uniform> char_model_uniform = character_model.frame.get_uniform_by_name("model");
+
+
+
+ glm::mat4 model = glm::rotate(
+ glm::mat4(1.0f),
+ 0.0f,
+ glm::vec3(0.0f, 0.0f, 1.0f)
+ );
+ model_uniform->set(model);
+
+ glm::mat4 char_model = glm::rotate(
+ glm::mat4(1.0f),
+ glm::pi<float>() * 0.5f,
+ glm::vec3(1.0f, 0.0f, 0.0f)
+ );
+ char_model = glm::scale(char_model, glm::vec3(0.1f, 0.1f, 0.1f));
+ char_model_uniform->set(char_model);
+
+ glm::mat4 sand_model = glm::rotate(
+ glm::mat4(1.0f),
+ 0.0f,
+ glm::vec3(0.0f, 0.0f, 1.0f)
+ );
+ sand_model = glm::scale(sand_model, glm::vec3(50.0f, 50.0f, 50.0f));
+ sand_model_uniform->set(sand_model);
- Texture2D model_texture(image);
- delete image;
- DeviceMemory *model_gpu_texcoords = model_frame.get_input_by_name("texcoord_vert");
- model_gpu_texcoords->set({texture_coords.data(), texture_coords.size()}, DeviceMemory::StorageType::STATIC);
-
- Result<Uniform> proj_uniform = model_frame.get_uniform_by_name("proj");
- Result<Uniform> view_uniform = model_frame.get_uniform_by_name("view");
- Result<Uniform> model_uniform = model_frame.get_uniform_by_name("model");
- Result<Uniform> tex_uniform = model_frame.get_uniform_by_name("tex");
-
- proj_uniform->set(proj);
- tex_uniform->set(model_texture);
-
- triangles.resize(0);
- texture_coords.resize(0);
Userdata userdata;
ThirdPersonCamera third_person_camera;
@@ -128,7 +147,7 @@ int main() {
glfwSetScrollCallback(window, [](GLFWwindow *window, double xoffset, double yoffset){
Userdata *userdata = (Userdata*)glfwGetWindowUserPointer(window);
- userdata->third_person_camera->zoom(-yoffset);
+ userdata->third_person_camera->zoom(-yoffset*0.1f);
});
glfwSetCursorPosCallback(window, [](GLFWwindow *window, double xpos, double ypos) {
@@ -158,13 +177,9 @@ int main() {
t_start = t_now;
time += time_delta;
- glm::mat4 camera_matrix = third_person_camera.get_matrix();
glm::vec3 camera_forward = third_person_camera.get_forward_vector();
glm::vec3 camera_right = third_person_camera.get_right_vector();
- sand_view_uniform->set(camera_matrix);
- view_uniform->set(camera_matrix);
-
float move_speed = time_delta * 3.0f;
glm::vec3 move_vec = glm::vec3();
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
@@ -183,40 +198,32 @@ int main() {
move_vec.x += camera_right.x;
move_vec.y += camera_right.y;
}
+
if(glm::length(move_vec) > 0.0f)
character_pos += (glm::normalize(move_vec) * move_speed);
+
third_person_camera.set_target_position(character_pos);
+ char_model[3][0] = character_pos.x;
+ char_model[3][1] = character_pos.y;
+ char_model[3][2] = character_pos.z - 2.0f;
+ char_model_uniform->set(char_model);
- glm::mat4 model = glm::mat4(1.0f);
- model = glm::rotate(
- model,
- 0.0f,
- glm::vec3(0.0f, 0.0f, 1.0f)
- );
- model_uniform->set(model);
-
- glm::mat4 sand_model = glm::mat4(1.0f);
- sand_model = glm::rotate(
- sand_model,
- 0.0f,
- glm::vec3(0.0f, 0.0f, 1.0f)
- );
- sand_model = glm::scale(sand_model, glm::vec3(50.0f, 50.0f, 50.0f));
- sand_model_uniform->set(sand_model);
-
- //printf("now: %f\n", time);
- //sand_time->set(time);
+ glm::mat4 camera_matrix = third_person_camera.get_matrix();
+ sand_view_uniform->set(camera_matrix);
+ view_uniform->set(camera_matrix);
+ char_view_uniform->set(camera_matrix);
// Set color for clearing
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Do the actual screen clearing, using the color set using glClearColor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- model_frame.draw();
+ buddha_model.frame.draw();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ character_model.frame.draw();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
sand_frame.draw();
- //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glfwSwapBuffers(window);
}
@@ -247,8 +254,32 @@ void create_sand(DeviceMemory *triangles, DeviceMemory *texcoords, Texture2D *te
texcoords->set({height_map_texcoord.data(), height_map_texcoord.size()}, DeviceMemory::StorageType::STATIC);
}
-DeviceMemory* load_model(const char *filepath) {
- return nullptr;
+Model load_model(const char *filepath, ShaderProgram *shader_program) {
+ ShaderFrame model_frame = shader_program->create_frame();
+
+ std::vector<Triangle3D> triangles;
+ std::vector<vec2f> texture_coords;
+ Image *image;
+ ObjModelLoader::load_from_file(filepath, triangles, texture_coords, &image);
+ // TODO: This needs to be done to prevent crash in glDrawArrays, but this should not be used when shader doesn't handle any texture
+ //if(texture_coords.size() < triangles.size())
+ // texture_coords.resize(triangles.size());
+
+ DeviceMemory *gpuModel = model_frame.get_input_by_name("position");
+ gpuModel->set({triangles.data(), triangles.size()}, DeviceMemory::StorageType::STATIC);
+
+ if(image) {
+ Texture2D model_texture(image);
+ delete image;
+ DeviceMemory *model_gpu_texcoords = model_frame.get_input_by_name("texcoord_vert");
+ model_gpu_texcoords->set({texture_coords.data(), texture_coords.size()}, DeviceMemory::StorageType::STATIC);
+
+ Result<Uniform> tex_uniform = model_frame.get_uniform_by_name("tex");
+ tex_uniform->set(model_texture);
+ return { std::move(model_frame), std::move(model_texture) };
+ } else {
+ return { std::move(model_frame), Texture2D() };
+ }
}
void glfwErrorHandler(int errorCode, const char *errorDescription)
@@ -282,10 +313,10 @@ void initGlfw()
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
if(flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
- glEnable(GL_DEBUG_OUTPUT);
- glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- glDebugMessageCallback(gl_debug_callback, nullptr);
- glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
+ //glEnable(GL_DEBUG_OUTPUT);
+ //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ //glDebugMessageCallback(gl_debug_callback, nullptr);
+ //glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
} else {
fprintf(stderr, "Warning: failed to enable gl debugging\n");
}
diff --git a/src/model_loader/ObjModelLoader.cpp b/src/model_loader/ObjModelLoader.cpp
index f70123a..7976bc9 100644
--- a/src/model_loader/ObjModelLoader.cpp
+++ b/src/model_loader/ObjModelLoader.cpp
@@ -11,10 +11,12 @@
namespace amalgine {
static StringView get_line(char *str, size_t size) {
- char *found_ptr = (char*)memchr(str, '\n', size);
- if(!found_ptr)
- found_ptr = str + size;
- return { str, static_cast<size_t>(found_ptr - str) };
+ for(size_t i = 0; i < size; ++i) {
+ char c = str[i];
+ if(c == '\n' || c == '\r')
+ return { str, i };
+ }
+ return { str, size };
}
static bool is_whitespace(char c) {
@@ -70,6 +72,29 @@ namespace amalgine {
return static_cast<size_t>(found_ptr - str.data);
}
+ struct FaceData {
+ int vertex_index;
+ int texcoord_index;
+ int normal_index;
+ };
+
+ // TODO: Optimize? dont use sscanf 3 times
+ static bool split_faces(StringView *input, FaceData *face_data) {
+ input->data[input->size] = '\0';
+
+ face_data->vertex_index = 0;
+ face_data->texcoord_index = 0;
+ face_data->normal_index = 0;
+ if(sscanf(input->data, "%d/%d/%d", &face_data->vertex_index, &face_data->texcoord_index, &face_data->normal_index) == 3)
+ return true;
+
+ face_data->texcoord_index = 0;
+ if(sscanf(input->data, "%d//%d", &face_data->vertex_index, &face_data->normal_index) == 2)
+ return true;
+
+ return sscanf(input->data, "%d/%d", &face_data->vertex_index, &face_data->texcoord_index) == 2;
+ }
+
struct Material {
Image *image;
};
@@ -120,21 +145,22 @@ namespace amalgine {
int num_columns = split_columns(column_data, ' ', columns, max_columns);
if(num_columns == 3 || num_columns == 4) {
bool valid = true;
+ // TODO: Handle these when they are not set in the below loop
int vertex_indices[4];
int texture_coord_indices[4];
+ int normal_indices[4]; // TODO: Use this
for(int i = 0; i < num_columns; ++i) {
- const int max_attributes = 3;
- StringView attributes[max_attributes];
- int num_attributes = split_columns(columns[i], '/', attributes, max_attributes);
- assert(num_attributes == 3);
-
- attributes[0].data[attributes[0].size] = '\0';
- attributes[1].data[attributes[1].size] = '\0';
- attributes[2].data[attributes[2].size] = '\0';
+ FaceData face_data;
+ if(!split_faces(&columns[i], &face_data)) {
+ valid = false;
+ abort();
+ break;
+ }
- vertex_indices[i] = atoi(attributes[0].data);
- texture_coord_indices[i] = atoi(attributes[1].data);
+ vertex_indices[i] = face_data.vertex_index;
+ texture_coord_indices[i] = face_data.texcoord_index;
+ normal_indices[i] = face_data.normal_index;
if(vertex_indices[i] < 1 || vertex_indices[i] > vertices.size()) {
valid = false;
@@ -142,7 +168,7 @@ namespace amalgine {
break;
}
- if(texture_coord_indices[i] < 1 || texture_coord_indices[i] > temp_texture_coords.size()) {
+ if(texture_coord_indices[i] != 0 && (texture_coord_indices[i] < 1 || texture_coord_indices[i] > temp_texture_coords.size())) {
valid = false;
abort();
break;
@@ -150,26 +176,31 @@ namespace amalgine {
--vertex_indices[i];
--texture_coord_indices[i];
+ --normal_indices[i];
}
if(valid) {
if(num_columns == 3) { // Triangle
triangles.push_back({ vertices[vertex_indices[0]], vertices[vertex_indices[1]], vertices[vertex_indices[2]] });
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
+ if(texture_coord_indices[0] >= 0) {
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
+ }
} else if(num_columns == 4) { // Quad, convert to triangle. TODO: Support rendering quads instead of converting to triangles
triangles.push_back({ vertices[vertex_indices[0]], vertices[vertex_indices[1]], vertices[vertex_indices[2]] });
triangles.push_back({ vertices[vertex_indices[2]], vertices[vertex_indices[3]], vertices[vertex_indices[0]] });
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
+ if(texture_coord_indices[0] >= 0) {
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[1]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[3]]);
- texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[2]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[3]]);
+ texture_coords.push_back(temp_texture_coords[texture_coord_indices[0]]);
+ }
}
}
}
@@ -185,22 +216,17 @@ namespace amalgine {
StringView column_data = { line_data.data + 7, line_data.size - 7 };
int num_columns = split_columns(column_data, ' ', columns, max_columns);
if(num_columns == 1) {
- std::string material_path;
- material_path.resize(dir_path_size + 1 + columns[0].size);
- memcpy(&material_path[0], dir_path.data(), dir_path_size);
- material_path[dir_path_size] = '/';
- memcpy(&material_path[dir_path_size + 1], columns[0].data, columns[0].size);
- printf("mtl file: %.*s\n", material_path.size(), material_path.data());
+ std::string material_path = dir_path + '/';
+ material_path.append(columns[0].data, columns[0].size);
+ printf("mtl file: %s\n", material_path.c_str());
assert(!*image);
Result<Material> material = load_material_from_file(material_path.c_str());
if(!material) {
- fprintf(stderr, "Error: %s\n", material.getErrorMsg().c_str());
- abort();
- goto cleanup;
+ fprintf(stderr, "Warning: %s\n", material.getErrorMsg().c_str());
+ } else {
+ *image = material->image;
}
-
- *image = material->image;
}
}