为什么简单的 opengl 代码却没有绘制出形状

更新

之前在知乎上发了一个帖子来询问,有个答主金条回答了而且还带了参考文档,原来在 specification 中有说明(好吧,看见那个一坨我就没有去翻了,后面有问题还是得去这里看看,说不定可以找到答案)。

概要

之前调试一个 opengl 小程序时,我写的临时代码无论如何都绘制不出形状来,检查了顶点数据 N 遍后确认顶点数据无误,于是我把注意点转向了 api 的调用,发现无法绘制出来形状和 opengl 版本是有些关系的。于是想写一篇 blog 整理一下。 opengl 历史就不说了,下面的测试代码用两种方式绘制三角形,一种是 opengl 现代模式绘制,另一种是兼容模式绘制。现代模式就是指定了 opengl 最低版本是 3.3 。

问题与结论

我遇见的问题如下。

  • 为什么我没有创建 vao 就绘制不出三角形?而在 opengles 中确可以。
  • 当我使用 vao 时,我可以不用 bo 来缓存顶点属性数据吗?
  • 如果我想在 opengl 中直接调用 glVertexAttribPointer 设置属性后调用 draw 函数绘制(调试时,总是想少写些代码),应该在什么环境下?

写代码测试后结论如下。

  • 指定 opengl 最低版本号为 3.3 时,这时绘制要创建一个 vertex array object (vao),否则无法绘制出形状。
  • 使用 vao 时,此时要使用 buffer object(bo)缓存顶点属性数据,否则无法绘制出形状。
  • 使用 vao 时,在 glBindVertexArray 后调用 glEnableVertexAttribArray 才会使 vao 内的顶点属性有效果。不然会导致顶点着色器无法接收数组属性数据。
  • 不指定 opengl 版本时,则没有太多要求,此时可以用最简单的代码来画一个三角形。

测试

为了弄清楚,我想了一个小例子来验证。例子中将绘制 4 个三角形。

  • 左上和右上是采用现代 opengl 绘制,这里左右的分别是左边采用了 bo 右边可根据宏定义是否采用 bo 。
  • 左下和右下是采用兼容 opengl 绘制。左采用了 bo 而右边未采用 bo 。并且绘制这两个三角形并未显示的创建一个 vao 。
  • 为了使现代模式和兼容模式互不影响,绘制时我采用了两个 program ,modern_program 和 compat_program 分别对应现代模式和兼容模式。

完整的代码在我的博客代码片段仓库中 blogsnippet\opengl\trimodern 目录。 下面定义了两个宏,默认是定义的,你可以注释掉来查看不同的效果。定义 USE_OPENGL33 表示采用现代 opengl 。定义 VAO_WITH_BO 表示采用 BO ,可以注释掉来查看三角形还能不能绘制。

#define USE_OPENGL33
#define VAO_WITH_BO

下面是绘制的代码,分成了两部分,首先用 modern_program 绘制上方的两个三角形,然后用 compat_program 绘制下方的两个三角形。

glUseProgram(modern_program);
glBindVertexArray(vao);
	glEnableVertexAttribArray(0); // 两个 program 都使用 0 索引属性,为了不被其他 program 影响,这里再次调用 
	// draw left up
	glBindBuffer(GL_ARRAY_BUFFER, leftup_bo);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // 在绘制时才定义数组属性数据
	glDrawArrays(GL_TRIANGLES, 0, 3);
	// draw right up
#ifdef VAO_WITH_BO
	glBindBuffer(GL_ARRAY_BUFFER, rightup_bo);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
#else
	glBindBuffer(GL_ARRAY_BUFFER, 0); // 测试代码,取消注释着两行,看看不使用 buffer object 能不能成功绘制
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices_rightup);
#endif
	glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);
		
glUseProgram(compat_program);
// draw left down
glBindBuffer(GL_ARRAY_BUFFER, leftdown_bo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, 0); // 由于下一个绘制没有用到缓冲区,这里要解绑缓冲区,不然会受到影响
// draw right down
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices_rightdown);
glDrawArrays(GL_TRIANGLES, 0, 3);
glUseProgram(0);

如下图。默认是宏都是定义的。可以发现采用 modern opengl 时,必须要显示创建 vao 才能绘制出图像。 use modern

如下图,当采用兼容 opengl 时,4 个三角形都绘制出来了。 use compat

可以通过注释 USE_OPENGL33VAO_WITH_BO 来产生四种效果图。可以手动试试奥。

转载于:https://my.oschina.net/iirecord/blog/747328

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值