#include "Render.hpp" #include "Assets.hpp" #include "Defines.hpp" #include "ThreadRole.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() { HELLO_I_AM(ThreadRole::Render); 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(scene.camera.position(), scene.camera.angles()); auto projection = Math::MVP::perspective_projection(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(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(glewGetErrorString(error))); throw std::runtime_error("Failed to load GL functions: " + error_string); } } }