在 OpenGL-ES 中四处移动像素 (Android)

Move pixels around in OpenGL-ES (Android)

我有一个可以在 OpenGL-ES 中使用正交单位矩阵渲染的纹理:

gst_gl_shader_set_uniform_matrix_4fv(shader, "u_transformation", 1, FALSE, identity_matrix);

我要移动"the pixels around": 上面的一半向左移动,底部的一半向右移动,如下图所示。有 "easy" 方法吗?我在 Android.

在这个相关的已回答问题 上,我能够保留顶部 'a' 或底部 'e'。有没有办法在 "cutting" 场景之后将 "double gst_gl_shader_set_uniform_matrix_4fv" 一分为二?

这里你想要的变换不能用变换矩阵来表示。矩阵只能表示某些 类 的变换。 3D space:

  • 一个 3x3 矩阵表示一个线性变换。典型示例包括旋转、缩放、镜像、剪切。
  • 一个 4x3 矩阵表示一个仿射变换。除上述内容外,还包括翻译。
  • 如果将 3D space 扩展到具有 4 个分量的齐次坐标,则 4x4 矩阵可以表示额外的 类 变换,例如投影。

你草图中的变换是上面的none。所以对你的顶点应用矩阵将无法做到这一点。

那你能做什么?我想到了两个选项:

  1. 如果您可以轻松地分别绘制两个部分 (top/bottom、left/right),您显然可以做到这一点,只需更改渲染两个部分之间的变换即可。
  2. 在着色器代码中应用逻辑。

对于选项 2,您可以在顶点着色器或片段着色器中执行此操作。如果您没有跨越两个部分之间边界的基元,则在顶点着色器中处理它会更有效。否则,可以在片段着色器中使用类似的逻辑。

绘制顶点着色器情况下的关键部分,假设您目前有以下内容可以在草图的左侧进行排列:

// Calculate output position and store it in variable "pos".
gl_Position = pos;

要获得第二种排列,逻辑可能如下所示(完全未经测试...):

if (pos.y > 0.0) {
    gl_Position = vec4(0.5 * pos.x - 0.5, 2.0 * pos.y - 1.0, pos.zw)
} else {
    gl_Position = vec4(0.5 * pos.x + 0.5, 2.0 * pos.y + 1.0, pos.zw);
}

想法是检查顶点是在上半部分还是下半部分,然后scale/shift相应地将坐标space的上半部分映射到左半部分,然后坐标的下半部分space变成右半部分。

这可以通过用 sign 操作替换条件来进一步简化:

float s = sign(pos.y);
gl_Position = vec4(0.5 * pos.x - sign * 0.5, 2.0 * pos.y - sign, pos.zw);

如果 pos.w 不是 1.0,则需要多加注意,例如,将透视投影应用于您的顶点。在这种情况下,您必须在上面的计算中包含 w 的除法。

Reto 回答 'semi' 中描述的公式起作用,因为它们只产生左侧的 "a" 或右侧的 "e",但不会同时产生两者。

我找到的解决方案是将顶点和索引的数量加倍,然后像这样处理顶点坐标:

static const GLfloat vertices[] = {
1.0f,  1.0f, 0.0f, 1.0f, 0.0f,
0.0f,  1.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 0.0f, 0.5f,
1.0f, -1.0f, 0.0f, 1.0f, 0.5f,

0.0f,  1.0f, 0.0f, 1.0f, 0.5f,
-1.0f,  1.0f, 0.0f, 0.0f, 0.5f,
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.0f, -1.0f, 0.0f, 1.0f, 1.0f
};

static const GLushort indices[] = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 };