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