我的矩阵数学有点生疏,所以我在找出我需要在这里应用的正确转换过程时遇到了一些麻烦。
我有一个全屏四边形,坐标范围从[-1, 1]
开始。我使用非方形纹理对此四边形进行纹理处理,然后缩放我的模型视图矩阵以调整大小并保留纵横比。我还想旋转调整大小的四边形,但是我得到拉伸/扭曲的结果。
这是我正在经历的过程:
_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中实现的,但该过程应该是通用的。
为简单起见,这一切都是在原点完成的。我很确定我在缩小和旋转之间缺少一些关系,但我不确定它是什么。
如果我希望四边形的大小为_shape.width, _shape.height
并且旋转任意角度,我缺少什么?
谢谢!
答案 0 :(得分:2)
我从来没有使用过webgl,所以我这里没有例子,但你不应该在你的模型视图矩阵中进行宽高比校正。这是投影矩阵的作用。
可以找到有关如何操作的示例here。
答案 1 :(得分:2)
您可以使用投影和模型视图的任意组合。因此,只需简化您的生活:使用一些保留窗口纵横比的投影,以便模型视图坐标不会各向异性扭曲。然后将纹理绘制到具有相同边缘比的四边形上。
这是在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);
}
}