cpp
复制代码
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <stdexcept>
// 函数声明
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void checkShaderCompileStatus(unsigned int shader, const std::string& type);
void checkProgramLinkStatus(unsigned int program);
// 着色器源代码
const char* vertexShaderSource = R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor;
gl_PointSize = 20.0f;
}
)";
const char* fragmentShaderSource = R"(
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0f);
}
)";
int main()
{
// 初始化 GLFW
if (!glfwInit()) {
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
// 配置 GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// 创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);
if (!window) {
std::cerr << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// 初始化 GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cerr << "Failed to initialize GLAD" << std::endl;
glfwTerminate();
return -1;
}
// 配置全局 OpenGL 状态
glViewport(0, 0, 800, 600);
glEnable(GL_PROGRAM_POINT_SIZE);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // 深灰色背景
// 定义顶点数据
float vertices[] = {
// 位置 // 颜色
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 右下 - 红色
-0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 左下 - 绿色
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f // 顶部 - 蓝色
};
// 创建并配置 VAO 和 VBO
unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 颜色属性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 解绑 VAO (不是必须的,但良好的习惯)
glBindVertexArray(0);
// 创建并编译着色器
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
checkShaderCompileStatus(vertexShader, "VERTEX");
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
checkShaderCompileStatus(fragmentShader, "FRAGMENT");
// 创建着色器程序并链接
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
checkProgramLinkStatus(shaderProgram);
// 删除着色器对象 (已链接到程序中,不再需要)
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// 主渲染循环
while (!glfwWindowShouldClose(window)) {
// 输入处理
processInput(window);
// 渲染
glClear(GL_COLOR_BUFFER_BIT);
// 绘制三角形
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
// 交换缓冲区和轮询事件
glfwSwapBuffers(window);
glfwPollEvents();
}
// 清理资源
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
glfwTerminate();
return 0;
}
// 回调函数定义
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// 着色器编译错误检查
void checkShaderCompileStatus(unsigned int shader, const std::string& type)
{
int success;
char infoLog[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "ERROR::SHADER::" << type << "::COMPILATION_FAILED\n"
<< infoLog << std::endl;
}
}
// 程序链接错误检查
void checkProgramLinkStatus(unsigned int program)
{
int success;
char infoLog[512];
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(program, 512, nullptr, infoLog);
std::cerr << "ERROR::PROGRAM::LINKING_FAILED\n"
<< infoLog << std::endl;
}
}