graphics - 正确的缩放和旋转转换设置

标签 graphics opengl-es matrix webgl

我的矩阵数学有点生疏,所以我在弄清楚我需要在这里应用的正确转换过程时遇到了一些麻烦。

我有一个全屏四边形,其两个方向的坐标范围为 [-1, 1]。我使用非方形纹理对这个四边形进行纹理化,然后缩放模型 View 矩阵以调整大小并保留纵横比。我还想旋转调整大小的四边形,但我得到了拉伸(stretch)/扭曲的结果。

这是我正在经历的过程:

_gl.viewport(0, 0, _gl.viewportWidth, _gl.viewportHeight); // full-screen viewport
mat4.rotate(_modelview_matrix, degToRad(-1.0 * _desired_rotation), [0, 0, 1]); // rotate around z
mat4.scale(_modelview_matrix, [_shape.width / _gl.viewportWidth, _shape.height / _gl.viewportHeight, 1]); // scale down

请注意,这是在 WebGL 中实现的,但该过程应该是通用的。

为了简单起见,这一切都是在源头完成的。我很确定我错过了缩小和旋转之间的一些关系,但我不确定它是什么。

Rotation distortion

如果我希望四边形的大小为 _shape.width, _shape.height 并旋转任意角度,我缺少什么?

谢谢!

最佳答案

您可以使用投影和模型 View 的任意组合。因此,让您的生活变得轻松:使用一些保留窗口纵横比的投影,以便模型 View 坐标不会出现各向异性扭曲。然后只需将纹理绘制到具有相同边缘比例的四边形上即可。

这是用 C 编写的,但这个概念应该很容易转移。

typedef struct Projection {
    enum{perspective, ortho} type;
    union {
        GLfloat fov;
        GLfloat size;
    };
    GLfloat near;
    GLfloat far;
} Projection;

Projection projection;

GLuint tex_width;
GLuint tex_height;

GLuint viewport_width;
GLuint viewport_height;

/*...*/

void display()
{
    GLfloat viewport_aspect;

    if(!viewport_width || !viewport_height)
        return;

    viewport_aspect = (float)viewport_width/(float)viewport_height;

    glViewport(0, 0, viewport_width, viewport_height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    switch(projection.type) {
    case ortho: {
            glOrtho(-0.5 * viewport_aspect * projection.size, 
                     0.5 * viewport_aspect * projection.size, 
                    -0.5 * projection.size,
                     0.5 * projection.size,
                    -projection.near,
                     projection.far );
        }
    case perspective: {
            glFrustum( -0.5 * viewport_aspect * projection.near * projection.fov, 
                        0.5 * viewport_aspect * projection.near * projection.fov, 
                       -0.5 * projection.near * projection.fov,
                        0.5 * projection.near * projection.fov,
                       -projection.near,
                        projection.far );
        }
    default:
        return;
    }

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    {
        GLfloat const T = 0.5*(float)texture_width/(float)texture_height;

        GLfloat quad[4][4] = {
           /* X     Y,   U,     V */
            {-T, -0.5,  0.0,  0.0},
            { T, -0.5,  1.0,  0.0},
            { T,  0.5,  1.0,  1.0},
            {-T,  0.5,  0.0,  1.0},
        }

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(2, GL_FLOAT, (char*)&quad[6]-(char*)&quad[2], &quad[2]);
        glTexCoordPointer(2, GL_FLOAT, (char*)&quad[6]-(char*)&quad[2], &quad[2]);

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, texture_ID);

        glDrawArrays(GL_QUADS, 0, 4);
    }
}

关于graphics - 正确的缩放和旋转转换设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5528736/

相关文章:

matrix - 使用 glm::perspective 关于 zFar 和 zNear 平面偏移的混淆

opengl-es - OpenGL ES 2 : Uniforms and attributes

python - 如何计算邻接矩阵csv的短路径测地距离[python]?

java - 使汽车(JPanel)在 Swing 中以平滑的曲线转弯

python - numpy 数组的 np.max(x ,axis = 1) 和 x.max(axis = 1) 之间的差异

android - 在Android的OpenGL ES中运行时创建大型纹理的最有效方法

Java,为面板创建和编辑图形对象?

java - 如何在java中使用两个paint方法?或者在基本的油漆方法之外

ios - 向 VBO 提供数据

ios - 用 Metal 渲染四边形性能