必须用现代OpenGL(3.3+核心模式),靠glDrawArrays+VBO+着色器程序,禁用glBegin/glEnd;需严格遵循VAO/VBO绑定顺序、检查着色器编译链接状态、匹配GLSL版本声明,并在macOS启用forward兼容。

直接上结论:**必须用现代 OpenGL(3.3+ 核心模式),靠 glDrawArrays + 顶点缓冲区(VBO)+ 着色器程序,不能用 glBegin/glEnd 那套旧接口**。Windows/macOS/Linux 上行为一致,但 macOS 需额外加 GLFW_OPENGL_FORWARD_COMPAT。
为什么 glDrawArrays 是唯一可靠选择
旧式立即渲染模式(glBegin/glEnd)在核心配置下已被完全移除。哪怕你编译通过,运行时调用也会触发 GL_INVALID_OPERATION 错误,且不会报具体位置——只会在 glGetError() 返回非零值,或直接黑屏。
- 所有主流教程(LearnOpenGL、OpenGL SuperBible)和现代引擎(bgfx、Ogre3D)都基于可编程管线
-
glDrawArrays(GL_TRIANGLES, 0, 3)是最简路径:3 个顶点 → 1 个三角形,不依赖索引或复杂拓扑 - 若误用
GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN传入 3 个点,结果看似一样,但扩展性差、语义模糊,容易在后续加点时出错
VAO 和 VBO 的绑定顺序不能颠倒
常见崩溃点:创建 VBO 后直接 glVertexAttribPointer,却没先 glBindVertexArray。GPU 不知道该把属性指针存到哪个对象里——这会导致后续 glDrawArrays 读取野指针,程序静默闪退或显示乱码。
- 必须按固定顺序:生成 VAO → 绑定 VAO → 生成/绑定 VBO →
glBufferData→glVertexAttribPointer→glEnableVertexAttribArray - VBO 可以解绑(
glBindBuffer(GL_ARRAY_BUFFER, 0)),但 VAO 一定不能解绑,否则属性状态丢失 - macOS 对未启用的 attribute 检查更严,即使你只用位置(location = 0),漏掉
glEnableVertexAttribArray(0)也会导致全黑
着色器编译失败时,infoLog 很可能为空
不是所有驱动都严格返回编译日志。比如 Intel HD Graphics 在 macOS 上有时 glGetShaderInfoLog 返回空字符串,但 glGetShaderiv(..., GL_COMPILE_STATUS, &success) 已是 GL_FALSE。光靠打印 infoLog 会误判为“编译成功”。
- 每次
glCompileShader后必须检查success,为 false 就立刻 return 或 abort - 片段着色器中漏写
out vec4 FragColor;或顶点着色器中没设gl_Position,都会导致链接失败,但错误发生在glLinkProgram阶段,需单独检查 - GLSL 版本声明必须匹配上下文:创建窗口时设了
GLFW_CONTEXT_VERSION_MAJOR=3,着色器第一行就得是#version 330 core;写成#version 330(缺 core)在部分 Linux 驱动下会静默失败
真正卡住人的地方,往往不是“怎么画”,而是“为什么没画出来”——它可能卡在 GLFW 窗口未响应、GLAD 加载失败、VAO 属性未启用、着色器链接时 missing entry point,甚至只是忘了在渲染循环里调 glClear。每一步的验证点都得亲手打日志,不能靠“应该没问题”。











