c++ - 无法在 OpenGL 中渲染天空盒

标签 c++ opengl rendering skybox

没有可见的天空盒,但代码似乎工作正常。

这就是我最终看到的:

screen

我是 OpenGL 新手,所以这可能是 GL 代码的绑定(bind)或位置问题。如需完整代码,您可以访问:https://github.com/ZigoRiloo96/Riloo_Engine

这里我有 Skybox 类:

class Skybox
{
public:
    Skybox();
    ~Skybox();

    void Draw(const glm::mat4& view, const glm::mat4& projection);

private:
    unsigned int cubemapTexture;

    GLuint VAO;
    GLuint VBO;

    Shader* shader;

    GLuint loadCubemap(std::vector<std::string> faces);
};

着色器:

#version 330 core
layout (location = 0) in vec3 aPos;

out vec3 TexCoords;

uniform mat4 projection;
uniform mat4 view;

void main()
{
    TexCoords = aPos;
    vec4 pos = projection * view * vec4(aPos, 1.0);
    gl_Position = pos.xyww;
}

#version 330 core
out vec4 FragColor;

in vec3 TexCoords;

uniform samplerCube skybox;

void main()
{    
    FragColor = texture(skybox, TexCoords);
}

以及类的实现:

Skybox::Skybox()
{
    GLfloat skyboxVertices[108] = 
    {
        // positions          
        -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
    };

    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

    std::vector<std::string> faces
    {
        "Resources/skybox/right.jpg",
        "Resources/skybox/left.jpg",
        "Resources/skybox/top.jpg",
        "Resources/skybox/bottom.jpg",
        "Resources/skybox/front.jpg",
        "Resources/skybox/back.jpg"
    };

    cubemapTexture = loadCubemap(faces);

    shader = new Shader("Resources/Shaders/skybox.vp", "Resources/Shaders/skybox.frag");

    shader->Use();
    shader->setInt("skybox", 0);
}

Skybox::~Skybox()
{
}

void Skybox::Draw(const glm::mat4& view, const glm::mat4& projection)
{
    glDepthFunc(GL_LEQUAL);
    shader->Use();
    shader->setMat4("view", glm::mat4(glm::mat3(view)));
    shader->setMat4("projection", projection);
    // skybox cube
    glBindVertexArray(VAO);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);
    glDepthFunc(GL_LESS); 
}

GLuint Skybox::loadCubemap(std::vector<std::string> faces)
{
    unsigned int textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

    int width, height, nrChannels;
    for (unsigned int i = 0; i < faces.size(); i++)
    {
        unsigned char *data = stbi_load(faces[i].c_str(), &width, &height, &nrChannels, 0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
            stbi_image_free(data);
        }
        else
        {
            printf("Stb can't load this sh*t: %s\n", faces[i].c_str());
            stbi_image_free(data);
        }
    }
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    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);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    return textureID;
}

最佳答案

感谢大家的帮助,但我犯了一个愚蠢的错误。当我在一个普通的立方体上渲染天空盒后,我明白了问题所在。这是我将矩阵设置为着色器的函数(他就是这个恶棍):

void Shader::setMat4(const char* char_s, const glm::mat4& mat)
{
    glUniformMatrix4fv(glGetUniformLocation(Program, "projection"), 1, GL_FALSE, glm::value_ptr(mat));
}

解决方案是将“projection”替换为char_s

img

关于c++ - 无法在 OpenGL 中渲染天空盒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49124199/

相关文章:

c++ - Visual Studio 2008 中特定于文件的编译选项

C++ - 生成具有可配置均值 "1s to 0s"比率的随机位集的有效方法

c++ - 新建 OpenGL 项目 glewInit() 错误

opengl - 通过统一属性将 float3/vec3 传递给着色器

linux - 如何将动画 3D 场景渲染为 h.264 流?

c++ - 为什么 Mac OSX pipe(2) 中的 read(2) 将 0x7F 插入到字符串中?

c++ - 为什么我的指针不是结构或 union ?

c++ - OpenGL着色器输入

ios - 在 UIImage 中平滑地移动一个洞?

opengl - 我是否需要 Gamma 校正现代计算机/显示器上的最终色彩输出