C++ OpenGL learning-create a quadrilateral

This article refers to the
opengl learning website
opengl learning website Chinese version
corresponding tutorial OpenGL homemade 3D game engine

// 创建第一个窗口
#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;

//顶点数据
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   // 左上角
};

unsigned int indices[] = {
    
     // 注意索引从0开始! 
	0, 1, 3, // 第一个三角形
	1, 2, 3  // 第二个三角形
};

//顶点着色器数据(版本号330,in代表输入,layout(location = 0)设置输入变量的位置值)
const char* vertexShaderSource =
"#version 330 core \n"
"layout (location = 0) in vec3 aPos; \n"
"void main(){\n"
"	gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);}";

//创建片段着色器(out代表输出)
const char* fragmentShaderSource =
"#version 330 core \n"
"out vec4 FragColor;\n"
"void main(){\n"
"	FragColor = vec4(1.0f,0.5f,0.2f,1.0f);}";

int main()
{
    
    
	//初始化GLFW
	glfwInit();

	//配置GLFW,glfwWindowHint的第一个参数表示要配置哪个选项,第二个参数是要设置的该配置选项的值
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	//在Mac OS X上需要添加glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);的初始化代码。
#ifdef __APPLE__
	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

	// 创建宽800,高600,名称为LearnOpenGL的窗口
	GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "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;
	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::SHADE::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	}

	//创建片段着色器
	unsigned int fragmentShader;
	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::SHADE::FRAGMENT::COMPILATION_FAILD\n" << infoLog << std::endl;
	}


	//创建程序对象
	unsigned int shaderProgram;
	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_FAILD\n" << infoLog << std::endl;
	}

	//激活程序对象
	glUseProgram(shaderProgram);

	//删除着色器
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);




	//创建顶点缓冲对象
	unsigned int VBO;
	glGenBuffers(1, &VBO);

	//创建顶点数组对象
	unsigned int VAO;
	glGenVertexArrays(1, &VAO);

	//创建索引缓冲对象:
	unsigned int EBO;
	glGenBuffers(1, &EBO);
	
	


	//绑定VAO
	glBindVertexArray(VAO);

	//将VBD绑定到GL_ARRAY_BUFFER上
	glBindBuffer(GL_ARRAY_BUFFER, VBO);



	//加载顶点数据到VBO
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


	//绑定EBO
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	//加载数据到EBO
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

	/*
	解析顶点数据的方法:
		第一个参数指定我们要配置的顶点属性,0即代表layout(location = 0)中的0,即为顶点的位置值
		第二个参数指定顶点属性的大小,vec3即为3
		第三个参数指定数据的类型,这里是GL_FLOAT
		第四个参数为是否希望数据被标准化,如果设置为GL_TRUE,所有数据都会被映射到0(对于有符号型signed数据是-1)到1之间
		第五个参数叫做步长(Stride),它告诉我们在连续的顶点属性组之间的间隔
		最后一个参数的类型是void*,所以需要进行强制类型转换,它表示位置数据在缓冲中起始位置的偏移量
	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);



	// 让窗口一直渲染
	while (!glfwWindowShouldClose(window))
	{
    
    
		//输入
		processInput(window);

		// 渲染

		//使用glClearColor指定了清除屏幕的颜色。每当我们调用glClear和clear颜色缓冲区时,整个颜色缓冲区将填充glClearColor配置的颜色即蓝绿色。
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		//准备开始绘制
		//1、使用程序对象
		glUseProgram(shaderProgram);
		//2、绑定配置好的VAO,绑定好VAO时,EBO也被绑定
		glBindVertexArray(VAO);
		//3、绘制四边形,第一个参数代表绘制三角形。第二个参数是点数,,第三个参数是索引的类型,这里是GL_UNSIGNED_INT。最后一个参数里我们可以指定EBO中的偏移量
		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

		glBindVertexArray(0);


		//glfwSwapBuffers将交换颜色缓冲区(一个大型2D缓冲区,它包含GLFW窗口中每个像素的颜色值),这个颜色缓冲区在这个渲染迭代期间用于渲染,并将其作为输出显示在屏幕上
		glfwSwapBuffers(window);

		//检查是否触发了任何事件(如键盘输入或鼠标移动事件),更新窗口状态,并调用相应的函数(可以通过回调方法注册这些函数)。
		glfwPollEvents();
	}

	// 清除所有分配的GLFW资源.
	glfwTerminate();
	return 0;
}

//  查询GLFW是否按下/释放了相关键并做出相应的反应
void processInput(GLFWwindow *window)
{
    
    
	//检查用户是否按了esc键(如果没有按,glfwGetKey返回GLFW_RELEASE)。如果用户确实按了esc键,那么我们通过使用glfwSetwindowShouldClose将其WindowShouldClose属性设置为true来关闭GLFW。主while循环的下一个条件检查将失败,应用程序将关闭。
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}


//窗口大小改变时,调用该函数
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    
    
	// 确保视窗与新的视窗尺寸相匹配
	glViewport(0, 0, width, height);
}

Output result:
Insert picture description here

Guess you like

Origin blog.csdn.net/peixin_huang/article/details/104395581