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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
--- a/plugins/cube/cube.cpp
+++ b/plugins/cube/cube.cpp
@@ -332,16 +332,14 @@
this->cube = cube;
auto grid = cube->output->wset()->get_workspace_grid_size();
auto current = cube->output->wset()->get_current_workspace();
- int count = cube->vertical_transition ? grid.height : grid.width;
+ // A vertical move translates complete Cube rows, including their
+ // side and rear faces. Keep textures for every row so fast steps
+ // and reversal preserve the visible position.
+ int count = cube->vertical_transition ? grid.height * grid.width : grid.width;
for (int i = 0; i < count; i++)
{
wf::point_t workspace = cube->vertical_transition ?
- wf::point_t{current.x, i} : wf::point_t{i, current.y};
- if (cube->vertical_transition && cube->workspace_animation_anchor &&
- (i == cube->workspace_animation_anchor->y))
- {
- workspace.x = cube->workspace_animation_anchor->x;
- }
+ wf::point_t{i % grid.width, i / grid.width} : wf::point_t{i, current.y};
auto node = std::make_shared<wf::workspace_stream_node_t>(
cube->output, workspace);
@@ -1209,13 +1207,18 @@
return wf::gles::render_target_gl_to_framebuffer(target) * scale;
}
- glm::mat4 calculate_vp_matrix(const wf::render_target_t& dest)
+ glm::mat4 calculate_vp_matrix(const wf::render_target_t& dest, float row_offset = 0.0f)
{
float zoom_factor = animation.cube_animation.zoom;
auto scale_matrix = glm::scale(glm::mat4(1.0),
glm::vec3(1. / zoom_factor, 1. / zoom_factor, 1. / zoom_factor));
- return output_transform(dest) * animation.projection * animation.view * scale_matrix;
+ // Translate the complete projected row by its viewport height. Doing
+ // this before the output transform keeps side/rear content moving at
+ // the same speed as the front, including rotated/scaled outputs.
+ auto row_translation = glm::translate(glm::mat4(1.0),
+ glm::vec3(0, 2 * row_offset, 0));
+ return output_transform(dest) * row_translation * animation.projection * animation.view * scale_matrix;
}
/* Calculate the base model matrix for the i-th side of the cube */
@@ -1242,78 +1245,52 @@
}
/* Render the sides of the cube, using the given culling mode - cw or ccw */
- void render_cube(GLuint front_face, std::vector<wf::auxilliary_buffer_t>& buffers)
+ void render_cube(GLuint front_face, std::vector<wf::auxilliary_buffer_t>& buffers,
+ const wf::render_target_t& target)
{
GL_CALL(glFrontFace(front_face));
static const GLuint indexData[] = {0, 1, 2, 0, 2, 3};
auto cws = output->wset()->get_current_workspace();
- const int count = get_num_faces();
- for (int i = 0; i < count; i++)
- {
- int index = (cws.x + i) % get_num_faces();
- GL_CALL(glBindTexture(GL_TEXTURE_2D, wf::gles_texture_t::from_aux(buffers[index]).tex_id));
- program.uniformMatrix4f("model", calculate_model_matrix(i));
-
- if (tessellation_support)
- {
+ const int faces = get_num_faces();
+ const int rows = vertical_transition ? (int)buffers.size() / faces : 1;
+ for (int row = 0; row < rows; row++)
+ {
+ // Move every face of a row together without changing its yaw,
+ // orientation, or perspective, including through the final frame.
+ const float offset = vertical_transition ?
+ row - cws.y + float(row_translation) : 0.0f;
+ program.uniformMatrix4f("VP", calculate_vp_matrix(target, offset));
+ for (int i = 0; i < faces; i++)
+ {
+ int index = row * faces + (cws.x + i) % faces;
+ GL_CALL(glBindTexture(GL_TEXTURE_2D, wf::gles_texture_t::from_aux(buffers[index]).tex_id));
+ program.uniformMatrix4f("model", calculate_model_matrix(i));
+
+ if (tessellation_support)
+ {
#ifdef USE_GLES32
- GL_CALL(glDrawElements(GL_PATCHES, 6, GL_UNSIGNED_INT, &indexData));
+ GL_CALL(glDrawElements(GL_PATCHES, 6, GL_UNSIGNED_INT, &indexData));
#endif
- } else
- {
- GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
- &indexData));
- }
- }
- }
-
- void render_vertical_rows(const wf::scene::render_instruction_t& data,
- std::vector<wf::auxilliary_buffer_t>& buffers)
- {
- const auto size = wf::dimensions(output->get_relative_geometry());
- const int current_row = output->wset()->get_current_workspace().y;
- // Round the shared offset once so adjacent rows meet without gaps.
- const int offset = std::lround(float(row_translation) * size.height);
+ } else
+ {
+ GL_CALL(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
+ &indexData));
+ }
+ }
+ }
+ }
+
+ void render(const wf::scene::render_instruction_t& data, std::vector<wf::auxilliary_buffer_t>& buffers)
+ {
data.pass->custom_gles_subpass([&]
{
- wf::gles::for_each_scissor_rect(data.target, data.damage, [&]
- {
- for (int i = 0; i < (int)buffers.size(); i++)
- {
- const int y = (i - current_row) * size.height + offset;
- if ((y >= size.height) || (y + size.height <= 0))
- {
- continue;
- }
-
- // Translate full-size workspace textures. No pitch, face
- // rotation, perspective scaling, or row wrapping.
- OpenGL::render_texture(wf::gles_texture_t::from_aux(buffers[i]),
- data.target, {0.0, double(y), double(size.width), double(size.height)});
- }
- });
- });
- }
-
- void render(const wf::scene::render_instruction_t& data, std::vector<wf::auxilliary_buffer_t>& buffers)
- {
- if (vertical_transition)
- {
- render_vertical_rows(data, buffers);
- return;
- }
-
- data.pass->custom_gles_subpass([&]
- {
if (program.get_program_id(wf::TEXTURE_TYPE_RGBA) == 0)
{
load_program();
}
/* The fixed output background is scheduled behind the cube. */
-
- auto vp = calculate_vp_matrix(data.target);
program.use(wf::TEXTURE_TYPE_RGBA);
GL_CALL(glEnable(GL_DEPTH_TEST));
@@ -1335,7 +1312,6 @@
program.attrib_pointer("position", 2, 0, vertexData);
program.attrib_pointer("uvPosition", 2, 0, coordData);
- program.uniformMatrix4f("VP", vp);
program.uniform1f("cube_brightness",
1.0 - wf::clamp((double)face_dim, 0.0, 1.0));
if (tessellation_support)
@@ -1359,8 +1335,8 @@
wf::gles::for_each_scissor_rect(data.target, data.damage, [&]
{
GL_CALL(glClear(GL_DEPTH_BUFFER_BIT));
- render_cube(GL_CCW, buffers);
- render_cube(GL_CW, buffers);
+ render_cube(GL_CCW, buffers, data.target);
+ render_cube(GL_CW, buffers, data.target);
});
GL_CALL(glDisable(GL_CULL_FACE));
GL_CALL(glDisable(GL_BLEND));
|