OpenGL 入门第一课 视窗以及三角形

请查看课件教程

下面是我粗劣画的过程图
在这里插入图片描述
下面是课件中的过程图
在这里插入图片描述

在这里插入图片描述

下面是未使用索引缓冲对象(EBO)的

#define GLEW_STATIC // 这个一定要加不然报错 静态链接库
#include<iostream>
#include<GL/glew.h>
#include<GLFW/glfw3.h>
using namespace std;
void processInput(GLFWwindow);
void processInput(GLFWwindow* window) {
	//如果键盘输入esc 则触发 退出
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		// 设置 要求退出
		glfwSetWindowShouldClose(window, true);
	}
}
// 逆时针方向绘制  默认情况下,逆时针的顶点连接顺序被定义为三角形的正
// 逆时针或顺时针都是相对于观察者方向的
float vertices[] = {
	-0.5f, 0.5f, 0.0f,  // 左上角
	0.5f, -0.5f, 0.0f,  // 右下角
	0.5f, 0.5f, 0.0f,   // 右上角
	// 第二个三角形
	0.5f, -0.5f, 0.0f,  // 右下角
	-0.5f, -0.5f, 0.0f, // 左下角
	-0.5f, 0.5f, 0.0f   // 左上角
};

const char* vertexShaderSource =
"#version 330 core                                      \n"
"layout (location = 0) in vec3 aPos;                    \n"
"void main()                                            \n"
"{                                                      \n"
"    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);   \n"
"}                                                      \n";
const char* fragmentShaderSource =
"#version 330 core                            \n"
"out vec4 FragColor;                          \n"
"void main()                                  \n"
"{                                            \n"
"    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}                                            \n";

int main() {
	// 初始化GLFW
	glfwInit();
	// 提示 我们使用的版本是3.3
	// 主版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	// 次版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	// 简介
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	// 创建一个窗口对象
	GLFWwindow* window = glfwCreateWindow(800, 600, "Test window", NULL, NULL);
	if (window == NULL) {
		cout << "open window failed." << endl;
		// 终止 glfw
		glfwTerminate();
	}
	// 绑定window到上下文对象 创建完窗口我们就可以通知GLFW将我们窗口的上下文设置为当前线程的主上下文了
	glfwMakeContextCurrent(window);

	glewExperimental = true;
	// GLEW_OK 0
	//init GLEW
	if (glewInit() != GLEW_OK) {
		cout << "glew init failed." << endl;
		// 终止 glfw
		glfwTerminate();
		return -1;
	}
	// OpenGL渲染窗口的尺寸大小 
	// glViewport函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)
	glViewport(0, 0, 800, 600);

	// 设置剔除 (opegl默认正面背面都显示(不剔除))
	glEnable(GL_CULL_FACE);
	// 剔除背面 GL_BACK 剔除正面 GL_FRONT
	glCullFace(GL_BACK);

	//VAO对象
	unsigned int VAO;
	// 生成一个VAO对象 这个方法可以生成多个 由第一个参数决定
	glGenVertexArrays(1, &VAO);
	// 绑定 VAO
	glBindVertexArray(VAO);

	unsigned int VBO; //如果多个可以用 VBO[]数组 这个方法可以生成多个 由第一个参数决定
	glGenBuffers(1, &VBO);
	//将新创建的缓冲绑定到 GL_ARRAY_BUFFER目标上
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	// glBufferData 是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数
	// GL_STATIC_DRAW 数据不会或几乎不会改变。
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// 编译着色器
	unsigned int vertexShader;
	// 创建这个着色器
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	// 编译
	glCompileShader(vertexShader);

	// 片段着色器
	unsigned int fragmentShader;
	// 创建这个着色器
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	// 编译
	glCompileShader(fragmentShader);


	// 着色器程序 是将多个着色器合并之后并最终链接完成的版本
	unsigned int shaderProgram;
	// 创建一个着色器程序对象
	shaderProgram = glCreateProgram();
	// 将之前编译的着色器附加到程序对象上
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	// 用glLinkProgram链接它们
	glLinkProgram(shaderProgram);

	// glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)
	// 从 0位 开始 将数据每三个为一组 单位为float 每次跳3*float字节 偏移为0
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	// 以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的
	glEnableVertexAttribArray(0);

	//渲染循环 ,它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的渲染循环:
	//glfwWindowShouldClose 我们每次循环的开始前检查一次GLFW是否被要求退出
	while (!glfwWindowShouldClose(window)) {

		//自定义事件 当键盘触发esc 退出
		processInput(window);

		glClearColor(0.2, 0.3, 0.3, 1.0);
		// GL_COLOR_BUFFER_BIT 颜色,GL_DEPTH_BUFFER_BIT 深度 和 GL_STENCIL_BUFFER_BIT 模板
		// 清除前面的那一帧的颜色
		glClear(GL_COLOR_BUFFER_BIT);
		// 绑定 VAO 
		glBindVertexArray(VAO);
		glUseProgram(shaderProgram);
		// 画三角形 从0开始 绘制三个顶点  和VBO的顶点数据(通过VAO间接绑定)来绘制图元
		glDrawArrays(GL_TRIANGLES, 0, 6);
		//解绑VAO
		glBindVertexArray(0);


		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	// 最后终止 glfw
	glfwTerminate();
	return 0;
}

未剔除背面

在这里插入图片描述

剔除背面

在这里插入图片描述
使用EBO的

#define GLEW_STATIC // 这个一定要加不然报错 静态链接库
#include<iostream>
#include<GL/glew.h>
#include<GLFW/glfw3.h>
using namespace std;
void processInput(GLFWwindow);
void processInput(GLFWwindow* window) {
	//如果键盘输入esc 则触发 退出
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		// 设置 要求退出
		glfwSetWindowShouldClose(window, true);
	}
}
// 逆时针方向绘制  默认情况下,逆时针的顶点连接顺序被定义为三角形的正
// 逆时针或顺时针都是相对于观察者方向的
float vertices[] {
	-0.5f, 0.5f, 0.0f,  // 左上角 0 
	0.5f, -0.5f, 0.0f,  // 右下角 1
	0.5f, 0.5f, 0.0f,   // 右上角 2
	// 第二个三角形
	//0.5f, -0.5f, 0.0f,  // 右下角
	-0.5f, -0.5f, 0.0f // 左下角  3
	//-0.5f, 0.5f, 0.0f   // 左上角
};
// 使用索引来减小画点的开销 (未用索引缓冲对象时,每个点都需要画一次(即使重复了))
unsigned int indices[] {
	0,1,2, //第一个三角形的索引
	1,3,0 //第二个三角形的索引
};
const char* vertexShaderSource =
"#version 330 core                                      \n"
"layout (location = 0) in vec3 aPos;                    \n"
"void main()                                            \n"
"{                                                      \n"
"    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);   \n"
"}                                                      \n";
const char* fragmentShaderSource =
"#version 330 core                            \n"
"out vec4 FragColor;                          \n"
"void main()                                  \n"
"{                                            \n"
"    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}                                            \n";

int main() {
	// 初始化GLFW
	glfwInit();
	// 提示 我们使用的版本是3.3
	// 主版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	// 次版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	// 简介
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	// 创建一个窗口对象
	GLFWwindow* window = glfwCreateWindow(800, 600, "Test window", NULL, NULL);
	if (window == NULL) {
		cout << "open window failed." << endl;
		// 终止 glfw
		glfwTerminate();
	}
	// 绑定window到上下文对象 创建完窗口我们就可以通知GLFW将我们窗口的上下文设置为当前线程的主上下文了
	glfwMakeContextCurrent(window);

	glewExperimental = true;
	// GLEW_OK 0
	//init GLEW
	if (glewInit() != GLEW_OK) {
		cout << "glew init failed." << endl;
		// 终止 glfw
		glfwTerminate();
		return -1;
	}
	// OpenGL渲染窗口的尺寸大小 
	// glViewport函数前两个参数控制窗口左下角的位置。第三个和第四个参数控制渲染窗口的宽度和高度(像素)
	glViewport(0, 0, 800, 600);

	// 设置剔除 (opegl默认正面背面都显示(不剔除))
	glEnable(GL_CULL_FACE);
	// 剔除背面 GL_BACK 剔除正面 GL_FRONT
	glCullFace(GL_BACK);

	//VAO对象
	unsigned int VAO;
	// 生成一个VAO对象 这个方法可以生成多个 由第一个参数决定
	glGenVertexArrays(1, &VAO);
	// 绑定 VAO
	glBindVertexArray(VAO);

	unsigned int VBO; //如果多个可以用 VBO[]数组 这个方法可以生成多个 由第一个参数决定
	glGenBuffers(1, &VBO);
	//将新创建的缓冲绑定到 GL_ARRAY_BUFFER目标上
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	// glBufferData 是一个专门用来把用户定义的数据复制到当前绑定缓冲的函数
	// GL_STATIC_DRAW 数据不会或几乎不会改变。
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	unsigned int EBO;
	glGenBuffers(1, &EBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	// 编译着色器
	unsigned int vertexShader;
	// 创建这个着色器
	vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	// 编译
	glCompileShader(vertexShader);

	// 片段着色器
	unsigned int fragmentShader;
	// 创建这个着色器
	fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	// 编译
	glCompileShader(fragmentShader);


	// 着色器程序 是将多个着色器合并之后并最终链接完成的版本
	unsigned int shaderProgram;
	// 创建一个着色器程序对象
	shaderProgram = glCreateProgram();
	// 将之前编译的着色器附加到程序对象上
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	// 用glLinkProgram链接它们
	glLinkProgram(shaderProgram);

	// glVertexAttribPointer函数告诉OpenGL该如何解析顶点数据(应用到逐个顶点属性上)
	// 从 0位 开始 将数据每三个为一组 单位为float 每次跳3*float字节 偏移为0
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	// 以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的
	glEnableVertexAttribArray(0);

	//渲染循环 ,它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的渲染循环:
	//glfwWindowShouldClose 我们每次循环的开始前检查一次GLFW是否被要求退出
	while (!glfwWindowShouldClose(window)) {

		//自定义事件 当键盘触发esc 退出
		processInput(window);

		glClearColor(0.2, 0.3, 0.3, 1.0);
		// GL_COLOR_BUFFER_BIT 颜色,GL_DEPTH_BUFFER_BIT 深度 和 GL_STENCIL_BUFFER_BIT 模板
		// 清除前面的那一帧的颜色
		glClear(GL_COLOR_BUFFER_BIT);
		// 绑定 VAO 
		glBindVertexArray(VAO);
		glUseProgram(shaderProgram);
		// 画三角形 从0开始 绘制三个顶点  和VBO的顶点数据(通过VAO间接绑定)来绘制图元
		//glDrawArrays(GL_TRIANGLES, 0, 6); 这个是不用索引画的
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);//可以不需要这个 绑定VAO的同时也会自动绑定EBO
		//glDrawElements函数从当前绑定到GL_ELEMENT_ARRAY_BUFFER目标的EBO中获取索引
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
		
		//解绑VAO
		glBindVertexArray(0);


		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	// 最后终止 glfw
	glfwTerminate();
	return 0;
}

使用线框模式

加上下面那行代码就变成线框模式了

	glViewport(0, 0, 800, 600);

	// 设置剔除 (opegl默认正面背面都显示(不剔除))
	glEnable(GL_CULL_FACE);
	// 剔除背面 GL_BACK 剔除正面 GL_FRONT
	glCullFace(GL_BACK);
	// 线框模式 
	//第一个参数表示我们打算将其应用到所有的三角形的正面和背面,第二个参数告诉我们用线来绘制
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

效果
在这里插入图片描述
在这里插入图片描述

判断正背面

处理背面剔除有两个需要参考的依据,一个是正背面判断,一个是观察者位置

正背面判断:在OpenGL中默认是逆时针打点的为正面,顺时针为侧面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值