OpenGL——绘制三角形和矩形

顶点着色器为片段着色器决定颜色,在顶点着色器中声明了一个vertexColor变量作为vec4输出,并在片段着色器中声明了一个类似的vertexColor。由于它们名字相同且类型相同,片段着色器中的vertexColor就和顶点着色器中的vertexColor链接了。

//顶点着色器
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"out vec4 vertexColor;\n"
"void main()\n"
"{\n"
//gl_Position:没有类型in、out或是uniform的声明,而是直接使用,且在后面的程序中也未被引用。
//原来它是默认是归一化的裁剪空间坐标,xyz各个维度的范围为-1到1,仅能在顶点着色器中使用,既是输入也是输出。
//gl_Position赋值范围就是float的取值范围(32位),只不过只有[-1,1]区间的片元被绘制。
//它是vec4类型的,不能重声明为dvec4等类型。
//gl_Position可以通过视角划分转换为标准化设备空间中的笛卡尔坐标
"  gl_Position = vec4(aPos, 1.0); "
"  vertexColor = vec4(0.5, 0.0, 0.0, 1.0); "
"}\0";

//片段着色器
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec4 vertexColor;\n "
"void main()\n"
"{\n"
"   FragColor = vertexColor;\n"
"}\n\0";

完整绘制代码:

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);

// 设置窗口宽高
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

//顶点着色器
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"out vec4 vertexColor;\n"
"void main()\n"
"{\n"
//gl_Position:没有类型in、out或是uniform的声明,而是直接使用,且在后面的程序中也未被引用。
//原来它是默认是归一化的裁剪空间坐标,xyz各个维度的范围为-1到1,仅能在顶点着色器中使用,既是输入也是输出。
//gl_Position赋值范围就是float的取值范围(32位),只不过只有[-1,1]区间的片元被绘制。
//它是vec4类型的,不能重声明为dvec4等类型。
//gl_Position可以通过视角划分转换为标准化设备空间中的笛卡尔坐标
"  gl_Position = vec4(aPos, 1.0); "
"  vertexColor = vec4(0.5, 0.0, 0.0, 1.0); "
"}\0";

//片段着色器
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"in vec4 vertexColor;\n "
"void main()\n"
"{\n"
"   FragColor = vertexColor;\n"
"}\n\0";

//顶点数组对象:Vertex Array Object,VAO
//顶点缓冲对象:Vertex Buffer Object,VBO
//索引缓冲对象:Element Buffer Object,EBO或Index Buffer Object,IBO

int main()
{

	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif


	// 创建窗口
	GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
	if (window == NULL)
	{
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	glfwMakeContextCurrent(window);
	//每当窗口调整大小的时候调用这个函数
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);


	//glad
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}



	// 创建顶点着色器
	unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	glCompileShader(vertexShader);
	// 检查是否成功
	int success;
	char infoLog[512];
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	//创建片段着色器
	unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);
	// 检查是否成功
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	}
	// 创建着色器程序,链接顶点着色器和片段着色器
	unsigned int shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);
	// 检查是否成功
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}
	//着色器对象链接到程序对象以后,删除着色器对象
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);



	// 指定三角形的三个顶点位置
	float vertices1[] = {
		-1.0f, 0.0f, 0.0f, // left  
		0.0f, 0.0f, 0.0f, // right 
		-0.5f,  0.5f, 0.0f  // top   
	};

	float vertices2[] = {
		0.5f, 0.0f, 0.0f,   // 右上角
		0.5f, -0.5f, 0.0f,  // 右下角
		0.0f, -0.5f, 0.0f, // 左下角
		0.0f, 0.0f, 0.0f   // 左上角
	};
	//矩形绘制索引
	unsigned int indices[] = { // 注意索引从0开始! 
		0, 1, 3, // 第一个三角形
		1, 2, 3  // 第二个三角形
	};

	float vertices[] = {
		//矩形
		0.5f, 0.0f, 0.0f,   // 右上角
		0.5f, -0.5f, 0.0f,  // 右下角
		0.0f, -0.5f, 0.0f, // 左下角
		0.0f, 0.0f, 0.0f,  // 左上角
		//三角形
		-1.0f, 0.0f, 0.0f, // left  
		0.0f, 0.0f, 0.0f, // right 
		-0.5f,  0.5f, 0.0f  // top   
	};

	//创建VBO VAO对象
	unsigned int VBO, VAO, EBO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);  
	glGenBuffers(1, &EBO);

	// 首先绑定顶点数组对象,然后绑定并设置顶点缓冲区,然后配置顶点属性。
	glBindVertexArray(VAO);

	// 顶点数组复制到一个顶点缓冲中,供OpenGL使用
	glBindBuffer(GL_ARRAY_BUFFER, VBO);//所有GL_ARRAY_BUFFER上的顶点数据都绑定到VBO上管理
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//将顶点数据复制到缓存内存中
	//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

	// 复制索引数组到一个索引缓冲中,供OpenGL使用
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	//设置顶点属性指针
	//每个顶点属性从一个VBO管理的内存中获得它的数据,而具体是从哪个VBO(程序中可以有多个VBO)获取,
	//则是通过在调用glVertexAttribPointer时绑定到GL_ARRAY_BUFFER的VBO决定的。
	//由于在调用glVertexAttribPointer之前绑定的是先前定义的VBO对象,顶点属性0现在会链接到它的顶点数据。
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); //0也可以,因为顶点是紧密型

	//以顶点属性位置值作为参数,启用顶点属性
	glEnableVertexAttribArray(0);

	// 解除绑定
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	// 解除绑定
	glBindVertexArray(0);

	// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

	// 调用以绘制线框多边形
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);


	//渲染循环,GLFW退出前一直保持运行
	while (!glfwWindowShouldClose(window))
	{
		// 输入
		processInput(window);

		//渲染指令
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//设置颜色
		glClear(GL_COLOR_BUFFER_BIT);//状态设置

	    // 绘制
		glUseProgram(shaderProgram);
		glBindVertexArray(VAO);  // 只有一个VAO,没有必要每次都绑定,但是这样更有条理
		//绘制三角形
		glDrawArrays(GL_TRIANGLES, 4, 3);//从数组的第五个顶点开始绘制
		//绘制矩形
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		// 交换颜色缓冲,储存着GLFW窗口每一个像素颜色值的大缓冲,迭代中用来绘制
		glfwSwapBuffers(window);
		//检查有没有触发什么事件,比如键盘输入、鼠标移动等
		glfwPollEvents();
	}


	// 可选:一旦资源超出其用途,则取消分配所有资源
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &EBO);
	glDeleteProgram(shaderProgram);



	// 清除分配的所以glfw资源
	glfwTerminate();

return 0;
}



// 输入控制,检查按键是否正在被按下
void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)  // 以Esc为例
		glfwSetWindowShouldClose(window, true);
}


// 每当窗口大小改变时(通过操作系统或用户调整大小),这个回调函数就会执行
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	//确保视口与新窗口尺寸匹配;注意宽度和高度将明显大于视网膜显示器上指定的高度。
	glViewport(0, 0, width, height);
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值