最后效果:
OpenGL version: 4.1 Metal
不知道为啥必须使用VAO 才行。
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
void processInput(GLFWwindow *window);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
const char *vertexShaderSource = R"(
#version 100
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
}
)";
const char *fragmentShaderSource = R"(
#version 100
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // Red color
}
)";
GLuint compileShader(GLenum type, const char *source)
{
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, nullptr);
glCompileShader(shader);
GLint compiled;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
{
GLint infoLen;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
std::vector<char> infoLog(infoLen);
glGetShaderInfoLog(shader, infoLen, nullptr, infoLog.data());
std::cerr << "Error compiling shader: " << infoLog.data() << std::endl;
glDeleteShader(shader);
return 0;
}
return shader;
}
GLuint createProgram(const char *vertexSource, const char *fragmentSource)
{
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexSource);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentSource);
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
GLint linked;
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if (!linked)
{
GLint infoLen;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
std::vector<char> infoLog(infoLen);
glGetProgramInfoLog(program, infoLen, nullptr, infoLog.data());
std::cerr << "Error linking program: " << infoLog.data() << std::endl;
glDeleteProgram(program);
return 0;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return program;
}
int main()
{
// glfw: initialize and configure
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
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);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
GLuint program = createProgram(vertexShaderSource, fragmentShaderSource);
glUseProgram(program);
if (glGetError() != GL_NO_ERROR)
{
std::cerr << "Error in glUseProgram." << std::endl;
}
// Define vertex data
GLfloat vertices[] = {
0.0f, 0.5f, // Vertex 1
-0.5f, -0.5f, // Vertex 2
0.5f, -0.5f // Vertex 3
};
// 创建 VAO 并绑定
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and bind vertex buffer (VBO)
GLuint vbo;
glGenBuffers(1, &vbo);
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
std::cerr << "Error during drawing 1: " << error << std::endl;
}
glBindBuffer(GL_ARRAY_BUFFER, vbo);
error = glGetError();
if (error != GL_NO_ERROR)
{
std::cerr << "Error during drawing 2: " << error << std::endl;
}
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
error = glGetError();
if (error != GL_NO_ERROR)
{
std::cerr << "Error during drawing 3: " << error << std::endl;
}
// Get the location of the attribute
GLint aPositionLocation = glGetAttribLocation(program, "a_position");
if (aPositionLocation == -1)
{
std::cerr << "Error: Attribute 'a_position' not found in shader." << std::endl;
return -1;
}
glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid *)0);
glEnableVertexAttribArray(aPositionLocation);
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
std::cerr << "OpenGL error: " << err << std::endl;
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Get OpenGL version
const char *version = (const char *)glGetString(GL_VERSION);
std::cout << "OpenGL version: " << version << std::endl;
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLenum drawError = glGetError();
glBindVertexArray(vao);
glUseProgram(program);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
// Cleanup
glDeleteBuffers(1, &vbo);
glfwTerminate();
return 0;
}
void processInput(GLFWwindow *window)
{
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);
}