/*引入OpneGL方法库头文件*/
#include <glad/glad.h>
#include <GLFW/glfw3.h>
/*引入文件里头文件,方便我们调用方法进行问题检查*/
#include <iostream>
/*视口变换回调函数*/
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
/*输入设置,比如按下Esc键关闭窗口*/
void player_input(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
/*顶点Shader源码*/
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";
/*片元Shader源码*/
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 finalColor;\n"
"void main()\n"
"{\n"
"finalColor = vec4(1.0);\n"
"}\0";
/*声明屏幕的宽度和高度,分别为800和600*/
const unsigned int Screen_Width = 800;
const unsigned int Screen_Height = 600;
/*主函数*/
int main()
{
/*初始化GLFW*/
glfwInit();
/*此函数基于OpenGL 3.3版本展开,需要告诉GLFW我们要使用的OpenGL版本是3.3,这样GLFW会在创建OpenGL上下文时做出适当的调整。
这也可以确保用户在没有适当的OpenGL版本支持的情况下无法运行。将主版本号(Major)和次版本号(Minor)都设为3。同样你可以修改它们的版本*/
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
/*我们明确告诉GLFW我们使用的是核心模式(Core-profile)
明确告诉GLFW我们需要使用核心模式意味着我们只能使用OpenGL功能的一个子集(没有我们已不再需要的向后兼容特性)。*/
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* 如果使用的是Mac OS X系统,还需要加下面这行代码到你的初始化代码中这些配置才能起作用*/
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif
/*设置窗口对象 */
GLFWwindow *window = glfwCreateWindow(Screen_Width, Screen_Height, "LearOpenGLWidnow", NULL, NULL);
/*如果窗口对象创建失败,在终端输出日志,并且释放内存*/
if (window == NULL)
{
std::cout << "Fail to create window !" << std::endl;
glfwTerminate();
return -1;
}
/*窗口对象创建成功,使用这个窗口 */
glfwMakeContextCurrent(window);
/*窗口大小变换回调*/
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
/*检测是否加载所有glad方法库的函数 */
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Fail to initialize glad !" << std::endl;
return -1;
}
/*构建编译顶点Shader*/
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, sizeof(infoLog), NULL, infoLog);
std::cout << "Error:Shader:VertexShader:Compile_Status_Failure" << infoLog << std::endl;
return -1;
}
/*构建编译片元Shader*/
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
/*检查是否构建编译成功*/
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, sizeof(infoLog), NULL, infoLog);
std::cout << "Error:Shader:FragmentShader:Compile_Status_Failure" << infoLog << std::endl;
return -1;
}
/*链接顶点Shader和片元Shader组成Shader进程 */
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
/*检查是否链接成功*/
glGetProgramiv(shaderProgram, GL_LINE, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, sizeof(infoLog), NULL, infoLog);
std::cout << "Error:Program:Link:Link_Fialure" << infoLog << std::endl;
return -1;
}
/*删除顶点Shader与片元Shader内存*/
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
/*设置三角形顶点数据 */
float vertexts[]{
-0.5f, -0.5f, 0.0f, // 左顶点
0.5f, -0.5f, 0.0f, // 右顶点
0.0f, 0.5f, 0.0f // 上顶点
};
/*声明顶点缓冲物体(Vertex Buffer Object)id与顶点数组物体(Vertex Array Objet)id*/
unsigned int VBO, VAO;
/*生成顶点数组 */
glGenVertexArrays(1, &VAO);
/*生成顶点缓冲区*/
glGenBuffers(1, &VBO);
/*先绑定顶点数组,在绑定和设置缓冲区,然后绑定顶点属性*/
/*绑定顶点数组*/
glBindVertexArray(VAO);
/*绑定缓冲区数据*/
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexts), vertexts, GL_STATIC_DRAW);
/*绑定顶点属性*/
/*第一个参数指代的是顶点Shader中location=0的0,是一个id而不是值
第二个参数指代顶点属性的大小,这里只有位置,为vec3,它是由3个值组成
第三个参数指代数据的类型,vec在OpenGL中为float类型
第四个参数指代是否归一化
第五个参数指代第二个属性数显的步长,简单说就是从这个属性第二次出现的地方到整个数组0位置之间有多少字节
第六个参数为位置数据在缓冲中起始位置的偏移量(Offset)。由于位置数据在数组的开头,所以这里是0*/
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0);
/*以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的*/
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
/*当窗口没有被关闭时,执行渲染循环 */
while (!glfwWindowShouldClose(window))
{
/* code */
/*按键输入以及对应操作事件*/
player_input(window);
/*渲染*/
/*清除颜色缓冲区*/
glClear(GL_COLOR_BUFFER_BIT);
/*使用Shader进程*/
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
/*绘制顶点数据*/
glDrawArrays(GL_TRIANGLES, 0, 3);
/*交换缓存区 */
glfwSwapBuffers(window);
/*执行事件 */
glfwPollEvents();
}
/*删除对象,缓存,进程*/
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
/*退出循环后释放内存*/
glfwTerminate();
return 0;
}
