OpenGL旋转2D纹理

5

更新

请查看底部的更新。


我在互联网上搜索了很多,找到了一些教程来解释我想要实现的内容,但是我无法让它工作,可能是教程不完整或者不适用于我的代码。

我试图做的事情很简单,就是围绕原点(中心)旋转一个2D图像。

我使用xStart、xEnd、yStart和yEnd来翻转纹理,它们都是0或1。

这就是代码的样子

GameRectangle dest = destination;
Vector2 position = dest.getPosition();

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, this->image);

//If the rotation isn't 0 we'll rotate it
if (rotation != 0)
{
    glMatrixMode(GL_TEXTURE);

    glLoadIdentity();
    glTranslatef(0.5, 0.5, 0);
    glRotatef(rotation, 0, 0, 1);

    glMatrixMode(GL_PROJECTION);
}

glBegin(GL_QUADS);
glTexCoord2d(xStart,yStart);
glVertex2f(position.x, position.y);

glTexCoord2d(xEnd,yStart);
glVertex2f(position.x + this->bounds.getWidth(), position.y);

glTexCoord2d(xEnd,yEnd); 
glVertex2f(position.x + this->bounds.getWidth(), position.y + this->bounds.getHeight());

glTexCoord2d(xStart,yEnd);
glVertex2f(position.x, position.y + this->bounds.getHeight());

glEnd();

glDisable(GL_TEXTURE_2D);

//Reset the rotation so next object won't be rotated
glMatrixMode(GL_TEXTURE);

glLoadIdentity();
glRotatef(0, 0, 0, 1);

glMatrixMode(GL_PROJECTION);

这段代码将以原始大小绘制图像并旋转它,但它将从左上角旋转,这会大量裁剪图像。通过调用GameRectangle.getOrigin(),我可以轻松地获取矩形的中心点,但我不知道在哪里使用它。
如果放置位:
 glTranslatef(-0.5, -0.5, 0);

当我调用:

 glRotatef(0.5, 0.5, 0);

它将从中心旋转,但如果它不是完美的90度旋转,它将拉伸图像。

更新


经过尝试几乎所有可能的方法,我得到了我想要的结果。

但我不确定这是否是最佳方法。如果我的代码有问题,请告诉我。

如我在上面的评论中提到的,我多次使用同一张图片,并使用不同的值进行绘制,因此我不能保存任何内容到实际图片中。所以每次渲染后我必须重置这些值。

我将我的代码更改为:

//Store the position temporary
GameRectangle dest = destination;
Vector2 position = dest.getPosition();

glEnable(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, this->image);

glTranslatef(dest.getOrigin().x, dest.getOrigin().y, 0);
glRotatef(rotation, 0, 0, 1);

glBegin(GL_QUADS);
glTexCoord2d(xStart,yStart);
glVertex2f(-dest.getWidth()/2, -dest.getHeight()/2);

glTexCoord2d(xEnd,yStart);
glVertex2f(dest.getWidth()/2, -dest.getHeight()/2);

glTexCoord2d(xEnd,yEnd); 
glVertex2f(dest.getWidth()/2, dest.getHeight()/2);

glTexCoord2d(xStart,yEnd);
glVertex2f(-dest.getWidth()/2, dest.getHeight()/2);

glEnd();

//Reset the rotation and translation
glRotatef(-rotation,0,0,1);
glTranslatef(-dest.getOrigin().x, -dest.getOrigin().y, 0);

glDisable(GL_TEXTURE_2D);

这会使纹理与其所绘制的四边形一起旋转,而不会拉伸或裁剪。然而,如果图像填充为正方形,则边缘会有些锯齿状,但我想在没有反锯齿的情况下无法避免这种情况。


4
你真的想旋转纹理而不是四边形吗?无论如何,如果你已经在使用OpenGL矩阵,你应该使用矩阵堆栈,即glPushMatrix和glPopMatrix,而不是在代码结尾重置矩阵。 - Alex P.
如果只是旋转四边形就足够了,我想那就是你想要的。 那么纹理会随着四边形一起旋转吗?如何正确地旋转四边形? - Orujimaru
另外,我不确定在哪里调用glPushMatrix()和glPopMatrix(),无论我把它们放在哪里,都不能得到期望的结果,要么旋转所有图像,要么没有图像旋转。我不知道这是否有任何区别,但我多次绘制相同的图像,但使用不同的旋转值等,因此我无法保存任何内容到实际图像。 - Orujimaru
我的“引擎”看起来很像XNA框架,我调用renderer.begin(),它执行以下操作:glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix();glOrtho(0, frameWidth, frameHeight, 0, -1, 1);然后是renderer.end()它执行以下操作:glPopMatrix(); SDL_GL_SwapBuffers();在这两者之间,我绘制每个单独的对象。所以我使用glPopMatrix和PushMatrix(),但不完全像你建议的那样。抱歉,我不知道glTexEnv的任何信息,但我尝试了glEnable(GL_POLYGON_SMOOTH),它修复了锯齿状的边缘,但是会在我的四边形中绘制一条白色/透明的对角线。 :S - Orujimaru
实际上我是指glTexParameter,这样你就可以启用Mip-Mapping或至少线性过滤。如果在glTranslatef之前的更新代码中进行glPushMatrix,然后在glEnd之后进行glPopMatrix,那么您就不需要“撤消”旋转,从而节省了几个不必要的浮点运算。现在可能还不是问题,但很快就会变成一个问题:D - Alex P.
显示剩余2条评论
1个回答

1
你想要的是这个:
glPushMatrix(); //Save the current matrix.
//Change the current matrix.
glTranslatef(dest.getOrigin().x, dest.getOrigin().y, 0);
glRotatef(rotation, 0, 0, 1);

glBegin(GL_QUADS);
glTexCoord2d(xStart,yStart);
glVertex2f(-dest.getWidth()/2, -dest.getHeight()/2);

glTexCoord2d(xEnd,yStart);
glVertex2f(dest.getWidth()/2, -dest.getHeight()/2);

glTexCoord2d(xEnd,yEnd); 
glVertex2f(dest.getWidth()/2, dest.getHeight()/2);

glTexCoord2d(xStart,yEnd);
glVertex2f(-dest.getWidth()/2, dest.getHeight()/2);

glEnd();

//Reset the current matrix to the one that was saved.
glPopMatrix();

1
你是否碰巧知道在OpenGL ES 2.0中如何完成这个任务? - peedee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接