欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL学习(二)绘制一个三角形

程序员文章站 2023-12-25 12:04:09
...

参考官方文档:https://learnopengl-cn.github.io/

首先,这个过程相当繁琐,需要做好思想准备。

首先先看源代码:

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

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}
//用着色器语言GLSL编写顶点着色器,然后编译它,下面是一个非常基础的GLSL顶点着色器的源代码
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"
"}\0";
//片段着色器,计算像素最后的颜色输出
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\0";

int main() {
	//initialize
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	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);
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GlAD" << std::endl;
		return -1;
	}
	//编译着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//编译片段着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//着色器程序。要使用前面编译的着色器我们必须把它们链接为一个着色器程序对象,然后再渲染对象时**这个着色器程序。
	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 vertices[] = {
		-0.5f,-0.5f,0.0f,
		0.5f,-0.5f,0.0f,
		0.0f,-0.5f,0.0f,
		0.0f,0.5f,0.0f
	};
	unsigned int indices[] = {
		0,1,3,
		1,2,3
	};
	//顶点数组对象VAO,创建
	unsigned int VBO, VAO, EBO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	//索引缓冲对象
	glGenBuffers(1, &EBO);
	//绑定VAO
	glBindVertexArray(VAO);
	//把顶点数组复制到缓冲*OpenGL使用
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),vertices,GL_STATIC_DRAW);
	//绑定EBO然后把索引复制到缓冲里
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,GL_STATIC_DRAW);
	//链接顶点属性,第一个参数为顶点属性的位置值location,
	//第二个参数为顶点属性的大小,顶点属性是一个vec3,所以大小为3
	//第三个参数指定数据的类型,这里为GL_FLOAT
	//第四个参数定义我们是否希望数据被标准化,
	//第五个参数为步长,告诉我们在连续的顶点属性组之间的间隔。由于我们知道这个数组是紧密排列的,
	//我们可以设置为0来让OpenGL来决定具体步长
	//最后一个参数类型是void*,表示位置数据在缓冲中起始位置的偏移量。由于位置数据在数组的开头,所以这里是0
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,3 * sizeof(float), (void*)0);

	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindVertexArray(0);


	glViewport(0, 0, 800, 600);
	void framebuffer_size_callback(GLFWwindow * window, int width, int height);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
	while (!glfwWindowShouldClose(window))
	{
		processInput(window);

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		//**着色器程序对象
		glUseProgram(shaderProgram);

		glBindVertexArray(VAO);
		//使用当前绑定的索引缓冲对象中的索引进行绘制
		//其中的参数分别是:绘制的模式、绘制顶点的个数、索引的类型和指定EBO中的偏移量,
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		glfwSwapBuffers(window);//交换颜色缓冲,它在每一次迭代中被用来绘制,并作为输出显示在屏幕上
		glfwPollEvents();//检测有没有触发什么事件、更新窗口状态,并调用对应的回调函数
	}
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &EBO);
	glDeleteProgram(shaderProgram);
	glfwTerminate();
	return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

上面的代码中各步骤都给出了相关注释。这些概念要理解起来都是有难度的。只能先知道这回事。
OpenGL学习(二)绘制一个三角形

将代码中的float数组修改为:

float vertices[] = {
		0.5f,  0.5f, 0.0f,  // top right
		 0.5f, -0.5f, 0.0f,  // bottom right
		-0.5f, -0.5f, 0.0f,  // bottom left
		-0.5f,  0.5f, 0.0f   // top left 
	};

后窗口中绘制的图形变为正方形
OpenGL学习(二)绘制一个三角形

添加代码使用线框模式:glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);绘制的图形可以看出这个矩阵是由两个三角形组成的:
OpenGL学习(二)绘制一个三角形

练习:

  1. 添加更多顶点到数据中,使用glDrawArrays,尝试绘制两个彼此相连的三角形。
#include<iostream>
#include<glad/glad.h>
#include<GLFW/glfw3.h>

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}
//用着色器语言GLSL编写顶点着色器,然后编译它,下面是一个非常基础的GLSL顶点着色器的源代码
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"
"}\0";
//片段着色器,计算像素最后的颜色输出
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\0";

int main() {
	
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	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);
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GlAD" << std::endl;
		return -1;
	}
	//编译着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//编译片段着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//着色器程序。要使用前面编译的着色器我们必须把它们链接为一个着色器程序对象,然后再渲染对象时**这个着色器程序。
	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 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
	};/*float vertices[] = {
		-0.5f,-0.5f,0.0f,
		0.5f,-0.5f,0.0f,
		0.0f,-0.5f,0.0f,
		0.0f,0.5f,0.0f
	};*/
	unsigned int indices[] = {
		0,1,3,
		1,2,3
	};
	//顶点数组对象VAO,创建
	unsigned int VBO, VAO, EBO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	//索引缓冲对象
	// glGenBuffers(1, &EBO);
	//绑定VAO
	glBindVertexArray(VAO);
	//把顶点数组复制到缓冲*OpenGL使用
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),vertices,GL_STATIC_DRAW);
	//绑定EBO然后把索引复制到缓冲里
	// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices,GL_STATIC_DRAW);
	//链接顶点属性,第一个参数为顶点属性的位置值location,
	//第二个参数为顶点属性的大小,顶点属性是一个vec3,所以大小为3
	//第三个参数指定数据的类型,这里为GL_FLOAT
	//第四个参数定义我们是否希望数据被标准化,
	//第五个参数为步长,告诉我们在连续的顶点属性组之间的间隔。由于我们知道这个数组是紧密排列的,
	//我们可以设置为0来让OpenGL来决定具体步长
	//最后一个参数类型是void*,表示位置数据在缓冲中起始位置的偏移量。由于位置数据在数组的开头,所以这里是0
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,3 * sizeof(float), (void*)0);

	glEnableVertexAttribArray(0);

	glBindBuffer(GL_ARRAY_BUFFER, 0);

	glBindVertexArray(0);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	glViewport(0, 0, 800, 600);
	void framebuffer_size_callback(GLFWwindow * window, int width, int height);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	while (!glfwWindowShouldClose(window))
	{
		processInput(window);

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		//**着色器程序对象
		glUseProgram(shaderProgram);

		glBindVertexArray(VAO);
		//glDrawElements
		//使用当前绑定的索引缓冲对象中的索引进行绘制
		//其中的参数分别是:绘制的模式、绘制顶点的个数、索引的类型和指定EBO中的偏移量,
		// glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
		//glDrawArrays
		//其中的参数分别为:绘制的图元类型,顶点数组的起始索颖,和打算绘制多少个顶点
		glDrawArrays(GL_TRIANGLES, 0,6);
		glfwSwapBuffers(window);//交换颜色缓冲,它在每一次迭代中被用来绘制,并作为输出显示在屏幕上
		glfwPollEvents();//检测有没有触发什么事件、更新窗口状态,并调用对应的回调函数
	}
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	glDeleteBuffers(1, &EBO);
	glDeleteProgram(shaderProgram);
	glfwTerminate();
	return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

OpenGL学习(二)绘制一个三角形

  1. 创建相同的两个三角形,但它们的数据使用不同的VAO和VBO

(这个问题还是不简单的,为了避免出错我直接看答案了,还是能理解)

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

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}
//用着色器语言GLSL编写顶点着色器,然后编译它,下面是一个非常基础的GLSL顶点着色器的源代码
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"
"}\0";
//片段着色器,计算像素最后的颜色输出
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\0";

int main() {
	
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	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);
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GlAD" << std::endl;
		return -1;
	}
	//编译着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//编译片段着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//着色器程序。要使用前面编译的着色器我们必须把它们链接为一个着色器程序对象,然后再渲染对象时**这个着色器程序。
	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 firstTriangle[] = {
		-0.9f, -0.5f, 0.0f,  // left 
		-0.0f, -0.5f, 0.0f,  // right
		-0.45f, 0.5f, 0.0f,  // top 
	};
	float secondTriangle[] = {
		0.0f, -0.5f, 0.0f,  // left
		0.9f, -0.5f, 0.0f,  // right
		0.45f, 0.5f, 0.0f   // top 
	};
	
	//顶点数组对象VAO,创建
	unsigned int VBOs[2], VAOs[2];
	glGenVertexArrays(2, VAOs);
	glGenBuffers(2,VBOs);
	
	glBindVertexArray(VAOs[0]);
	//把顶点数组复制到缓冲*OpenGL使用
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle),firstTriangle,GL_STATIC_DRAW);
	
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	glBindVertexArray(VAOs[1]);
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	//glBindVertexArray(0);
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	


	glViewport(0, 0, 800, 600);
	void framebuffer_size_callback(GLFWwindow * window, int width, int height);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	while (!glfwWindowShouldClose(window))
	{
		processInput(window);

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		//**着色器程序对象
		glUseProgram(shaderProgram);

		glBindVertexArray(VAOs[0]);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		glBindVertexArray(VAOs[1]);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		
		glfwSwapBuffers(window);//交换颜色缓冲,它在每一次迭代中被用来绘制,并作为输出显示在屏幕上
		glfwPollEvents();//检测有没有触发什么事件、更新窗口状态,并调用对应的回调函数
	}
	glDeleteVertexArrays(1, VAOs);
	glDeleteBuffers(1, VBOs);
	//glDeleteBuffers(1, &EBO);
	glDeleteProgram(shaderProgram);
	glfwTerminate();
	return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

OpenGL学习(二)绘制一个三角形

  1. 创建两个着色器程序,第二个程序使用一个不同的片段着色器,输出黄色;再次绘制这两个三角形,让其中一个输出为黄色。
#include<iostream>
#include<glad/glad.h>
#include<GLFW/glfw3.h>

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}
//用着色器语言GLSL编写顶点着色器,然后编译它,下面是一个非常基础的GLSL顶点着色器的源代码
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"
"}\0";
//片段着色器,计算像素最后的颜色输出
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\0";
const char* fragmentShaderSource2 = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";

int main() {
	
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
	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);
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GlAD" << std::endl;
		return -1;
	}
	//编译着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//编译片段着色器
	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::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}
	//第二个
	int fragMentShader2 = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragMentShader2, 1, &fragmentShaderSource2, NULL);
	glCompileShader(fragMentShader2);
	glGetShaderiv(fragMentShader2, GL_COMPILE_STATUS, &success);
	if (!success) {
		glGetShaderInfoLog(fragMentShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILEATION_FAILED\n" << infoLog << std::endl;
	}

	//着色器程序。要使用前面编译的着色器我们必须把它们链接为一个着色器程序对象,然后再渲染对象时**这个着色器程序。
	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;
	}
	//第二个着色器程序
	int shaderProgram2 = glCreateProgram();
	glAttachShader(shaderProgram2, vertexShader);
	glAttachShader(shaderProgram2, fragMentShader2);
	glLinkProgram(shaderProgram2);
	glGetProgramiv(shaderProgram2, 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);
	glDeleteShader(fragMentShader2);
	//顶点输入
	float firstTriangle[] = {
		-0.9f, -0.5f, 0.0f,  // left 
		-0.0f, -0.5f, 0.0f,  // right
		-0.45f, 0.5f, 0.0f,  // top 
	};
	float secondTriangle[] = {
		0.0f, -0.5f, 0.0f,  // left
		0.9f, -0.5f, 0.0f,  // right
		0.45f, 0.5f, 0.0f   // top 
	};
	
	//顶点数组对象VAO,创建
	unsigned int VBOs[2], VAOs[2];
	glGenVertexArrays(2, VAOs);
	glGenBuffers(2,VBOs);
	
	glBindVertexArray(VAOs[0]);
	//把顶点数组复制到缓冲*OpenGL使用
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle),firstTriangle,GL_STATIC_DRAW);
	
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	glBindVertexArray(VAOs[1]);
	glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(secondTriangle), secondTriangle, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);

	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	//glBindVertexArray(0);
	//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	


	glViewport(0, 0, 800, 600);
	void framebuffer_size_callback(GLFWwindow * window, int width, int height);
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	while (!glfwWindowShouldClose(window))
	{
		processInput(window);

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
		//**着色器程序对象
		glUseProgram(shaderProgram);

		glBindVertexArray(VAOs[0]);
		glDrawArrays(GL_TRIANGLES, 0, 3);

		glUseProgram(shaderProgram2);
		glBindVertexArray(VAOs[1]);
		glDrawArrays(GL_TRIANGLES, 0, 3);
		
		glfwSwapBuffers(window);//交换颜色缓冲,它在每一次迭代中被用来绘制,并作为输出显示在屏幕上
		glfwPollEvents();//检测有没有触发什么事件、更新窗口状态,并调用对应的回调函数
	}
	glDeleteVertexArrays(1, VAOs);
	glDeleteBuffers(1, VBOs);
	//glDeleteBuffers(1, &EBO);
	glDeleteProgram(shaderProgram);
	glDeleteProgram(shaderProgram2);
	glfwTerminate();
	return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

OpenGL学习(二)绘制一个三角形

上一篇:

下一篇: