现代opengl 3.3+核心模式下绘制立方体需手动组织顶点(8个)、索引(36个),绑定vao/vbo/ibo,使用gldrawelements;必须正确设置顶点布局(stride/offset)、用mat3 normalmatrix变换法向量、启用并清除深度测试,且obj坐标系需z取反对齐opengl右手系。

OpenGL 3.3+核心模式下怎么加载顶点数据画一个立方体
不能直接用 glBegin/glEnd——那是已废弃的立即模式,现代 OpenGL 要求你手动组织顶点、绑定 VAO/VBO/IBO,并写好着色器。最简可行路径是:定义 8 个顶点 + 36 个索引(重复使用顶点),用 glDrawElements 渲染。
常见错误是只传顶点没传法向量或纹理坐标,导致光照发黑或贴图错乱;更隐蔽的问题是顶点布局(glVertexAttribPointer)中步长(stride)和偏移(offset)算错,比如把 sizeof(float) * 6 写成 sizeof(float) * 3,结果法向量全读成零。
- 顶点结构建议用
struct { glm::vec3 pos; glm::vec3 normal; },打包紧凑,避免内存对齐陷阱 - VAO 必须在绑定 VBO 后才调用
glVertexAttribPointer,否则配置不生效 - 索引类型固定用
GL_UNSIGNED_INT,别用GL_UNSIGNED_SHORT除非你确认模型顶点数 ≤65535
顶点着色器里怎么正确传递法向量给片元着色器
法向量必须在顶点着色器中用 normalMatrix(即模型-视图矩阵的逆转置)变换,否则旋转缩放后法向量长度失真、方向错误,光照计算全崩。别直接用 mat4 变换法向量——它不保持垂直性。
示例片段:
// 顶点着色器
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat3 normalMatrix; // 注意是 mat3!
in vec3 aPos;
in vec3 aNormal;
out vec3 FragNormal;
<p>void main() {
gl_Position = projection <em> view </em> model <em> vec4(aPos, 1.0);
FragNormal = normalMatrix </em> aNormal; // 关键:用 mat3 变换
}</p>
-
normalMatrix在 CPU 端应由glm::transpose(glm::inverse(glm::mat3(view * model)))计算,不是glm::mat3(model) - 如果模型有非均匀缩放,
mat3版本会出错,此时必须用glm::mat4的逆转置再取上 3×3 子块 - 插值后的
FragNormal到片元着色器后务必归一化:normalize(FragNormal),否则光照强度随三角形大小变化
为什么网格显示为空白或只有部分面
八成是剔除(culling)或深度测试没配对。默认开启 GL_CULL_FACE,但若顶点顺序不统一(顺时针/逆时针混用),背面会被直接丢弃;同时若没开 GL_DEPTH_TEST 或没清深度缓冲,远近面会互相覆盖。
- 检查顶点索引顺序:所有三角形按相同 winding order(如逆时针)定义,可用
glFrontFace(GL_CCW)显式声明 - 必须在渲染循环开头调用
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT),漏掉GL_DEPTH_BUFFER_BIT就会复用上帧深度值 - 深度缓冲格式要匹配:创建 framebuffer 时若用
GL_DEPTH_COMPONENT16,精度不够,复杂网格易发生 z-fighting;优先选GL_DEPTH_COMPONENT24或GL_DEPTH_COMPONENT32F
加载 OBJ 文件后网格变形或翻转怎么办
OBJ 坐标系是 Y-up、Z-forward,而 OpenGL 默认是 Y-up、Z-backward(右手系 vs 左手系)。直接加载会导致模型沿 Z 轴镜像翻转,看起来“穿模”或朝向相反。
- 最稳妥做法:加载时对顶点 z 坐标取反(
vertex.z = -vertex.z),同时翻转法向量 z 分量 - 不要试图靠修改投影矩阵修复——那会影响整个场景的深度关系
- OBJ 的纹理坐标 y 轴也常需翻转(
texCoord.y = 1.0f - texCoord.y),否则贴图上下颠倒 - 若用 Assimp 库,启用
aiProcess_FlipWindingOrder | aiProcess_FlipUVs标志,但注意它不自动处理 Z 轴翻转,仍需手动干预
实际跑通一个带光照的立方体,核心不在“画出来”,而在验证法向量变换、深度测试、坐标系对齐这三处是否真正一致。少一个,模型就可能静默失败——不报错,只显示不对。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











