[OpenGL]绘制三角形 完整代码 (函数的声明与实现分开)。
各分块功能包装成函数,更显简单有条理
//=main.cpp==
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include"common.h"
#include"shader_common.h"
#include "draw_triangle.h"
#include <iostream>
int main(void)
{
draw_trangle();
return 0 ;
}
//common.h=
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#ifndef COMMON_H
#define COMMON_H
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void init_opengl();
#endif
//=common.cpp=
#include"common.h"
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
***//下面的WIDTH,HEIGHT,WINDOW 只能在此文件中声明,不能在common.h中声明。否则出错。***
const GLuint WIDTH = 800, HEIGHT = 600;
GLFWwindow* window;
void init_opengl()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
glfwMakeContextCurrent(window);
gladLoadGL();
glfwSetFramebufferSizeCallback(window,framebuffer_size_callback);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}
//=draw_triangle.h==
#ifndef DRAW_TRIANGLE_H
#define DRAW_TRIANGLE_H
#include "shader_common.h"
int draw_trangle();
#endif
//=draw_triangle.cpp==
#include "shader_common.h"
// 使用extern关键字声明全局变量
extern GLFWwindow* window;
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int draw_trangle()
{
// 初始化 OpenGL
init_opengl();
// 编译和链接着色器
GLuint shaderProgram = compile_shader(vertexShaderSource, fragmentShaderSource);
// 顶点数据
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f, // Left
0.5f, -0.5f, 0.0f, // Right
0.0f, 0.5f, 0.0f // Top
};
// 申请缓冲区
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// 绑定VAO,表示
glBindVertexArray(VAO);
// 提交数据
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 使用Buffer中的数据在 VAO 生成 0 号顶点属性的指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
// 启用 0 号顶点属性
glEnableVertexAttribArray(0);
// 解绑VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 解绑VAO
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
processInput(window);
// 清屏
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 指定着色器程序
glUseProgram(shaderProgram);
// 绑定VAO
glBindVertexArray(VAO);
// 绘制指令
glDrawArrays(GL_TRIANGLES, 0, 3);
// 解绑 VAO
glBindVertexArray(0);
// 双缓冲交换
glfwSwapBuffers(window);
// 处理事件
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glfwTerminate();
return 0;
}
//=shader_common.h=
#ifndef SHADER_COMMON_H
#define SHADER_COMMON_H
#include "common.h"
GLuint compile_shader(const GLchar* vertexShaderSource, const GLchar* fragmentShaderSource);
#endif
//=shader_common.cpp=
#include "common.h"
GLuint compile_shader(const GLchar* vertexShaderSource, const GLchar* fragmentShaderSource)
{
// 创建顶点着色器
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
// 指定着色器代码
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
// 编译顶点着色器,检查并提示编译结果
glCompileShader(vertexShader);
GLint success;
GLchar 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;
}
// 创建片段着色器
GLuint 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;
}
// 创建着色器程序
GLuint 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);
return shaderProgram;
}