【问题标题】:opengl object vibrate after moving a distance移动距离后opengl对象振动
【发布时间】:2018-03-15 22:19:45
【问题描述】:

我有一个物体在地形上移动,第三人称相机跟随它,当我在不同方向移动它一段距离后,即使它没有移动并且相机围绕它旋转,它也会开始摇晃或振动,这是物体的移动代码

double& delta = engine.getDeltaTime();
GLfloat velocity = delta * movementSpeed;
glm::vec3 t(glm::vec3(0, 0, 1) * (velocity * 3.0f));
//translate the objet atri before rendering
matrix = glm::translate(matrix, t);
//get the forward vetor of the matrix
glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]);
f = glm::normalize(f);
f = f * (velocity * 3.0f);
f = -f;
camera.translate(f);

并且相机旋转是

void Camera::rotate(GLfloat xoffset, GLfloat yoffset, glm::vec3& c, double& delta, GLboolean constrainpitch) {
    xoffset *= (delta * this->rotSpeed);
    yoffset *= (delta * this->rotSpeed);
    pitch += yoffset;
    yaw += xoffset;
    if (constrainpitch) {
        if (pitch >= maxPitch) {
            pitch = maxPitch;
            yoffset = 0;
        }
        if (pitch <= minPitch) {
            pitch = minPitch;
            yoffset = 0;
        }
    }
    glm::quat Qx(glm::angleAxis(glm::radians(yoffset), glm::vec3(1.0f, 0.0f, 0.0f)));
    glm::quat Qy(glm::angleAxis(glm::radians(xoffset), glm::vec3(0.0f, 1.0f, 0.0f)));
    glm::mat4 rotX = glm::mat4_cast(Qx);
    glm::mat4 rotY = glm::mat4_cast(Qy);
    view = glm::translate(view, c);
    view = rotX * view;
    view = view * rotY;
    view = glm::translate(view, -c);
}

【问题讨论】:

  • 我添加了更多信息的答案

标签: android c++ opengl-es


【解决方案1】:

对我来说,这听起来像是一种数字效应。即使是来自您的游戏对象的小偏移量也会以小的移动/旋转影响后续相机的旋转,并且它看起来像一个振动的对象/相机。

所以你可以做的是:

  • 在为您的相机计算新的旋转之前检查移动是否高于阈值
  • 当您超过此阈值时:使用四元数的 lerp 算法在新旧旋转之间进行线性插值(请参阅此统一答案以更好地了解您的代码的外观:Unity lerp discussion

【讨论】:

  • 我为相机旋转xoffset = glm::mix(xoffset, nx,(GLfloat) delta);做了一个线性插值,但没有解决问题,物体本身在振动而不是相机,我通过将glm::vec3 t(glm::vec3(0, 0, 1) * (velocity * 3.0f));添加到它的方向向量来移动它如果可以的话,我可以用什么对该平移向量进行线性插值吗?
  • 我猜是从旧位置到新位置。
  • 我将代码更改为以下glm::vec3 opos = getPosition(); glm::vec3 t(glm::vec3(0, 0, 1) * (velocity * 3.0f)); glm::mat4 nmat(matrix); nmat = glm::translate(matrix, t); glm::vec3 npos(nmat[3]); glm::vec3 ipos = glm::mix(npos, opos, (GLfloat) delta); matrix[3] = glm::vec4(ipos, 1.0f); glm::vec3 f(matrix[2][0], matrix[2][1], matrix[2][2]); f = -glm::normalize(f) * (velocity * 3.0f); camera-&gt;translate(f); 我得到了旧位置并将翻译应用于临时矩阵,然后得到位置并使用 glm::mix 进行插值但未解决
  • 问题是着色器精度是中等,当我将它设置为高时隐藏振动,插值效果非常好,谢谢
【解决方案2】:
  1. float 有时还不够。

    我在 CPU 端使用double 精度矩阵来避免此类问题。但由于您使用的是 Android,这可能是不可能的。对于 GPU 再次使用 floats,因为还没有 64 位插值器。

  2. 大数字通常是问题所在

    如果您的世界很大,那么您将大数字传递到方程式中,乘以任何错误,并且只有在最后阶段,这些东西才会相对于相机位置进行转换,这意味着错误会保持成倍增加,但数字会被限制,因此错误/数据比率得到了大。

    要在渲染之前降低此问题,请将所有顶点转换为原点位于或靠近相机的坐标系。您可以忽略旋转只是偏移位置。

    这样你只会在远离相机的地方得到更高的错误,而视角无论如何都不可见......有关更多信息,请参阅:

  3. 使用累积变换矩阵代替欧拉角

    有关更多信息,请参阅Understanding 4x4 homogenous transform matrices 以及该答案底部的所有链接。

【讨论】:

  • 是的,这是大数字问题,但在 GLSL 中使用高精度解决了问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多