OpenGL着色器 - 围绕其原点旋转模型(2D World)

时间:2013-07-22 14:31:56

标签: java opengl rotation vertex-shader

所以我创建了一个顶点着色器,它接受一个角度并计算旋转。虽然模型围绕世界中心而不是自己的轴/原点旋转,但存在一个问题。

旁注:这是2D旋转。

如何让模型通过自己的轴旋转?

这是我当前的顶点着色器:

#version 150 core

in vec4 in_Position;
in vec4 in_Color;
in vec2 in_TextureCoord;

out vec4 pass_Color;
out vec2 pass_TextureCoord;

void main(void) {


    gl_Position = in_Position;

    pass_Color = in_Color;
    pass_TextureCoord = in_TextureCoord;
}

旋转CPU端:

    Vector3f center = new Vector3f(phyxBody.getPosition().x,phyxBody.getPosition().y,0);
    Matrix4f pos = new Matrix4f();
    pos.m00 = (phyxBody.getPosition().x)-(getWidth()/30f/2f);
    pos.m01 = (phyxBody.getPosition().y)+(getHeight()/30f/2f);
    pos.m10 = (phyxBody.getPosition().x)-(getWidth()/30f/2f);
    pos.m11 = (phyxBody.getPosition().y)-(getHeight()/30f/2f);
    pos.m20 = (phyxBody.getPosition().x)+(getWidth()/30f/2f);
    pos.m21 = (phyxBody.getPosition().y)-(getHeight()/30f/2f);
    pos.m30 = (phyxBody.getPosition().x)+(getWidth()/30f/2f);
    pos.m31 = (phyxBody.getPosition().y)+(getHeight()/30f/2f);

    pos.rotate(phyxBody.getAngle(),center);

结果是一个奇怪的旋转对象..你知道为什么吗?不要担心/ 30f部分。

  • phyxBody是JBox2D库中Body类的一个实例。 phyxBody.getAngle()在raidians中。
  • Matrix4f是LWJGL库中的一个类。

编辑:

    Vector3f center = new Vector3f(0,0,0);
    Matrix4f pos = new Matrix4f();
    pos.m00 = -(getWidth()/30f/2f);
    pos.m01 = +(getHeight()/30f/2f);
    pos.m10 = -(getWidth()/30f/2f);
    pos.m11 = -(getHeight()/30f/2f);
    pos.m20 = +(getWidth()/30f/2f);
    pos.m21 = -(getHeight()/30f/2f);
    pos.m30 = +(getWidth()/30f/2f);
    pos.m31 = +(getHeight()/30f/2f);

    pos.rotate(phyxBody.getAngle(),center);

    pos.m00 += phyxBody.getPosition().x;
    pos.m01 += phyxBody.getPosition().y;
    pos.m10 += phyxBody.getPosition().x;
    pos.m11 += phyxBody.getPosition().y;
    pos.m20 += phyxBody.getPosition().x;
    pos.m21 += phyxBody.getPosition().y;
    pos.m30 += phyxBody.getPosition().x;
    pos.m31 += phyxBody.getPosition().y;

这是转换代码,但轮换仍然无法正常工作。

我尝试旋转方法:(我做错了什么?)

    if (phyxBody.getAngle() != 0.0) {
        pos.m00 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
        pos.m01 *= Math.sin(Math.toDegrees(phyxBody.getAngle()));
        pos.m10 *= -Math.sin(Math.toDegrees(phyxBody.getAngle()));
        pos.m11 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
        pos.m20 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
        pos.m21 *= Math.sin(Math.toDegrees(phyxBody.getAngle()));
        pos.m30 *= -Math.sin(Math.toDegrees(phyxBody.getAngle()));
        pos.m31 *= Math.cos(Math.toDegrees(phyxBody.getAngle()));
    }

2 个答案:

答案 0 :(得分:4)

顺序是缩放*旋转*翻译 - 请参阅this question。我猜你已经在你的着色器之外翻译了你的坐标。你必须先旋转,然后翻译。很高兴知道你正在做的事情背后的线性代数,所以你知道为什么事情有效或无效。

执行此操作的典型方法是传递已经处理缩放/旋转/平移的预先计算的ModelView矩阵。如果您已经已经翻译了您的顶点,则无法在不必要地撤消它并在之后重做它的情况下修复着色器中的问题。在您的顶点中发送未翻译的数据,并将数据(如角度)与它们一起进行翻译。 您可以事先翻译和旋转。这取决于你想做什么。

底线:您必须在翻译之前轮换。

以下是进行顶点变换的典型方法:

OpenGL方面:

  1. 计算ModelView矩阵:缩放*旋转*翻译

  2. 作为统一矩阵传递到着色器

  3. GLSL方面:

    1. 通过顶点着色器中的ModelView矩阵乘以顶点

    2. 发送至gl_Position

    3. 对编辑的回应:

      我倾向于认为您的实施需要完全重做。您有属于模型的点。这些点都是围绕原点定向的。例如,如果你有一辆汽车,这些点会形成一个三角形网格。

      • 如果您只是不翻译这些点然后旋转它们,汽车将围绕其中心旋转。如果您之后翻译,汽车将以旋转的方式转换到您指定的位置。这里的关键是模型的原点与旋转原点对齐,因此您最终会围绕自身旋转模型。

      • 如果您改为转换到新位置并然后旋转,您的模型将旋转,就像它绕原点旋转一样。这可能不是你想要的。

      • 如果您直接修改实际顶点位置而不是使用转换矩阵,那么您做错了。即使您只有一个正方形,也将坐标保留在(-1,-1)( - 1,1)(1,1)(1,-1)(注意中心位于(0,0)处)并且将它们翻译成你想要的地方。

      • 您不必重新实现数学功能,也可能不应该(除非您的目标是明确地这样做)。 GLM是一个流行的数学库,可以完成您想要的一切,并且专门为OpenGL量身定制。

      最终修改

      这是一件精美的艺术作品,我为你展示了你需要做的事情。enter image description here

      • 请注意,右下角的模型是如何围绕 world 原点扫描出来的,大约45度。如果我们再去45,它的底边平行于X轴,并且正Y轴与左下角的蓝色顶点和右下角的紫色顶点相交。

      • 您应该查看如何使用顶点,矩阵和着色器。顶点应指定一次,每次有可能更新对象的比例,旋转或位置时,矩阵应更新,并且着色器应将模型中的每个顶点乘以均匀(常量)。 / p>

答案 1 :(得分:2)

你的精灵缺乏足够的信息,无法做你想做的事情。为了计算关于点的旋转,你需要知道那个点是什么。你没有。

因此,如果要围绕任意位置进行旋转,则需要将该位置传递到着色器。在那里,你从你的位置减去它,旋转位置,并将其重新添加。但是,这需要大量的工作,这就是为什么你应该只计算CPU上的矩阵来完成所有这些。您的着色器将被赋予此矩阵并自行执行变换。

当然,这本身需要其他东西,因为你通过偏移CPU上的顶点来不断更新这些对象的位置。这不好;你应该保持这些对象相对于它们在缓冲区中的来源。然后,您应该将它们转换为世界位置,作为矩阵的一部分。

因此,您的着色器应该采用对象相对坐标,并且应该传递一个矩阵,该矩阵执行旋转,然后转换到它们的世界空间位置。实际上,划伤;矩阵应该转换到最终的相机空间位置(世界空间总是一个坏主意)。