本人刚学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

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

843

被折叠的 条评论
为什么被折叠?



