LearnOpenGL-高级OpenGL-6.天空盒

本文介绍了使用OpenGL进行天空盒渲染、环境映射(包括反射和折射)的技术。首先讲解了天空盒的概念和采样方法,然后通过代码示例展示了如何创建和应用立方体贴图实现天空盒效果。接着,文章详细阐述了反射的原理和实现,包括立方体反射及模型反射。最后讨论了折射的原理,并给出了相应的代码实现。整个过程中,深度测试的作用和调整是关键,确保了渲染的正确顺序和效果。

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正

我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject

天空盒

介绍

立方体贴图就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体

如何采样

  • 方向向量的大小并不重要,只要提供了方向,OpenGL就会获取方向向量(最终)所击中的纹素,并返回对应的采样纹理值。
  • 只要立方体的中心位于原点,我们就能使用立方体的实际位置向量来对立方体贴图进行采样了。
  • 我们可以将所有顶点的纹理坐标当做是立方体的顶点位置。最终得到的结果就是可以访问立方体贴图上正确面(Face)纹理的一个纹理坐标。

立方体有36个顶点位置,在顶点着色器后顶点属性进行线性插值,每个片段都有自己的顶点位置,采样天空盒时用这个顶点位置当做纹理坐标即可,立方体的一个面的正反面的天空盒图案都一样,实际是作为摄像机的我们处在一个采样6个贴图的盒子内部,以此实现游戏的远景。

OpenGL纹理目标

纹理目标 方位
GL_TEXTURE_CUBE_MAP_POSITIVE_X
GL_TEXTURE_CUBE_MAP_NEGATIVE_X
GL_TEXTURE_CUBE_MAP_POSITIVE_Y
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
GL_TEXTURE_CUBE_MAP_POSITIVE_Z
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

例子0:天空盒效果

  • 加载天空盒

    // 加载纹理// -------------
    unsigned int cubeTexture = loadTexture(FileSystem::getPath("assest/textures/container.jpg").c_str());
    // 加载天空盒
    vector<std::string> faces{
         
         
        FileSystem::getPath("assest/textures/skybox/right.jpg"),
        FileSystem::getPath("assest/textures/skybox/left.jpg"),
        FileSystem::getPath("assest/textures/skybox/top.jpg"),
        FileSystem::getPath("assest/textures/skybox/bottom.jpg"),
        FileSystem::getPath("assest/textures/skybox/front.jpg"),
        FileSystem::getPath("assest/textures/skybox/back.jpg")
    };
    unsigned int cubemapTexture = loadCubemap(faces);
    // 加载天空盒
    // 加载顺序
    // order:
    // +X (right)
    // -X (left)
    // +Y (top)
    // -Y (bottom)
    // +Z (front) 
    // -Z (back)
    unsigned int loadCubemap(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 {
         
         
                std::cout << "Cubemap texture failed to load at path:" << faces[i] << std::endl;
                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;
    }
    
  • 为天空盒创建立方体的六个面的顶点数据以及VAO VBO

    // skybox VAO
    unsigned int skyboxVAO, skyboxVBO;
    glGenVertexArrays(1, &skyboxVAO);
    glGenBuffers(1, &skyboxVBO);
    glBindVertexArray(skyboxVAO);
    glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
    glBufferData(GL_ARRAY_BUFFER
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘建杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值