1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#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<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);
}
}
}
|