简体   繁体   English

Skybox旋转与世界不同步

[英]Skybox rotates out of sync with world

I've got a small scene with a loaded mesh, a ground plane and a skybox. 我有一个很小的场景,上面有一个已加载的网格,一个地平面和一个天空盒。 I am generating a cube, and using the vertex positions as the cubemap texture co-ordinates. 我正在生成一个多维数据集,并将顶点位置用作多维数据集贴图纹理坐标。

Horizontal rotation (about the y-axis) works perfectly and the world movement is aligned with the skybox. 水平旋转(绕y轴)可以完美工作,并且世界运动与天空盒对齐。 Vertical rotation (about the camera's x-axis) doesn't seem to match up with the movement of the other objects, except that the strange thing is that when the camera is looking at the center of a cube face, everything seems aligned. 垂直旋转(绕相机的x轴)似乎与其他对象的移动不匹配,除了奇怪的是,当相机看着立方体面的中心时,所有东西似乎都对齐了。 In other words, the movement is non-linear and I'll try my best to illustrate the effect with some images: 换句话说,运动是非线性的,我将尽力通过一些图像来说明这种效果:

First, the horizontal movement which as far as I can tell is correct: 首先,据我所知,水平运动是正确的:

Facing forward: 面向未来: 面向未来

Facing left at almost 45Deg: 面对将近45度 面对将近45Deg

Facing left at 90Deg: 面对90Deg: 面对90Deg

And now the vertical movement which seems to have some discrepancy in movement: 现在,垂直运动似乎在运动方面有些差异:

Facing forward again: 再次面对: 再次面对

Notice the position of the ground plane in relation to the skybox in this image. 注意此图像中地平面相对于天空盒的位置。 I rotated slightly left to make it more apparent that the Sun is being obscured when it shouldn't. 我稍微向左旋转,以使太阳在不应该被遮挡的时候更加明显。

Facing slightly down: 面朝下: 面朝下

Finally, a view straight up to show the view is correctly centered on the (skybox) cube face. 最后,直接显示视图的视图正确地位于(skybox)多维数据集面上。

Facing straight up: 面朝上: 面朝上

Here's my drawing code, with the ground plane and mesh drawing omitted for brevity. 这是我的绘图代码,为简洁起见,省略了地平面和网格图。 (Note that the cube in the center is a loaded mesh, and isn't generated by the same function for the skybox). (请注意,位于中心的多维数据集是一个已加载的网格,不是由天空盒的同一函数生成的)。

void MeshWidget::draw() {

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glPushMatrix();

    glRotatef(-rot_[MOVE_CAMERA][1], 0.0f, 1.0f, 0.0f);
    glRotatef(-rot_[MOVE_CAMERA][0], 1.0f, 0.0f, 0.0f);
    glRotatef(-rot_[MOVE_CAMERA][2], 0.0f, 0.0f, 1.0f);

    glDisable(GL_DEPTH_TEST);
    glUseProgramObjectARB(shader_prog_ids_[2]);
    glBindBuffer(GL_ARRAY_BUFFER, SkyBoxVBOID);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, sizeof(Vec3), BUFFER_OFFSET(0));

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, SkyIndexVBOID);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
    glUseProgramObjectARB(shader_prog_ids_[0]);
    glEnable(GL_DEPTH_TEST);

    glPopMatrix();

    glTranslatef(0.0f, 0.0f, -4.0f + zoom_factor_);

    glRotatef(rot_[MOVE_CAMERA][0], 1.0f, 0.0f, 0.0f);
    glRotatef(rot_[MOVE_CAMERA][1], 0.0f, 1.0f, 0.0f);
    glRotatef(rot_[MOVE_CAMERA][2], 0.0f, 0.0f, 1.0f);

    glPushMatrix();

    // Transform light to be relative to world, not camera.
    glRotatef(rot_[MOVE_LIGHT][1], 0.0f, 1.0f, 0.0f);
    glRotatef(rot_[MOVE_LIGHT][0], 1.0f, 0.0f, 0.0f);
    glRotatef(rot_[MOVE_LIGHT][2], 0.0f, 0.0f, 1.0f);

    float lightpos[] = {10.0f, 0.0f, 0.0f, 1.0f};
    glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

    glPopMatrix();

    if (show_ground_) {

        // Draw ground...
    }

    glPushMatrix();

    // Transform and draw mesh...

    glPopMatrix();
}

And finally, here's the GLSL code for the skybox, which generates the texture co-ordinates: 最后,这是天空盒的GLSL代码,该代码生成纹理坐标:

Vertex shader: 顶点着色器:

void main()
{
    vec4 vVertex = vec4(gl_ModelViewMatrix * gl_Vertex);

    gl_TexCoord[0].xyz = normalize(vVertex).xyz;
    gl_TexCoord[0].w = 1.0;

    gl_TexCoord[0].x = -gl_TexCoord[0].x;

    gl_Position = gl_Vertex;
}

Fragment shader: 片段着色器:

uniform samplerCube cubeMap;

void main()
{
    gl_FragColor = texture(cubeMap, gl_TexCoord[0]);
}

I'd also like to know if using quaternions for all camera and object rotations would help. 我还想知道,使用四元数进行所有相机和对象旋转是否会有所帮助。

If you need any more information (or images), please ask! 如果您需要更多信息(或图像),请询问!

I think you should be generating your skybox texture lookup based on a worldspace vector (gl_Vertex?) not a view space vector (vVertex). 我认为您应该基于世界空间矢量(gl_Vertex?)而不是视图空间矢量(vVertex)来生成天空盒纹理查找。

I'm assuming your skybox coordinates are already defined in worldspace as I don't see a model matrix transform before drawing it (only the camera rotations). 我假设您的天空盒坐标已经在世界空间中定义,因为在绘制它之前,我看不到模型矩阵的变换(仅摄像机旋转)。 In that case, you should be sampling the skybox texture based on the worldspace position of a vertex, it doesn't need to be transformed by the camera. 在这种情况下,您应该根据顶点的世界空间位置对天空盒纹理进行采样,而不必通过摄影机对其进行转换。 You're already translating the vertex by the camera, you shouldn't need to translate the lookup vector as well. 您已经通过摄影机平移了顶点,也不需要平移查找向量。

Try replacing normalize(vVertex) with normalize(gl_Vertex) and see if that improves things. 尝试更换normalize(vVertex)normalize(gl_Vertex)看看是否能提高的东西。

Also I might get rid of the x = -x thing, I suspect that was put in to compensate for the fact that the texture was rotating in the wrong direction originally? 另外,我可能会摆脱x = -x的问题,我怀疑是为了补偿纹理最初沿错误方向旋转的事实而投入的?

I'd also like to know if using quaternions for all camera and object rotations would help. 我还想知道,使用四元数进行所有相机和对象旋转是否会有所帮助。

Help how? 帮助如何? It doesn't offer any new functionality over using matrices. 它不提供使用矩阵的任何新功能。 I've heard arguments both ways as to whether matrixes or quaternions have better performance, but I see no need to use them. 我听说过关于矩阵或四元数是否具有更好性能的两种争论,但我认为没有必要使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM