顶点着色器是否可用于翻页效果?

时间:2014-02-14 15:38:02

标签: java android opengl-es-2.0 shader

我过去曾经做过Open GL ES,但很久以前。从我现在阅读的内容来看,似乎更加强调管理自己的矩阵堆栈并将矩阵直接推入顶点着色器来定位对象。

这一切都很好,但我只是想知道你与着色器有多远意义。我不知道它们是否仅用于简单的事情,或者我可以将它们用于翻页效果。肯定会有很多数学需要计算。感觉这是一个很好的地方,但我没有经验知道是否有任何问题。

我打算输入一个指向着色器手指位置的点,然后着色器将根据手指位置偏移构成页面的网格中的每个顶点。

我将在使用OpenGl ES 2.0的Android应用中尝试此操作。

所以,

问题

这看起来是一种合理的方法,如果不是,那么在我需要的效果和模式化OpenGL API的情况下,最好的方法是如何充分利用图形芯片?

到目前为止我所研究的内容

我已经阅读了许多博客和教程,包括Tutorials for Modern Open GL,但着色器始终用于照明或基本定位。我认为页面转换效果的计算可能需要比我见过的着色器更多的数学计算,但我不知道着色器中的数学计算量太多了!

我知道我应该放手一搏看看,但是在这个项目开始之前我已经有点时间了,而且我现在正在研究这个问题!

更新

就像更新一样,我最近发现着色器有一个指令限制,因此一个要求是我能够在指令限制内完成所有页面转动数学运算。

1 个答案:

答案 0 :(得分:2)

我在OpenGL ES 2.0顶点着色器中实现了页面卷曲效果,我将与您共享此代码。它使用纹理坐标来控制页面的旋转角度。这样,旋转不受场景中三角形网格的位置的影响,只有顶点在卷曲页面上的距离。这很好用,但我最终放弃了这种方法,以实现更简单的实现,其中卷曲是伪造的,只有几个三角形在页面上呈现平面并使用纹理来伪造一些阴影效果。两种方式完成后,我怀疑可能所有的页面卷曲效果都是假的,因为实现和调试起来要简单得多。

uniform mat4 transform_matrix;
uniform highp float radius;
uniform mediump vec2 axis;
uniform mediump vec2 axis_origin;
uniform highp float tex_size;

attribute vec2 texCoord;

varying vec2 texCoordVarying;
varying float shadeVarying;

mat4 rotationxy(float angle, vec2 axis);
mat4 translationThenRotationZ(float x, float y, float z, float angle);

void main()
{
    vec3 axisOrigin = vec3(axis_origin, radius);
    vec2 offsetTexCoord = texCoord - axis_origin;
    float angle = dot(offsetTexCoord, vec2(axis.y, -axis.x)) / radius;

    vec4 coord;
    vec4 myNormal = vec4(0.0, 0.0, 1.0, 1.0);

    if (angle <= 0.0) {                        // Flat section before curl
        coord = vec4(texCoord, 0.0, 1.0);
    } else {
        vec2 proj = dot(offsetTexCoord , axis) * (axis);
        const float PI = 3.14159265358979323846264;

        if (angle >= PI) {                    // Flat section after curl
            float axisAngle = asin(axis.x);
            proj += axis_origin;
            mat4 tr = translationThenRotationZ(proj.x, proj.y, 0.0, axisAngle);
            coord = vec4((PI - angle) * radius, 0.0, (radius + radius), 1.0);
            coord = tr * coord;

            myNormal.z = -1.0;
        } else {                            // Curl
            mat4 r = rotationxy(angle, axis);

            myNormal = r * myNormal;

            coord = vec4(proj, -axisOrigin.z, 1.0);
            r[3][0] = axisOrigin.x;
            r[3][1] = axisOrigin.y;
            r[3][2] = axisOrigin.z;
            coord = r * coord;
        }
    }
    gl_Position = transform_matrix * coord;

    shadeVarying = 0.25 + abs(myNormal.z) * 0.75;
    texCoordVarying = texCoord / tex_size;
}

mat4 rotationxy(float angle, vec2 axis)
{
    float x = axis.x;
    float y = axis.y;

    float xSqd = x * x;
    float ySqd = y * y;

    float xy = x * y;

    float cosAngle = cos(angle);
    float sinAngle = sin(angle);

    float xsinAngle = x * sinAngle;
    float ysinAngle = y * sinAngle;

    float oneMinusCos = 1.0 - cosAngle;

    float xyOneMinusCos = xy * oneMinusCos;

    mat4 target;
    target[0][0] = xSqd + (1.0 - xSqd)*cosAngle;
    target[0][1] = xyOneMinusCos;
    target[0][2] = ysinAngle;
    target[0][3] = 0.0;

    target[1][0] = xyOneMinusCos;
    target[1][1] = ySqd + (1.0 - ySqd)*cosAngle;
    target[1][2] = - xsinAngle;
    target[1][3] = 0.0;

    target[2][0] = - ysinAngle;
    target[2][1] = xsinAngle;
    target[2][2] = cosAngle;
    target[2][3] = 0.0;

    target[3][0] = 0.0;
    target[3][1] = 0.0;
    target[3][2] = 0.0;
    target[3][3] = 1.0;

    return target;
}

mat4 translationThenRotationZ(float x, float y, float z, float angle)
{
    float cosAngle = cos(angle);
    float sinAngle = sin(angle);

    mat4 target;
    target[0][0] = cosAngle;
    target[0][1] = -sinAngle;
    target[0][2] = 0.0;
    target[0][3] = 0.0;

    target[1][0] = sinAngle;
    target[1][1] = cosAngle;
    target[1][2] = 0.0;
    target[1][3] = 0.0;

    target[2][0] = 0.0;
    target[2][1] = 0.0;
    target[2][2] = 1.0;
    target[2][3] = 0.0;

    target[3][0] = x;
    target[3][1] = y;
    target[3][2] = z;
    target[3][3] = 1.0;

    return target;
}