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