OpenGL学习笔记(十八)立方体贴图

立方体贴图
立方体贴图的应用之一就是做天空盒子。
先是顶点着色器

#version 330 core
layout (location=0) in vec3 aPos;

out vec3 TexCoords;
uniform mat4 projMat;
uniform mat4 viewMat;

void main()
{
TexCoords=aPos;
vec4 pos=projMat*viewMat*vec4(aPos*20.0f,1.0f);
gl_Position=pos.xyww;//让天空盒子的深度一直为1.0

}

片段着色器

#version 330 core
out vec4 FragColor;
in vec3 TexCoords;
uniform samplerCube skybox;
void main()
{
FragColor=texture(skybox,TexCoords);
}

然后是主函数里面

//加载立方体贴图的函数
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);//立方体贴图的方位是枚举的,所以可以直接相加可得
			
			
		}
		else
		{
			std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
			
		}
		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);
		stbi_image_free(data);
		
	}
	return textureID;
}

前序工作

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
};//绘制立方体的顶点
vector<std::string>faces//天空盒子的几个面
	{
		"skybox/right.jpg",
		"skybox/left.jpg",
		"skybox/top.jpg",
		"skybox/bottom.jpg",
		"skybox/front.jpg",
		"skybox/back.jpg"
	};
	unsigned int cubemapTexture = loadCubemap(faces);
   Shader skyboxShader = Shader("Cubemaps_vertShader.vert", "Cubemaps_fragment.frag");
   
	GLuint skyboxVAO,skyboxVBO;//这个就是老生常谈了,不讲了
	glGenVertexArrays(1, &skyboxVAO);
	glGenBuffers(1, &skyboxVBO);
	glBindVertexArray(skyboxVAO);
	glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), skyboxVertices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);

	glEnableVertexAttribArray(0);

开始绘制


//最后绘制天空盒子
glDepthFunc(GL_LEQUAL);
		skyboxShader.Use();
		viewMat = myCamera->GetViewMatrix();//获取视角矩阵
		skyboxShader.setMat4("viewMat", viewMat);
		skyboxShader.setMat4("projMat", projMat);//获取投影矩阵
		glBindVertexArray(skyboxVAO);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);//设定立方体矩阵
		//skyboxShader.setInt("skybox", 0);
		
		glDrawArrays(GL_TRIANGLES, 0, 36);
		glBindVertexArray(0);
		glDepthFunc(GL_LESS);

效果:
在这里插入图片描述
反射
在这里插入图片描述
更新箱子的顶点着色器

#version 330 core
layout (location=0) in vec3 aPos;//输入的位置向量
layout(location=1) in vec3 aNormal;//输入的法向量
out vec3 Normal;//输出的位置向量
out vec3 Position;//输出的法向量
uniform mat4 projMat;
uniform mat4 viewMat;
uniform mat4 modelMat;

void main()
{
Normal=mat3(transpose(inverse(modelMat)))*aNormal;计算法向量
Position=vec3(modelMat*vec4(aPos,1.0f));//计算位置向量
gl_Position=projMat*viewMat*modelMat*vec4(aPos,1.0f);

}

更新cube的片段着色器

#version 330 core
out vec4 FragColor;
in vec3 Normal;//顶点着色器传过来的法向量
in vec3 Position;//传过来的位置向量
uniform vec3 cameraPos;//相机位置
uniform samplerCube skybox;//需要天空盒子
void main()
{
vec3 I=normalize(Position-cameraPos);//计算i向量
vec3 R=reflect(I,normalize(Normal));//reflect传入一个法向量和观察向量计算r向量
FragColor=vec4(texture(skybox,R).rgb,1.0);
}

在这里插入图片描述
折射
在这里插入图片描述
一些常用的材质折射表
在这里插入图片描述
假设箱子为玻璃材质:
修改片段着色器

#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec3 Position;
uniform vec3 cameraPos;
uniform samplerCube skybox;
void main()
{
float ratio=1.00/1.52;
vec3 I=normalize(Position-cameraPos);
vec3 R=refract(I,normalize(Normal),ratio);//计算的方式变成refract
FragColor=vec4(texture(skybox,R).rgb,1.0);
}

输出效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值