使用 glRotatef 旋转会导致翘曲

Posted

技术标签:

【中文标题】使用 glRotatef 旋转会导致翘曲【英文标题】:Rotating with glRotatef causes warping 【发布时间】:2016-11-03 11:19:44 【问题描述】:

我正在尝试将玩家的图像旋转到他们指向的位置。从技术上讲,这很好用。将图像变换到中心后沿Z轴旋转,然后再变换回来,没问题。

但是,当它被渲染时,当角度指向窗口的较宽部分时,图像会被挤压,就好像它试图按比例对图像进行归一化一样。如果我将分辨率设置为正方形(1080x1080、1440x1440 等),那么它可以正常工作,但任何不是正方形的矩形分辨率都会使其播放器图像变形。

我最初在尝试让环境围绕播放器的 x/y 坐标旋转时遇到了同样的问题,但是通过将 glViewport 设置为正方形来解决这个问题。

glViewport(0,0,width,width);

Warped when rotated 90 degrees

Normal when not rotated.

这些效果分别镜像 270 度和 180 度,并在所有其他角度逐渐相互转换。

Player.render() 的代码

glPushMatrix();
    glTranslatef(
        x/Main.width*2,
        y/Main.height*2,
        0);
    glRotatef((float)angle,0f,0f,1f);
    glTranslatef(
        -x/Main.width*2,
        -y/Main.height*2,
        0);
    drawTexture(t,x-w/2,y-w/2,w,w); //t = texture, w = width in pixels for texture to be mapped to
glPopMatrix();

还有drawTexture方法:

public static void drawTexture(Texture in,float x, float y,float w, float h) 
    //Main.width and Main.height are the window window width and height.
    float nx = x*2/Main.width;
    float ny = y*2/Main.height;
    float nw = w*2/Main.width;
    float nh = h*2/Main.height;

    in.bind(0); 

    glTexEnvf(GL_TEXTURE_2D,GL_TEXTURE_ENV_MODE,GL_MODULATE);
    glDepthMask(false);
    glEnable(GL_BLEND);

    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glColor4f(1.0f,1.0f,1.0f,1.0f);

    glBegin(GL_QUADS);
        glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
        glTexCoord2f(0, 1);
        glVertex2f(nx,ny);
        glTexCoord2f(1, 1);
        glVertex2f(nx+nw,ny);
        glTexCoord2f(1, 0);
        glVertex2f(nx+nw,ny+nh);
        glTexCoord2f(0, 0);
        glVertex2f(nx,ny+nh);
    glEnd();


    glDisable(GL_BLEND);
    glDepthMask(true);   


不完全确定去哪里尝试解决这个问题,我自己对其他显然没有这个问题的人的研究只是导致了脱发。如果需要更多代码或更多图片,请相信我,我会竭诚为您提供帮助。

【问题讨论】:

【参考方案1】:

在一个可爱的早上 5:30,我想通了。

修复了播放器渲染的代码

    glPushMatrix();
        glTranslatef(
                x/Main.width*2,
                y/Main.height*2,
                0);
        glScalef(1f,(float)Main.width/Main.height,1f);
        glRotatef((float)angle,0f,0f,1f);
        glScalef(1f,(float)Main.height/Main.width,1f);
        glTranslatef(
                -x/Main.width*2,
                -y/Main.height*2,
                0);
        drawTexture(t,x-w/2,y-w/2,w,w);
    glPopMatrix();

(注意围绕旋转添加的缩放函数)。 必须添加这些,因为我在每一帧的开头添加了另一个缩放功能,它可以缩放所有内容以在所有分辨率下看起来都正常:

        glScalef(1f,(float)Main.height/Main.width,1f);

因为否则它会将 300 像素的宽度视为 169 像素的高度,由于 LWJGL 采用比例浮点参数的方式(在两个方向上为 -1f 到 +1f,这个缩放函数将其更改为 -1f 到 +1f高度,宽度为 -1.78f 到 +1.78f,宽高比为 16:9。这使得纹理贴图在旋转时变得很奇怪,所以如果我按相反的比例缩放它以使其达到 1:1,旋转,然后按比例缩小以达到比例,那么一切都很好。

希望我的解释是可以理解的。 第一次玩这个,所以生活和学习。

【讨论】:

【参考方案2】:

我相信你调用 drawTexture 以高度为宽度。

【讨论】:

drawTexture(t,x-w/2,y-w/2,w,w);这是你的代码。最后一个参数是高度,但似乎是宽度。 不知道 w 是什么,但发现它很奇怪,因为您的算法适用于正方形分辨率,并且您传递的参数与宽度和高度相同。 如果我想任意拉伸纹理以获得视觉效果,或者纹理不是方形的,我会使用它。纹理是正方形的,drawTexture 的宽度和高度只是指定了我希望纹理映射到的矩形。所以我可以拥有相同的纹理,并在飞行中在任一方向上使其变小或变大。 'w' 用于两者,因为我希望矩形在任一方向上都是正方形,并将其设置为宽度和高度的相同变量使其更简单。

以上是关于使用 glRotatef 旋转会导致翘曲的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的矩阵旋转会在 OpenGL 中倒退

API 调用期间的 Android 屏幕旋转会产生 kotlinx.coroutines.JobCancellationException

bitmap图片用matrix旋转会失真,怎么同时旋转而不失真!

四元数旋转导致场景伸展

如何使翘曲导致另一个翘曲处于空闲状态?

基于Three.js中的父/其他对象坐标系保持对象旋转?