计算机图形学 | 实验九:纹理贴图和天空盒

news2024/12/30 3:26:58

计算机图形学 | 实验九:纹理贴图和天空盒

  • 计算机图形学 | 实验九:纹理贴图和天空盒
    • 实验概述
    • 顶点数据
      • 立方体顶点数据
      • 天空盒顶点数组
    • 纹理载入
      • 创建纹理
      • 纹理读取
      • 纹理绑定
    • 使用纹理
      • 立方体着色器
        • 顶点着色器
        • 片元着色器
      • 天空盒着色器
        • 顶点着色器
        • 片元着色器
    • 立方体贴图和平面纹理对比
      • 着色器中的区别
      • 定义和设置上的区别
        • 纹理定义
        • 资源载入
      • 天空盒位置的控制
    • 总结

华中科技大学《计算机图形学》课程

MOOC地址:计算机图形学(HUST)

计算机图形学 | 实验九:纹理贴图和天空盒

实验概述

这次实验我们主要学习如何绘制带有平面纹理的立方体,以及运用立方体贴图实现的天空盒。实验要求:

  1. 平面纹理(之前实验的基础上,在立方体贴上纹理)
  2. 立方体贴图(天空盒,背景的天空盒采用立方体贴图)

实验最终的实现效果:

在这里插入图片描述

顶点数据

立方体顶点数据

这是立方体顶点数组,可以看到前三个float量是我们熟悉的顶点坐标位置,后面两个float量是顶点所对应的纹理UV坐标,通过这个UV坐标,我们可以控制将纹理上的哪一部分贴在三角形片元上。

const float vertices[] = { //立方体数组
	-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
	0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
	0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
	0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
	0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
	-0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

	-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
	-0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
	-0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

	0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
	0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
	0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
	0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
	0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
	0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
	0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
	-0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
	-0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
	0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
	0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
	-0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
	-0.5f,  0.5f, -0.5f,  0.0f, 1.0f
};

天空盒顶点数组

紧接着我们看到天空盒的顶点数组。我们可以发现,天空盒的顶点数组是没有之前的纹理坐标的。

float skybox_vertices[] = {   //天空盒顶点数组
	-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
};

因为我们使用的是立方体贴图,天空盒的顶点坐标即可对应它纹理坐标。我们可以直接将顶点坐标作为立方体贴图的纹理坐标。

纹理载入

我们用平面纹理包裹住之前实验实现的立方体,用立方体贴图包裹住天空盒,即可得到我们最后需要的结果。

为了实现纹理贴图,我们需要进行几步操作:首先进行纹理定义和设置,然后进行纹理资源载入,生成多级纹理,在使用前进行纹理绑定,以及最后在着色器中进行采样。

在这里插入图片描述

创建纹理

首先我们定义一个纹理,绑定在GL_TEXTURE_2D上,然后就开始设置它的纹理属性,最后四行中,前两行是用来设置纹理的环绕方式。后两行则是设置纹理的过滤方式。设置这些纹理的属性有很多参数,下面我们就来介绍一下这里的参数有哪些,分别都是什么作用。

GLuint texture1; glGenTextures(1, &texture1); 
glBindTexture(GL_TEXTURE_2D, texture1); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

上面的代码中,glTexParameteri函数是负责设置纹理的属性。

其中第四、第五行代码:

  1. GL_TEXTURE_WRAP_S表示在s轴上纹理的环绕方式;
  2. GL_TEXTURE_WRAP_T表示在T轴上纹理的环绕方式,这里s和t等价于平面纹理图片的x轴和y轴;
  3. GL_REPEAT是表示纹理重复出现,它也是在不设置的情况下默认环绕方式。GL_MIRRORED_REPEAT也是重复图片,但是他表示以镜像方式重复出现;
  4. GL_CLAMP_TO_EDGE表示纹理坐标会被约束在0-1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。这种环绕方式通常会在我们设置纹理坐标超过0-1的范围时被使用到。

其中第六第七行代码:

  1. GL_TEXTURE_MIN_FILTER是设置纹理在缩小时的过滤方式
  2. GL_TEXTURE_MAG_FILTER是设置纹理在放大时的过滤方式。

过滤方式我们主要使用的有两种,一种是GL_NEAREST即线性过滤,这种过滤方法会产生颗粒状的图案,但是也能更清晰的看到组成纹理的像素。GL_LINEAR即临近过滤,它能够产生更平滑的图案,但是也有更真实的输出。

纹理读取

接下来我们学习如何进行资源载入,即把图片读入内存,最终绑定到着色器。我们使用#include <stb/stb_image.h>中的_stbi_load,根据路径读取纹理图片,并读取纹理的宽高和通道数,将纹理数据存入data数组中,最后判断是否读取成功,若失败,则报错,若成功,则进行下一步操作。部分代码如下:

//加载纹理
int width, height, nrchannels;//纹理长宽,通道数
stbi_set_flip_vertically_on_load(true);
unsigned char *data = stbi_load("res/texture/CG_Sprite.jpg", &width, &height, &nrchannels, 0);
if (data)
{
	//生成纹理
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
	glGenerateMipmap(GL_TEXTURE_2D);
}
else
	std::cout << "Failed to load texture" << std::endl;

在读取纹理之后,我们还要将data中的纹理数据存入GL_TEXTURE_2D,存入的时候我们需要同时输入纹理的宽高,接着我们使用glGenerateMipmap(GL_TEXTURE_2D)生成多级渐远纹理。

纹理绑定

由于可能出现多个纹理,所以我们每次使用纹理绘制之前,最好进行一次绑定操作。glActiveTexture(GL_TEXTURE0)为选择GL_TEXTUERE0纹理单元,将要要使用的纹理绑定到GL_TEXTURE0纹理单元中,计算机有很多纹理单元GL_TEXTURE1 GL_TEXTURE0 GL_TEXTURE2 GL_TEXTURE3 GL_TEXTURE4,使用时每个纹理最好对一个纹理单元。

接着我们使用glBindTexture(GL_TEXTURE_2D, texture1);去绑定纹理,绑定后即可进行绘制。

glActiveTexture(GL_TEXTURE0); //绑定纹理
glBindTexture(GL_TEXTURE_2D, texture1);

...

glDrawArrays(GL_TRIANGLES, 0, 36);//绘制

使用纹理

后面介绍如何在着色器中使用纹理,需要注意的是,立方体和天空盒使用纹理的方式是不一样的,我们先看看着色器中如何使用平面纹理。

立方体着色器

顶点着色器

立方体的顶点着色器负责的纹理方面的功能不多,只是将顶点对应的纹理坐标传入片元着色器。

#version 330 core 
layout (location = 0) 
in vec3 aPos; 
layout (location = 1) in vec2 aTexCoord; 
out vec2 TexCoord; 
...
void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0); 
	TexCoord=vec2(aTexCoord.x,aTexCoord.y);
}

片元着色器

片元着色器则是根据传入的sampler2D类型的纹理和纹理对应坐标,使用texture进行采样,获取当前片元的颜色值。

在这里插入代码片
#version 330 core 
out vec4 FragColor; 
in vec2 TexCoord; 
uniform sampler2D texture1; 
void main() 
{
	FragColor = texture(texture1,TexCoord);
}

天空盒着色器

顶点着色器

接着我们看到天空盒的着色器具体跟立方体的着色器到底有哪些不同。

天空盒的顶点着色器将顶点坐标直接作为纹理坐标传入片元着色器,可以发现平面纹理的纹理坐标是vec2类型,而立方体的纹理坐标则是vec3类型,并且pvm矩阵也发生了变化,这个我们后面再提,还有我们可以看到的是我们把z变量替换成了w,这是为了使天空盒永远在所有物体之后,作为背景,使其深度值最大,不遮挡任何物体。

#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);
	//这是因为天空盒会在之后覆盖所有的场景中其他物体。我们需要耍个花招让深度缓冲相信天空盒的深度缓冲有着最大深度值1.0,如此只要有个物体存在深度测试就会失败,看似物体就在它前面了
	//透视除法(perspective division)是在顶点着色器运行之后执行的,把gl_Position的xyz坐标除以w元素。我们从深度测试教程了解到除法结果的z元素等于顶点的深度值。利用这个信息,我们可以把输出位置的z元素设置为它的w元素,这样就会导致z元素等于1.0了,因为,当透视除法应用后,它的z元素转换为w/w = 1.0:
    gl_Position = pos.xyww;
}  

片元着色器

天空盒的片元着色器也与立方体的片元着色器有些不同,它传入的是samplerCube类型的立方体贴图,且纹理坐标也是vec3类型,但是最终还是通过texture进行采样。

#version 330 core
out vec4 FragColor;

in vec3 TexCoords;

uniform samplerCube skybox;

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

立方体贴图和平面纹理对比

着色器中的区别

我们刚才这是对立方体和天空盒着色器的区别进行了分析,发现天空盒着色器传入的纹理是samplerCube类型,那我们怎样向着色器传入samplerCube类型的纹理呢?它与立方体纹理的区别又在那里呢?

立方体贴图的六个面,每个面都对应一个纹理,且有其相应的顺序。有人可能会觉得为什么不能贴六个纹理而非要用立方体贴图呢?那是因为立方体贴图有其独特的属性,我们有时候可以直接使用方向向量对立方体贴图进行索引和采样。

我们可以设想一下,有一束光线从立方体的中心向任意一个方向射出,我们知道了射出光线的方向向量,即可在在立方体贴图上找到对应的纹理坐标,获取到相应的颜色值,通过这种方法我们可以实现光的折射和反射,通过出射光和入射光的方向找到对应的颜色值。

定义和设置上的区别

我们之前讲了立方体贴图和平面纹理在着色器中的区别,那他们在别的方面还有什么区别吗?因为立方体贴图包括六个相关的平面纹理,所以他们在纹理的定义和设置和资源载入上还是有一些区别的。

纹理定义

首先设置纹理属性值,首先是定义纹理id时,我们将GLuint换成了unsigned int,这两种方式其实是完全等价的,所以使用的时候我们可以根据自己的需要来,接着就是绑定纹理,因为是立方体纹理,所以之前的绑定在GL_TEXTURE_2D变成了绑定在GL_TEXTURE_CUBE_MAP,其他属性的设置基本相同,但是需要注意的是,由于以及是立体纹理而不仅仅是平面纹理了,所以他的环绕方式也多出了一个R轴的环绕方式,对应的是现实中的z轴。

unsigned int load_cubemap(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++)
	{
		stbi_set_flip_vertically_on_load(false);
		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;
}

资源载入

资源载入时我们也需要一次性载入6张纹理,一般我们使用for循环载入,循环六次,同时每次载入纹理存储的地址也有所不同,不同的纹理存储在不同的地址,不过这些地址都是相邻的,所以每次只需要加i即可。

unsigned int load_cubemap(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++)
	{
		stbi_set_flip_vertically_on_load(false);
		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;
}

天空盒位置的控制

那么我们该如何摆放天空盒呢?首先天空盒是一个包裹着相机的大盒子,它不需要进行世界坐标系的模型变换,其次相机不管如何移动,应该始终在天空盒的中心点,那么我们如何取消天空盒着色器中view矩阵的位移而保存相机视角变换之类的操作呢?

相机view矩阵,主要包含了位移和旋转操作,如图4.3.1所示,第一行公式为位移矩阵如何发挥其功能,而位移部分则是在Tx,Ty,Tz中体现, Tx,Ty,Tz为位移量,我们只需要把view矩阵从4x4先转换为3x3矩阵,去掉位移部分,再转换回4x4矩阵,则可完全去掉位移量,并保持旋转效果。

在这里插入图片描述

体现在程序中则是如下操作,先转换成mat3矩阵,再转换成mat4矩阵。

//去除相机位移
view = glm::mat4(glm::mat3(glm::lookAt(camera_position, camera_position + camera_front, camera_up))); 

总结

以上为本次实验的要点解析,下面是实验结果演示。

在这里插入图片描述

运行之后我们移动视角可以发现,不管我们怎样移动相机的位置,天空盒相对于摄像机的位置始终保持不变。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

管好【SD-WEBUI】中大量的模型:模型信息预览插件(Part.3)

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;模型预览图&#xff08;一&#xff09;模型信息预览插件&#xff08;Model Preview&#xff09;&#xff08;1.1&#xff09;示例&#xff08;Markdown描述提示词备注&#xff09;&#xff08;1.2&#xff0…

AI大模型驱动下,数字虚拟人与虚拟场景为高等学院建设带来何种改变?

继今年年初美国人工智能研究实验室OpenAI推出ChatGPT&#xff08;一种人工智能驱动的自然语言处理工具&#xff09;之后一段时间里&#xff0c;阿里、百度、商汤等一众国内IT巨头纷纷发布了各自的AI大模型&#xff08;可浅理解为用于AI学习用的超大量数据&#xff09;&#xff…

运动控制轴单位设置(H5U PLC)

H5U PLC运动控制相关应用,请参看下面博客文章 10轴总线控制(汇川H5UPLC+总线伺服编程应用)_RXXW_Dor的博客-CSDN博客H5UPLC控制总线伺服的详细配置过程,可以参看下面的文章链接:汇川H5U PLC通过EtherCAT总线控制SV660N和X3E伺服_ethercat总线伺服如何控制_RXXW_Dor的博客-C…

使用MFT进行加密文件传输的7个好处

至少&#xff0c;托管文件传输&#xff08;MFT&#xff09;解决方案是一种产品&#xff0c;它包含入站和出站文件传输的所有方面&#xff0c;同时使用行业标准的网络协议和无缝加密。它可以从单个集中管理点在您的网络&#xff0c;系统&#xff0c;应用程序&#xff0c;贸易伙伴…

2024王道数据结构考研丨第二章:线性表

2024王道数据结构考研笔记专栏将持续更新&#xff0c;欢迎 点此 收藏&#xff0c;共同交流学习… 文章目录 第二章&#xff1a;线性表2.1线性表的定义2.2顺序表的定义2.2.1静态分配:2.2.2动态分配 2.2顺序表的基本操作1.插入操作 &#xff1a;平均时间复杂度O(n)2.删除操作&…

小白怎么入门网络安全?看这篇文章就够啦!(2023最新)

作为一名从业多年的网络安全工程师&#xff0c;我了解到&#xff0c;网络安全是一个高度技术密集的领域&#xff0c;它涵盖了网络架构、网络协议、操作系统、编程语言、密码学、安全漏洞、入侵检测和应急响应等多个方面。如果你是零基础的小白&#xff0c;想要进入这个行业&…

5个设计师必备的页面设计工具!

在现代科技飞速发展的时代&#xff0c;设计软件的选择越来越多。本文将盘点 5 大主流页面设计工具其中&#xff0c;即时设计是一款协同页面设计工具&#xff0c;提供在线编辑和保存等功能&#xff0c;同时拥有免费设计素材和在线留言评论等实用功能。它的云端协作设计使得复杂的…

街电入局两轮电动车充电,讲出了“跃迁”式的新故事?

以共享单车为起点&#xff0c;中国的共享经济正蓬勃发展。国家信息中心披露的数据显示&#xff0c;2022年&#xff0c;中国共享经济市场交易规模约38320亿元&#xff0c;同比增长约3.9%。 虽然同属共享经济&#xff0c;但与部分共享单车企业嫁入“豪门”全身而退不同&#xff…

【接口自动化测试】cookie绕过验证码自动登录?(保持登录状态)

目录 前言 cookie工作原理 cookie绕过登录 【自动化测试工程师学习路线】 1、自动化测试必备Python编程内容​ 2、Web UI 自动化测试基础内容​ 3、Web UI 自动化测试实战内容​ 4、APP UI 自动化测试基础内容​ 5、APP UI 自动化测试实战内容​ 6、API 接口自动化测…

实验四 面向对象分析与设计——UML类图与时序图

一、实验目的&#xff1a; 掌握面向对象分析中静态结构模型与动态行为模型的基本思想。学会识别系统中的类、类的属性和操作以及类之间的关系&#xff0c;掌握UML类图的绘制方法。了解时序图的作用和组成元素&#xff0c;掌握UML时序图的绘制方法。 二、实验仪器及实验环境&a…

ATA-2000系列高压放大器在压电陶瓷中的典型应用

ATA-2000系列高压放大器在压电陶瓷中的典型应用 压电陶瓷介绍&#xff1a; 压电陶瓷是一种能够将机械能和电能互相转换的陶瓷材料。压电陶瓷除具有压电性外&#xff0c;还具有介电性、弹性等,已被广泛应用于医学成像、声传感器、声换能器、超声马达等。压电陶瓷利用其材料在机…

改进YOLOv7 | 头部解耦 | 将YOLOX解耦头添加到YOLOv7 | 涨点杀器

改进YOLOv7 | 头部解耦 | 将YOLOX解耦头添加到YOLOv7 论文地址:https://arxiv.org/abs/2107.08430 文章目录 改进YOLOv7 | 头部解耦 | 将YOLOX解耦头添加到YOLOv71. 解耦头原理2. 解耦头对收敛速度的影响3. 解耦头对精度的影响4. 代码改进方式第一步第二步第三步第四步第五步参…

字节跳动测试岗四面总结....

字节一面 1、 简单做一下自我介绍 2、 简要介绍一下项目/你负责的模块/选一个模块说一下你设计的用例 3 、get请求和post请求的区别 4、 如何判断前后端bug/3xx是什么意思 5、 说一下XXX项目中你做的接口测试/做了多少次 6、 http和https的区别 7、 考了几个ADB命令/查看…

NebulaGraph和HugeGraph调研

1、社区资料丰富程度 各平台搜索词条数汇总 图数据库百度搜索必应搜索谷歌搜索CSDN知乎掘金简书语雀githubgiteestackoverflowNebulaGraph261000072600090600128810768131324188202HugeGraph45720001156500530009630170215132811 经过对比&#xff0c;NebulaGraph 在谷歌搜索…

大数据期末复习资料2023 Beta版

大数据单元1在线测试&#xff1a;https://ks.wjx.top/vm/tv3XfFg.aspx# 大数据单元2在线测试&#xff1a;https://ks.wjx.top/vm/QfXBgWP.aspx# 大数据单元3在线测试-1&#xff1a;https://ks.wjx.top/vm/PeLX5WR.aspx# 大数据单元3在线测试-2&#xff1a;https://ks.wjx.top/v…

重磅来袭,ChatGPT官方的掌上神器目前仅支持IOS

今天凌晨&#xff0c;OpenAI 推出了 ChatGPT 的 iOS app&#xff0c;在这个开放的世界里&#xff0c;智能化的 AI 功能早已经突破了人类的想象力。而 ChatGPT 确实不会让我们失望&#xff0c;它的真「iPhone 时刻」来了&#xff01;从现在起&#xff0c;我们可以在 iPhone 上使…

3面美团测试岗,HR现场直接发20k的offer,我是横着走出来的...

前情提要 这是一个发生在我身上的真实事情&#xff1a; 我工作不到2年&#xff0c;周末在朋友圈发了个喜报&#xff0c;准备入职美团。之后&#xff0c;我的朋友就带着祝福跟我聊了许久&#xff0c;聊天的内容就是具体了解一下我面试的过程&#xff0c;心路历程和未来的打算…

解决方案|电源适配器自动测试系统ATECLOUD-Power

随着电子产品的不断普及&#xff0c;电源适配器的应用越来越广泛。然而&#xff0c;在生产过程中&#xff0c;适配器电源的质量是至关重要的。为了确保电子产品的质量&#xff0c;适配器电源需要经过严格的测试和验证。传统的适配器电源测试方法需要大量的人力和时间&#xff0…

如何让数据安全管理工作化繁为简?uDSP 十问十答

数据安全管理工作与国家数据安全、企业资产保护以及个人信息保护工作息息相关。复杂、多元、流通的数据也给数据安全带来了更多的威胁和挑战&#xff0c;如数据资产管理、分类分级问题&#xff0c;数据安全集中管控问题&#xff0c;数据共享与流通问题等。原点安全一体化数据安…

科技云报道:垂直大模型竞争,能突破数据“卡点”吗?

科技云报道原创。 AI大模型火遍全球&#xff0c;中国产业也激发了对人工智能应用的新热情。 随着各大厂商参与竞逐&#xff0c;市场正在分化为通用与垂直两大路径&#xff0c;两者在参数级别、应用场景、商业模式等方面差异已逐步显现。 企业涌入垂直大模型赛道 通用AI大模型…