diff options
Diffstat (limited to 'src/Render.cpp')
| -rw-r--r-- | src/Render.cpp | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/Render.cpp b/src/Render.cpp new file mode 100644 index 0000000..3955f1c --- /dev/null +++ b/src/Render.cpp @@ -0,0 +1,102 @@ +#include "Render.hpp" +#include "Assets.hpp" +#include "Defines.hpp" +#include "Time.hpp" +#include "Common/Assert.hpp" +#include "GFX/Image/PPMParser.hpp" +#include "GFX/Shading/Program.hpp" +#include "Math/MVP.hpp" + +namespace MC { + +void Render::run() { + m_window.attach(); + setup_gl(); + + m_resources.initialize(); + + glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); + m_window.on_size_change([](GLFWwindow* _, I32 w, I32 h) { + glViewport(0, 0, w, h); + }); + + auto image = GFX::Image::PPMParser(Assets::Images::atlas).parse(); + auto texture = GFX::Texture(image); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + + while (!m_window.should_close()) { + Scene scene = m_control->wait_for_render_data(); + + m_window.start_render(); + render_scene(scene, texture); + + m_control->finish_render(); + } +} + +void Render::render_scene(Scene const& scene, GFX::Texture const& texture) const { + Vector<3, F32> sky_color = SKY_COLOR; + glClearColor(sky_color.x(), sky_color.y(), sky_color.z(), 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + auto view = Math::MVP::view<F32>(scene.camera.position(), scene.camera.angles()); + auto projection = Math::MVP::perspective_projection<F32>(ASPECT, FOV, 0.1f, 1000.0f); + + for (auto& action : scene.actions.actions()) { + auto& program = m_resources.program(action.program); + program.bind(); + + auto model_uniform = program.uniform("model_matrix"); + auto view_uniform = program.uniform("view_matrix"); + auto projection_uniform = program.uniform("projection_matrix"); + auto sun_direction_uniform = program.uniform("sun_direction"); + auto sky_color_uniform = program.uniform("sky_color"); + auto mesh_alpha_uniform = program.uniform("mesh_alpha"); + + ASSERT(model_uniform.has_value() && view_uniform.has_value() && projection_uniform.has_value(), + "Program does not have the necessary MVP uniforms"); + + auto transform = action.transform; + auto model = Math::MVP::model<F32>(transform.position(), transform.scale(), transform.rotation()); + + model_uniform->set(model); + view_uniform->set(view); + projection_uniform->set(projection); + + if (sun_direction_uniform.has_value()) + sun_direction_uniform->set(SUN_DIRECTION); + + if (sky_color_uniform.has_value()) + sky_color_uniform->set(SKY_COLOR); + + if (mesh_alpha_uniform.has_value()) + mesh_alpha_uniform->set(action.alpha); + + texture.bind(); + action.mesh->bind(); + glDrawElements(TO(GLenum, action.draw_mode), action.mesh->size(), GL_UNSIGNED_INT, nullptr); + action.mesh->unbind(); + texture.unbind(); + + program.unbind(); + } +} + +void Render::setup_gl() { + GLenum error = glewInit(); + if (error != GLEW_OK) { + std::string error_string(reinterpret_cast<Char const*>(glewGetErrorString(error))); + throw std::runtime_error("Failed to load GL functions: " + error_string); + } +} + +} |
