Skybox与世界不同步

时间:2012-05-31 04:54:20

标签: c++ opengl glsl

我有一个带有加载网格,地平面和天空盒的小场景。我正在生成一个立方体,并使用顶点位置作为立方体贴图纹理坐标。

水平旋转(绕y轴)完美运行,世界运动与天空盒对齐。垂直旋转(关于相机的x轴)似乎与其他物体的运动不匹配,除了奇怪的是当相机看着立方体脸的中心时一切似乎都是一致的。换句话说,这个动作是非线性的,我会尽力用一些图像说明效果:

首先,据我所知,横向移动是正确的:

面向前方:Facing forward

面向左边近45Deg: Facing left at almost 45Deg

面向90Deg左侧: Facing left at 90Deg

现在垂直运动似乎在运动中存在一些差异:

再次面向前方: Facing forward again

注意此图像中地平面相对于天空盒的位置。我向左稍微旋转,以便更明显地表明太阳在它不应该被遮挡的时候被遮挡。

面临轻微下降: Facing slightly down

最后,直接显示视图的视图正确地居中于(天空盒)立方体面上。

直面: Facing straight up

这是我的绘图代码,为简洁省略了地平面和网格绘图。 (请注意,中心的立方体是一个加载的网格,并且不是由天空盒的相同函数生成的。)

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();
}

最后,这里是天空盒的GLSL代码,它生成纹理坐标:

顶点着色器:

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;
}

片段着色器:

uniform samplerCube cubeMap;

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

我还想知道使用四元数来进行所有相机和物体旋转都会有所帮助。

如果您需要更多信息(或图片),请询问!

1 个答案:

答案 0 :(得分:0)

我认为您应该根据世界空间矢量(gl_Vertex?)而不是视图空间矢量(vVertex)生成天空盒纹理查找。

我假设您的天空盒坐标已经在世界空间中定义,因为在绘制它之前我没有看到模型矩阵变换(只有相机旋转)。在这种情况下,您应该根据顶点的世界空间位置对天空盒纹理进行采样,它不需要由相机进行变换。您已经通过相机翻译顶点,您也不需要翻译查找向量。

尝试将normalize(vVertex)替换为normalize(gl_Vertex)并查看是否可以改善效果。

此外,我可能会摆脱x = -x的东西,我怀疑这是为了弥补纹理最初在错误的方向旋转的事实?

  

我还想知道对所有相机和物体旋转使用四元数是否有帮助。

帮忙怎么样?它不提供使用矩阵的任何新功能。我已经听过关于矩阵或四元数是否具有更好性能的论证,但我认为没有必要使用它们。