1 #include "wall_renderer.hpp"
2 #include "canvas/gl_util.hpp"
3 #include "canvas3d_base.hpp"
4 #include <cmath>
5 #include <glm/glm.hpp>
6 #include <glm/gtc/matrix_transform.hpp>
7 #include <glm/gtc/type_ptr.hpp>
8
9 namespace horizon {
WallRenderer(Canvas3DBase & c)10 WallRenderer::WallRenderer(Canvas3DBase &c) : ca(c)
11 {
12 }
13
create_vao(GLuint program,GLuint & vbo_out)14 static GLuint create_vao(GLuint program, GLuint &vbo_out)
15 {
16 GLuint position_index = glGetAttribLocation(program, "position");
17 GLuint vao, buffer;
18
19 /* we need to create a VAO to store the other buffers */
20 glGenVertexArrays(1, &vao);
21 glBindVertexArray(vao);
22
23 /* this is the VBO that holds the vertex data */
24 glGenBuffers(1, &buffer);
25 glBindBuffer(GL_ARRAY_BUFFER, buffer);
26
27 CanvasMesh::Layer3D::Vertex vertices[] = {
28 // Position
29 {-5, -5}, {5, -5}, {-5, 5},
30
31 {5, 5}, {5, -5}, {-5, 5},
32 };
33 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
34
35 /* enable and set the position attribute */
36 glEnableVertexAttribArray(position_index);
37 glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE, sizeof(CanvasMesh::Layer3D::Vertex), 0);
38
39 /* enable and set the color attribute */
40 /* reset the state; we will re-enable the VAO when needed */
41 glBindBuffer(GL_ARRAY_BUFFER, 0);
42 glBindVertexArray(0);
43
44 // glDeleteBuffers (1, &buffer);
45 vbo_out = buffer;
46
47 return vao;
48 }
49
realize()50 void WallRenderer::realize()
51 {
52 program = gl_create_program_from_resource("/org/horizon-eda/horizon/canvas3d/shaders/wall-vertex.glsl",
53 "/org/horizon-eda/horizon/canvas3d/shaders/wall-fragment.glsl",
54 "/org/horizon-eda/horizon/canvas3d/shaders/"
55 "wall-geometry.glsl");
56 vao = create_vao(program, vbo);
57
58 GET_LOC(this, view);
59 GET_LOC(this, proj);
60 GET_LOC(this, layer_offset);
61 GET_LOC(this, layer_thickness);
62 GET_LOC(this, layer_color);
63 GET_LOC(this, cam_normal);
64 }
65
push()66 void WallRenderer::push()
67 {
68 glBindBuffer(GL_ARRAY_BUFFER, vbo);
69 n_vertices = 0;
70 for (const auto &it : ca.ca.get_layers()) {
71 n_vertices += it.second.walls.size();
72 }
73 glBufferData(GL_ARRAY_BUFFER, sizeof(CanvasMesh::Layer3D::Vertex) * n_vertices, nullptr, GL_STREAM_DRAW);
74 GL_CHECK_ERROR
75 size_t ofs = 0;
76 layer_offsets.clear();
77 for (const auto &it : ca.ca.get_layers()) {
78 glBufferSubData(GL_ARRAY_BUFFER, ofs * sizeof(CanvasMesh::Layer3D::Vertex),
79 it.second.walls.size() * sizeof(CanvasMesh::Layer3D::Vertex), it.second.walls.data());
80 layer_offsets[it.first] = ofs;
81 ofs += it.second.walls.size();
82 }
83 glBindBuffer(GL_ARRAY_BUFFER, 0);
84 }
85
render(int layer)86 void WallRenderer::render(int layer)
87 {
88 if (ca.ca.get_layer(layer).alpha != 1)
89 return;
90 auto co = ca.get_layer_color(layer);
91 glUniform4f(layer_color_loc, co.r, co.g, co.b, ca.ca.get_layer(layer).alpha);
92 glUniform1f(layer_offset_loc, ca.get_layer_offset(layer));
93 glUniform1f(layer_thickness_loc, ca.get_layer_thickness(layer));
94 glDrawArrays(GL_LINE_STRIP_ADJACENCY, layer_offsets[layer], ca.ca.get_layer(layer).walls.size());
95 }
96
render()97 void WallRenderer::render()
98 {
99 glUseProgram(program);
100 glBindVertexArray(vao);
101
102 glUniformMatrix4fv(view_loc, 1, GL_FALSE, glm::value_ptr(ca.viewmat));
103 glUniformMatrix4fv(proj_loc, 1, GL_FALSE, glm::value_ptr(ca.projmat));
104 glUniform3fv(cam_normal_loc, 1, glm::value_ptr(ca.cam_normal));
105
106 for (const auto &it : layer_offsets) {
107 if (ca.layer_is_visible(it.first))
108 render(it.first);
109 }
110 }
111 } // namespace horizon
112