当前位置: 首页 > news >正文

OpenGL:Cube Map

前面绘制天空盒的时候有提到过 Cube Map,但是 Cube Map 又是什么呢?

Cube Map 其实是就是一个包含了6个2D纹理的纹理,每个2D纹理都组成了立方体的一个面:一个有纹理的立方体。与2D纹理坐标 (s, t) 不同的是,我们使用3个维度 (s, t, r) 来对 Cube Map 进行索引定位,并且 Cube Map 有个特性,其纹理坐标等于它的方向坐标。就是我们使用单位立方体,中心为原点,某个点的坐标就等于它的纹理坐标。

Cube Map 不只是能够用来创建天空盒,还能够用来制作环境反射和折射等效果。

6个纹理面
每个面对应OpenGL特定的目标:

枚举常量方向
GL_TEXTURE_CUBE_MAP_POSITIVE_X+X (右)
GL_TEXTURE_CUBE_MAP_NEGATIVE_X-X (左)
GL_TEXTURE_CUBE_MAP_POSITIVE_Y+Y (上)
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y-Y (下)
GL_TEXTURE_CUBE_MAP_POSITIVE_Z+Z (后/远)
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z-Z (前/近)

和2D纹理创建类似,我们需要读取纹理数据,然后将其绑定到纹理对象上面去。不同的是,我们创建的是 GL_TEXTURE_CUBE_MAP 为目标的纹理对象,并且需要给6个不同的目标设置不同的纹理。下面是创建 Cube Map 的伪代码:

GLuint textureID;
glGenTexture(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);const GLenum targets[6] = {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
};for(int i = 0; i < 6; ++i) {// 读取纹理数据data = load_image(faces[i]);    // faces 是纹理文件的名字// 设置纹理数据glTexImage2D(targets[i], 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
}// 设置纹理参数
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

根据上面的流程我们就创建好了一个 Cube Map 对象,下面我们将使用这个对象来进行天空盒的制作。

和skybox一样,我们需要制作shader进行天空盒的绘制:

// skybox.vert
#version 440
layout (location = 0) in vec3 aPostion;out vec3 TexCoord;uniform mat4 projection;
uniform mat4 view;void main()
{TexCoord = aPostion;gl_Position = projection * view * vec4(aPostion, 1.0f);gl_Position = gl_Position.xyww;
}

在这个 vertex shader 中,我们将原先外部传入的纹理坐标换成了使用立方体的位置坐标作为纹理坐标(这里需要注意的是,我使用的是单位大小的立方体,如果你使用不是单位大小的,你需要进行标准化)。

// skybox.frag
#version 440
out vec4 fragColor;in vec3 TexCoord;layout (binding = 0) uniform samplerCube skybox;void main()
{fragColor = texture(skybox, TexCoord);
}

在 fragment shader 中,注意到使用的sampler是专门对cubemap进行采样的 samplerCube,其使用方法和sampler2D 一样,就不赘述了。

和之前同样的绘制流程:渲染其他物体 -> 禁止深度写入 -> 渲染天空盒 -> 重置深度状态。

// 1. 首先生效的物体
renderScene(window, mainShader, currentTime, true); // 2. 天空盒配置(在最后渲染)
glDepthMask(GL_FALSE);          // 禁用深度写入
glDepthFunc(GL_LEQUAL);         // 启用小于等于深度测试skybox.use();
skybox.setMat4("projection", pMat);// 消位移,只保留旋转(防止近裁剪面穿帮)
glm::mat4 view = glm::mat4(glm::mat3(vMat)); 
skybox.setMat4("view", view);// 3. 绘制天空盒
glBindVertexArray(VAO);  
cubemap.bind();  
glDrawArrays(GL_TRIANGLES, 0, 36);   // 4. 重置深度状态
glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);

在这里插入图片描述

http://www.dtcms.com/a/618044.html

相关文章:

  • 《玩转Docker》[应用篇17]:容器可视化管理平台-Docker安装部署Portainer
  • 开平 做一网站建设工程教育网建设工程类的考试辅导网站
  • 多线程 -- 初阶(4) [单例模式 阻塞队列]
  • 如何用VS2017做网站加盟商网站建设
  • HTML 基础知识二:创建容器和表格(附html实战案例)
  • OpenCV(二十八):双边滤波
  • 【2025CVPR物体姿态估计方向】ONDA-Pose:面向自监督六维物体姿态估计的遮挡感知神经域自适应方法
  • 衡阳网站建设开发价格推广关键词排名查询
  • MATLAB基于IOWA-云模型的长距离引水工程运行安全风险评价研究
  • 基层建设论文查询官方网站零基础怎么做电商
  • 跨链如何实现消息互通,消息指的又是什么
  • 手动处理售后太慢?RPA智能处理小红书工单,效率提升1200%[特殊字符]
  • Hello-Agents task4---构建你的智能体框架
  • MySQL 主从复制机制详解:binlog 与 relay log 流程
  • 学校网站首页代码html9个广州seo推广神技
  • ROS2踩了个大坑
  • 网页制作范例泰安优化公司
  • 只做自己网站网站免费正能量不用下载
  • 人形机器人——非接触式传感技术
  • Rust在企业安全领域的应用,架构解析与实际操作
  • 当AI学会“说人话“:Azure语音合成技术的魔法世界
  • 深入探索剖析 JVM 的启动过程
  • 头歌答案--爬虫实战
  • 佛山网站建设在哪找试论述外贸网站建设应注意的问题
  • 微软技术实用指南:typescript + c#
  • 盐城市亭湖区建设局网站郑州最好的妇科医院
  • 241. Java 集合 - 使用 Collections 工厂类处理集合
  • 织梦网站换空间wordpress 添加中文字体
  • 物联网设备自适应硬件冗余与动态故障切换运维技术
  • C++零基础通关教程《第三课》