OpenGL:天空盒放大太多

Posted

技术标签:

【中文标题】OpenGL:天空盒放大太多【英文标题】:OpenGL: Skybox magnified too much 【发布时间】:2015-01-24 17:53:35 【问题描述】:

我正在尝试在游戏中实现天空盒。我使用的图片是:

不幸的是,它被极度放大,只显示了纹理的几个像素。它看起来像这样:

这是我创建天空盒的代码:

SkyBox::SkyBox()


    programID = LoadShaders("Resources/Shaders/skybox.vert", "Resources/Shaders/skybox.frag");

    pID = glGetUniformLocation(programID, "P");
    vID = glGetUniformLocation(programID, "V");

    float points[] =
    
        -1.0f,  1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,

        -1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f, -1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,

        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,

        -1.0f, -1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f, -1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,

        -1.0f,  1.0f, -1.0f,
        1.0f,  1.0f, -1.0f,
        1.0f,  1.0f,  1.0f,
        1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f,  1.0f,
        -1.0f,  1.0f, -1.0f,

        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f,  1.0f,
        1.0f, -1.0f,  1.0f
    ;
    glGenBuffers (1, &vbo);
    glBindBuffer (GL_ARRAY_BUFFER, vbo);
    glBufferData (GL_ARRAY_BUFFER, sizeof (points), points, GL_STATIC_DRAW);

    const char *pth = "/Users/uonibr/Documents/Programming/Space Shooter/Space Shooter/Space Shooter/Resources/space.jpg";

    createCubeMap(pth, pth, pth, pth, pth, pth);



bool load_cube_map_side (GLuint texture, GLenum side_target, const char* file_name)

    glBindTexture (GL_TEXTURE_CUBE_MAP, texture);

    int x, y;
    unsigned char*  image_data = SOIL_load_image(file_name, &x, &y, 0, SOIL_LOAD_RGBA);
    if (!image_data) 
        fprintf (stderr, "ERROR: could not load %s\n", file_name);
        return false;
    
    // non-power-of-2 dimensions check
    if ((x & (x - 1)) != 0 || (y & (y - 1)) != 0) 
        fprintf (
                 stderr, "WARNING: image %s is not power-of-2 dimensions\n", file_name
                 );
    

    // copy image data into 'target' side of cube map
    glTexImage2D (
                  side_target,
                  0,
                  GL_RGBA,
                  x,
                  y,
                  0,
                  GL_RGBA,
                  GL_UNSIGNED_BYTE,
                  image_data
                  );
    free (image_data);
    return true;



void SkyBox::createCubeMap ( const char* front, const char* back, const char* top, const char* bottom, const char* left,const char* right)

    // generate a cube-map texture to hold all the sides
    glActiveTexture (GL_TEXTURE0);
    glGenTextures (1, &cubeMap);

    // load each image and copy into a side of the cube-map texture
    assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, front));
    assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, back));
    assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, top));
    assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, bottom));
    assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, left));
    assert(load_cube_map_side (cubeMap, GL_TEXTURE_CUBE_MAP_POSITIVE_X, right));

    // format cube map texture
    glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
    glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

这是天空盒的渲染代码:

void SkyBox::render(const Camera &camera) const

    glDepthMask (GL_FALSE);
    glUseProgram (programID);
    glActiveTexture (GL_TEXTURE0);
    glBindTexture (GL_TEXTURE_CUBE_MAP, cubeMap);
    glUniformMatrix4fv(pID, 1, GL_FALSE, &camera.getProjectionMatrix()[0][0]);
    glm::mat4 view = camera.getRotationMatrix();
    glUniformMatrix4fv(vID, 1, GL_FALSE, &view[0][0]);
    glEnableVertexAttribArray (0);
    // 1st attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(
                          0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
                          3,                  // size
                          GL_FLOAT,           // type
                          GL_FALSE,           // normalized?
                          0,                  // stride
                          (void*)0            // array buffer offset
                          );

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glDrawArrays (GL_TRIANGLES, 0, 36);

    glDisableVertexAttribArray(0);
    glDepthMask (GL_TRUE);
    glCullFace(GL_BACK);


片段着色器很简单:

#version 330 core

in vec3 texcoords;
uniform samplerCube cube_texture;
out vec4 frag_color;

void main () 
    frag_color = texture (cube_texture, texcoords);

和顶点着色器一样:

#version 330 core

in vec3 vp;
uniform mat4 P, V;
out vec3 texcoords;

void main () 
    texcoords = vp;
    gl_Position = P * V * vec4 (vp, 1.0);


编辑: 这是我生成投影矩阵的代码:

glm::mat4 Camera::getProjectionMatrix() const

    return glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);

这是我的 FoV:

 float FoV = 3.14159 * 65. / 180;

【问题讨论】:

投影矩阵可能有问题。如果您使用 FOV 非常小的截锥体,可能会导致这种行为。 我编辑了我的问题以添加投影矩阵代码的样子 glm::perspective 不是以度数而不是弧度为单位的 FOV 吗?尝试只为您的 FOV 使用 65。 【参考方案1】:

我确定了问题: 当我应该通过度数时,我将弧度传递给 glm::perspective() 函数。因此,正如对该问题的评论,答案是一个小的 FoV

【讨论】:

以上是关于OpenGL:天空盒放大太多的主要内容,如果未能解决你的问题,请参考以下文章

GLSL 纹理函数只为天空盒返回黑色

unity3d怎么在脚本里面更改天空盒

关于Unity中天空盒的使用

unity怎么不让天空盒子的太阳反射到地面太难看

关于Unity中如何代码动态修改天空盒

unity 中怎样设置动态天空盒,让天空盒上的云动起来