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

时间:2016-03-11 22:34:24

标签: android opengl-es opengl-es-2.0

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

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

我想移动“周围的像素”:顶部的一半向左移动,底部的一半向右移动,如下图所示。有一种“简单”的方法吗?我在Android上。

在这个相关回答的问题How to crop/clip in OpenGL using u_transformation上,我能够保持顶部'a'或底部'e'。在“切割”两个场景后,有没有办法做“双gst_gl_shader_set_uniform_matrix_4fv”?

enter image description here

2 个答案:

答案 0 :(得分:1)

此处所需的转换无法通过转换矩阵表示。矩阵只能代表某些类型的转换。在3D空间:

  • 3x3矩阵表示线性变换。典型的例子包括旋转,缩放,镜像,剪切。
  • 4x3矩阵表示仿射变换。除此之外,还包括翻译。
  • 如果将3D空间扩展为具有4个分量的同质坐标,则4x4矩阵可以表示其他类型的变换,例如投影。

草图中的变换不是上述内容。因此,将矩阵应用于顶点将无法执行此操作。

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

  1. 如果您可以轻松地分别绘制两个部分(顶部/底部,左侧/右侧),您可以明显地这样做,只需更改渲染这两个部分之间的转换。
  2. 在着色器代码中应用逻辑。
  3. 对于选项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);
    }
    

    这个想法是你检查顶点是在顶部还是在底部,并相应地缩放/移动它以将坐标空间的上半部分映射到左半部分,并将坐标空间的下半部分映射到右半边。

    通过用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合并。

答案 1 :(得分:0)

Reto中描述的公式回答'半'工作,因为他们只生产" 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 };