(自用)learnOpenGL学习总结-高级OpenGL-立方体贴图

ok终于来到了立方体贴图了,在这里面我们可以加入好看的天空包围盒,这样的画我们的背景就不再是黑色的了!

首先,立方体贴图和前面的sampler2D贴图一样,不过是6个2D组成的立方体而已。

那么为什么要把6个组合在一起呢?立方体贴图可以通过一个方向向量来进行索引(或者说采样)。什么意思?

我们类比一下,之前在一个2D面上我们通过uv纹理坐标来找到对应的纹理值对吧。这里也一样,不过是通过一个方向向量来获得。

 假设我们有一个立方体、然后又有一个立方体贴图,只要立方体中心在原点,我就可以通过立方体表面的位置来确定对应的方向向量从而确定对应的立方体纹理坐标。

创建立方体贴图

和前面创建贴图一样。

unsigned int textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);

不过因为有6个面,所以需要贴6次。

int width, height, nrChannels;
unsigned char *data;  
for(unsigned int i = 0; i < textures_faces.size(); i++)
{
    data = stbi_load(textures_faces[i].c_str(), &width, &height, &nrChannels, 0);
    glTexImage2D(
        GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 
        0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data
    );
}

这里我们有一个叫做textures_faces的vector,它包含了立方体贴图所需的所有纹理路径,并以表中的顺序排列。这将为当前绑定的立方体贴图中的每个面生成一个纹理。

然后还需要设置环绕和过滤方式

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_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);

可以看到这里出现了个R坐标,其实就是纹理的第三个维度,和位置的z一样。

最后在片段着色器中要使用一个samplerCube就行

天空盒

我们现在下载一个天空盒到我们的项目中。

 加载天空盒

和之前把图片加载到gpu一样,现在是加载一个cubemap。

unsigned int LoadCubeMapToGPU(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 {
			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;

};

然后需要存一个skybox的图片vector

float skyboxVertices[] = {
	// 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
};

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

然后需要给这cube给一个VAO VBO

	unsigned int cubemapTexture = LoadCubeMapToGPU(faces);

	unsigned int skyboxVAO, skyboxVBO;
	glGenBuffers(1, &skyboxVBO);
	glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);

	glGenVertexArrays(1, &skyboxVAO);
	glBindVertexArray(skyboxVAO);

	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

最后写一个skybox的shader就好。

#version 330 core

layout(location = 0) in vec3 aPos;

out vec3 TexCoords;

uniform mat4 projMat;
uniform mat4 viewMat;

void main(){
	gl_Position = projMat*viewMat*vec4(aPos,1.0f);
	TexCoords = aPos;
}

#version 330 core
out vec4 FragColor;
in vec3 TexCoords;

uniform samplerCube skybox;

void main(){

	FragColor =	 texture(skybox,TexCoords);
}

可以看到在顶点着色器里面我们把坐标信息作为纹理信息传给了片段着色器,这是因为cubemap的纹理坐标就是一个向量,所以我们直接把原点在世界中心的立方体的各点坐标当作纹理向量给片段着色器就好。

最后是loop中,我们要记住,画天空盒,我们得先画,而且画的时候需要把深度测试关了,这样的画,之后的物体就是画在背景之前了。

loop中这么写。

//第一阶段
...
//clear screen
...
//skybox
glDepthMask(GL_FALSE);
skyboxShader->use();

iewMat = camera.GetViewMatrix();
projMat = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);
glUniformMatrix4fv(glGetUniformLocation(skyboxShader->ID, "viewMat"), 1, GL_FALSE, glm::value_ptr(viewMat));
glUniformMatrix4fv(glGetUniformLocation(skyboxShader->ID, "projMat"), 1, GL_FALSE, glm::value_ptr(projMat));


glBindVertexArray(skyboxVAO);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
glDrawArrays(GL_TRIANGLES, 0, 36);
glDepthMask(GL_TRUE);
...
//木块 机器人 其他

不过结果不对,我们希望天空盒是以玩家为中心的,这样不论玩家移动了多远,天空盒都不会变近,让玩家产生周围环境非常大的印象。然而,当前的观察矩阵会旋转、缩放和位移来变换天空盒的所有位置,所以当玩家移动的时候,立方体贴图也会移动!我们希望移除观察矩阵中的位移部分,让移动不会影响天空盒的位置向量。

在基础光照小节中,我们通过取4x4矩阵左上角的3x3矩阵来移除变换矩阵的位移部分。我们可以将观察矩阵转换为3x3矩阵(移除位移),再将其转换回4x4矩阵,来达到类似的效果。

修改viewMat

glm::mat4 view = glm::mat4(glm::mat3(camera.GetViewMatrix()));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/355882.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

81.网游逆向分析与插件开发-背包的获取-装备栏数据结构的逆向分析

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;自动化助手显示物品数据-CSDN博客 然后游戏中有弓箭&#xff0c;弓箭有数量&#xff0c;可以作为突破口&#xff0c;也可以使用物品id 获取弓的方式 获取弓箭的方式 然后搜索250 然后搜索出一个 然后…

【智能家居入门之微信小程序控制下位机】(STM32、ONENET云平台、微信小程序、HTTP协议)

实现微信小程序控制单片机外设动作 一、使用ONENET可视化组件控制单片机外设动作二、使用微信小程序控制单片机外设动作三、总结 本篇博客话接上文&#xff1a; https://blog.csdn.net/m0_71523511/article/details/135892908 上一篇博客实现了微信小程序接收单片机上传的数据…

《吐血整理》高级系列教程-吃透Fiddler抓包教程(30)-Fiddler如何抓取Android7.0以上的Https包-番外篇

1.简介 通过宏哥前边几篇文章的讲解和介绍想必大家都知道android7.0以上&#xff0c;有android的机制不在信任用户证书&#xff0c;导致https协议无法抓包。除非把证书装在系统信任的证书里&#xff0c;此时手机需要root权限。但是大家都知道root手机是非常繁琐的且不安全&…

开源大数据集群部署(七)Freeipa卸载

作者&#xff1a;櫰木 1、命令卸载 卸载FreeIPA服务器和客户端的命令&#xff0c;以及清理相关残留文件和卸载相关软件包。 ipa-server-install -U --uninstall #服务端卸载 ipa-client-install -U --uninstall #客户端卸载 #删除残留文件&#xff0c;避免二次安装失败 cd /va…

数据可视化工具JSON Crack结合内网穿透实现公网访问

文章目录 1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互…

Prometheus 监控系统的初步了解与系统搭建

目录 目录 目录 前言 Prometheus的相关知识 Prometheus特点 Prometheus的存储引擎&#xff1a;TSDB Prometheus的组件 1.核心组件&#xff1a;prometheus server Prometheus server又分为三个部分&#xff1a; 2.exports 3.client Library 4.cadvisor 5.blackbox-ex…

Java毕业设计-基于jsp+servlet的人事管理系统-第79期

获取源码资料&#xff0c;请移步从戎源码网&#xff1a;从戎源码网_专业的计算机毕业设计网站 项目介绍 基于jspservlet的人事管理系统&#xff1a;有配套报告文档&#xff0c;前端 jsp、jquery&#xff0c;后端 servlet、jdbc&#xff0c;集成员工档案管理、公告浏览、请假信…

H5项目使用@microsoft/fetch-event-source

前言&#xff1a; 在microsoft/fetch-event-source 文档中&#xff0c;没有介绍在项目中使用script 引入&#xff0c;只介绍了通过npm 引入的方式&#xff1b;项目的接口又是 post 方式的流式接口。 解决方式&#xff1a; 借助 webpack 工具 实现步骤&#xff1a; 1、初始化…

vue预览pdf文件的几种方法

文章目录 vue预览pdf集中方法方法一&#xff1a;方法二&#xff1a;展示效果&#xff1a;需要包依赖&#xff1a;代码&#xff1a; 方法三&#xff1a;展示效果&#xff1a;需要包依赖&#xff1a;代码&#xff1a;自己调参数&#xff0c;选择符合自己的 vue预览pdf集中方法 我…

方差与协方差之间的区别?

方差和协方差都是用来衡量随机变量之间关系的统计量&#xff0c;但它们的计算方式和含义有所不同。 方差&#xff08;Variance&#xff09;&#xff1a;方差是描述数据集合离散程度的统计量&#xff0c;它衡量了数据点与均值之间的平均距离。 方差越大&#xff0c;表示数据点越…

【AI大模型应用开发】1.3 Prompt攻防(安全) 和 Prompt逆向工程

随着GPT和Prompt工程的大火&#xff0c;随之而来的是隐私问题和安全问题。尤其是最近GPTs刚刚开放&#xff0c;藏在GPTs后面的提示词就被网友们扒了出来&#xff0c;甚至直接被人作为开源项目发布&#xff0c;一点安全和隐私都没有&#xff0c;原作者的收益也必然受到极大损失……

图灵日记之java奇妙历险记--抽象类和接口

目录 抽象类概念抽象类语法 接口概念规则使用特性实现多个接口接口的继承接口使用实例Clonable接口和深拷贝抽象类和接口的区别 Object类 抽象类 概念 在面向对象的概念中,所有对象都是通过类来描述的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够…

Axios使用方法详解,从入门到进阶

目录 &#x1f333; Axios的诞生 &#x1f333; Axios的介绍 定义 原理 特性 浏览器支持情况 如何安装 &#x1f333; Axios的使用 ◼️ 创建vue项目 ◼️ Axios的基础用法&#xff08;get、post、put 等请求方法&#xff09; get方法 post方法 put和patch方法 …

Jenkins打包、发布、部署

目录 前言 一、安装jdk 二、安装maven 三、安装git 四、安装jenkins 五、访问jenkins 六、创建用户 七、配置jenkins 八、执行 总结 前言 服务器&#xff1a;CentOS 7.9 64位 jdk&#xff1a;1.8 maven&#xff1a;3.9.1 git&#xff1a;git version 1.8.3.1 jenkins&a…

C++中的智能指针

目录 背景 裸指针 智能指针 原理 智能指针 auto_ptr unique_ptr 1. unique_ptr禁止拷贝构造(copy constructor)和赋值运算() 1.1 C提供了标准库函数move() 1.2.如果unique_ptr是一个临时右值 2. unique_ptr可用于数组 shared_ptr 环状引用问题 weak_ptr 注意&#xf…

CRM管理系统有哪些应用价值?

如何杜绝员工飞单、走私单&#xff1f; 如何避免员工离职带走客户&#xff1f; ——crm管理系统 企业要想取得成功&#xff0c;有强大的技术支持和合适的工具辅助&#xff0c;crm管理系统这类工具就是客户管理系统&#xff0c;它是一种先进的管理模式&#xff0c;crm管理系统通…

浅析透明图片显示

1、理解图片构成 上面是一个飞机的透明图片&#xff0c;每个图片都是有一个个像素点构成的&#xff0c;每个像素点都是一个颜色&#xff0c;在内存中占4个字节&#xff0c;由透明度、红、绿、蓝构成。如下图&#xff1a; 该飞机图片飞机图片长51像素&#xff0c;宽63像素。就是…

苹果m1、m2安装blender GIS,解决not Imageio 报错

blender-GIS 能够在地图上生成地形&#xff0c;如下图所示&#xff1a; 使用blenderGIS过程中会有 imageio 找不到的情况&#xff0c; 网上的 imageio 用在苹果电脑的M1、M2芯片上好像还是没有出图&#xff0c;似乎这个 imageio 这个已经是好几年前的代码&#xff0c;没能适配…

Sphinx的原理详解和使用

一、Sphinx介绍 1.1 简介 Sphinx是由俄罗斯人Andrew Aksyonoff开发的一个全文检索引擎。意图为其他应用提供高速、低空间占用、高结果 相关度的全文搜索功能。Sphinx可以非常容易的与SQL数据库和脚本语言集成。当前系统内置MySQL和PostgreSQL 数据库数据源的支持&#xff0c;也…

Vue3 + Express 实现大文件分片上传、断点续传、秒传

目录 前言原理实现项目搭建获取文件文件分片hash计算文件上传文件合并秒传&断点续传 完整代码 前言 在日常开发中&#xff0c;文件上传是常见的操作之一。文件上传技术使得用户可以方便地将本地文件上传到Web服务器上&#xff0c;这在许多场景下都是必需的&#xff0c;比如…