(十七)深度检测

在opengl中,绘制两个三角形,一般都是后画遮盖住先画的,那么如何达到近处的遮挡远处的效果呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <glad/glad.h>//glad必须在glfw头文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

//GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/string_cast.hpp>

void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}

GLuint program = 0;
GLuint vao = 0;

glm::mat4 transformGoku(1.0f);
glm::mat4 transformLuffy(1.0f);

GLuint textureGoku = 0;
GLuint textureLuffy = 0;

glm::mat4 viewMatrix(1.0f);
glm::mat4 perspectiveMatrix(1.0f);
void prepareCamera()
{
	//lookat:生成一个viewMatrix
	//eye:当前摄像机所在的位置
	//center:当前摄像机看向的那个点
	//up:穹顶向量
	viewMatrix = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
}

void preparePerspective()
{
	//fovy:y轴方向的视张角,弧度单位
	//aspect:近平面的横纵百分比
	//near:近平面距离
	//far:远平面距离
	perspectiveMatrix = glm::perspective(glm::radians(60.0f), 800.0f / 600, 0.1f, 1000.0f);
}
void prepareVAO()
{
	//positions
	float positions[] = {
		-1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		0.0f,  1.0f, 0.0f,
	};
	//颜色
	float colors[] = {
		-1.0f, 0.0f, 0.0f,
		1.0f, 0.0f, 0.0f,
		0.0f,  1.0f, 0.0f,
	};
	//索引
	unsigned int indices[] = {
		0, 1, 2,
	};
	//uv坐标
	float uvs[] = {
		0.0f, 0.0f,
		1.0f, 0.0f,
		0.5f, 1.0f,
	};

	//2 VBO创建
	GLuint posVbo = 0;
	GLuint colorVbo = 0;
	GLuint uvVbo = 0;
	glGenBuffers(1, &posVbo);
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);

	glGenBuffers(1, &colorVbo);
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);

	glGenBuffers(1, &uvVbo);
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);

	//3 EBO创建
	GLuint ebo = 0;
	glGenBuffers(1, &ebo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//4 VAO创建
	vao = 0;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	//5 绑定vbo ebo 加入属性描述信息
	//5.1 加入位置属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, posVbo);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.2 加入颜色属性描述信息
	glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);

	//5.3 加入uv属性描述数据
	glBindBuffer(GL_ARRAY_BUFFER, uvVbo);
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);

	//5.2 加入ebo到当前的vao
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

	glBindVertexArray(0);
}
void prepareShader() {
	//1 完成vs与fs的源代码,并且装入字符串
	//aPos作为attribute(属性)传入shader不允许更改的
	const char* vertexShaderSource =
		"#version 330 core\n"
		"layout (location = 0) in vec3 aPos;\n"
		"layout (location = 1) in vec3 aColor;\n"
		"layout (location = 2) in vec2 aUV;\n"
		"out vec3 color;\n"
		"out vec2 uv;\n"
		"uniform mat4 transform;\n"
		"uniform mat4 viewMatrix;\n"
		"uniform mat4 perspectiveMatrix;\n"
		"void main()\n"
		"{\n"
		"   vec4 position = vec4(aPos, 1.0);\n"
		"   position = perspectiveMatrix * viewMatrix * transform * position;\n"
		"   gl_Position = position;\n"
		"   color = aColor;\n"
		"   uv = aUV;\n"
		"}\0";
	const char* fragmentShaderSource =
		"#version 330 core\n"
		"out vec4 FragColor;\n"
		"in vec3 color;\n"
		"in vec2 uv;\n"
		"uniform sampler2D sampler;\n"
		"void main()\n"
		"{\n"
		"   FragColor = texture(sampler, uv);\n"
		"}\n\0";


	//2 创建Shader程序(vs、fs)
	GLuint vertex, fragment;
	vertex = glCreateShader(GL_VERTEX_SHADER);
	fragment = glCreateShader(GL_FRAGMENT_SHADER);


	//3 为shader程序输入shader代码
	glShaderSource(vertex, 1, &vertexShaderSource, NULL);
	glShaderSource(fragment, 1, &fragmentShaderSource, NULL);

	int success = 0;
	char infoLog[1024];
	//4 执行shader代码编译 
	glCompileShader(vertex);
	//检查vertex编译结果
	glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(vertex, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;
	}

	glCompileShader(fragment);
	//检查fragment编译结果
	glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(fragment, 1024, NULL, infoLog);
		std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;
	}

	//5 创建一个Program壳子
	program = glCreateProgram();

	//6 将vs与fs编译好的结果放到program这个壳子里
	glAttachShader(program, vertex);
	glAttachShader(program, fragment);

	//7 执行program的链接操作,形成最终可执行shader程序
	glLinkProgram(program);

	//检查链接错误
	glGetProgramiv(program, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(program, 1024, NULL, infoLog);
		std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;
	}

	//清理
	glDeleteShader(vertex);
	glDeleteShader(fragment);
}

GLuint genTexture(const char * path,unsigned int unit)
{
	//1 stbImage 读取图片
	int width, height, channels;
	//--反转y轴
	stbi_set_flip_vertically_on_load(true);
	unsigned char* data = stbi_load(path, &width, &height, &channels, STBI_rgb_alpha);

	//2 生成纹理并且激活单元绑定
	GLuint texture = 0;
	glGenTextures(1, &texture);
	//--激活纹理单元--
	glActiveTexture(GL_TEXTURE0 + unit);
	//--绑定纹理对象--
	glBindTexture(GL_TEXTURE_2D, texture);

	//3 传输纹理数据,开辟显存
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

	//***释放数据
	stbi_image_free(data);

	//4 设置纹理的过滤方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	//5 设置纹理的包裹方式
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//u
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//v

	return texture;
}

void prepareState()
{
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);
	//glClearDepth(0.0f);
}

void prepareTexture()
{
	textureGoku = genTexture("goku.jpg", 0);
	textureLuffy = genTexture("luffy.jpg", 0);
}

void render()
{
	//执行opengl画布清理操作
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//1.绑定当前的program
	glUseProgram(program);

	//2 更新Uniform的时候,一定要先UserProgram
	//2.1 通过名称拿到Uniform变量的位置Location
	GLint location = glGetUniformLocation(program, "sampler");
	//2.2 通过Location更新Uniform变量的值
	glUniform1f(location, 0);

	GLint locationTransform = glGetUniformLocation(program, "transform");
	//transpose参数:表示是否对传输进去的矩阵数据进行转置
	glUniformMatrix4fv(locationTransform, 1, GL_FALSE, glm::value_ptr(transformLuffy));

	GLint locationviewMatrix = glGetUniformLocation(program, "viewMatrix");
	glUniformMatrix4fv(locationviewMatrix, 1, GL_FALSE, glm::value_ptr(viewMatrix));

	GLint locationperspectiveMatrix = glGetUniformLocation(program, "perspectiveMatrix");
	glUniformMatrix4fv(locationperspectiveMatrix, 1, GL_FALSE, glm::value_ptr(perspectiveMatrix));

	//先切换纹理单元,然后绑定texture对象
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureLuffy);

	//3 绑定当前的vao
	glBindVertexArray(vao);
	//4 发出绘制指令
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);

	//第二次绘制
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, textureGoku);
	transformGoku = glm::translate(glm::mat4(1.0f), glm::vec3(0.8f, 0.0f, -1.0f));
	glUniformMatrix4fv(glGetUniformLocation(program, "transform"), 1, GL_FALSE, glm::value_ptr(transformGoku));
	glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);

	glBindVertexArray(0);
}


int main()
{
	//初始化glfw环境
	glfwInit();
	//设置opengl主版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	//设置opengl次版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//设置opengl启用核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//创建窗体对象
	GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);
	//设置当前窗体对象为opengl的绘制舞台
	glfwMakeContextCurrent(window);
	//窗体大小回调
	glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);
	//键盘相应回调
	glfwSetKeyCallback(window, glfwKeyCallback);

	//使用glad加载所有当前版本opengl的函数
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "初始化glad失败" << std::endl;
		return -1;
	}
	;
	//设置opengl视口大小和清理颜色
	glViewport(0, 0, 800, 600);
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

	//shader
	prepareShader();
	//vao
	prepareVAO();
	//texture
	prepareTexture();
	prepareCamera();
	preparePerspective();
	prepareState();
	//执行窗体循环
	while (!glfwWindowShouldClose(window))
	{
		//接受并分发窗体消息
		//检查消息队列是否有需要处理的鼠标、键盘等消息
		//如果有的话就将消息批量处理,清空队列
		glfwPollEvents();
		//渲染操作
		render();
		//切换双缓存
		glfwSwapBuffers(window);
	}

	//推出程序前做相关清理
	glfwTerminate();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vegetablesssss

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值