文档章节

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

ylme
 ylme
发布于 2016/09/16 16:35
字数 1062
阅读 175
收藏 0

更新

之前在知乎上发了一个帖子来询问,有个答主金条回答了而且还带了参考文档,原来在 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 来产生四种效果图。可以手动试试奥。

© 著作权归作者所有

ylme
粉丝 12
博文 42
码字总数 42711
作品 0
广州
程序员
私信 提问
Android图形---OpenGL(五)

本文译自:http://developer.android.com/guide/topics/graphics/opengl.html 形状的外观和折点 在OpenGL中,形状的外观是由三个或三维空间中更多的点来定义的一个表面。一个三个或更多的三维...

长平狐
2012/10/16
66
0
图片和图形之用OpenGL ES显示图形(9)

原文 概要 Android框架提供了大量用于创建有吸引力的功能性图形用户界面的标准工具。但是,如果您想要更多地控制应用程序在屏幕上绘制的内容,或者冒险进入三维图形,则需要使用其他工具。A...

lichong951
2018/05/26
0
0
在Android中使用OpenGL ES进行开发第(二)课:定义图形

一、前期基础知识储备 笔者计划写三篇文章来详细分析OpenGL ES基础的同时也是入门关键的三个点: ①OpenGL ES是什么?与OpenGL的关系是什么?——概念部分 ②使用OpenGLES绘制2D/3D图形的第一...

weixin_41101173
2018/04/22
0
0
与OpenGL ES的第一次约会

最近公司的项目中需要实现一个实时视频绘制的功能,在相机中根据识别到的人脸点位信息,对指定的点之间绘制出图案来引导用户。出于性能的考量,决定采用OpenGL ES来进行图案的绘制。最终效果...

金小俊
2018/09/05
0
0
OpenGL开发之旅基础知识介绍

OpenGL开发之旅基础知识介绍 glLoadIdentity();gluortho2D(-1.0,1.0,-1.0,1.0) glEnd(); glPushMatrix();glPopMatrix(); 0000FF;">void) { // 清除颜色缓冲区 glClear(GLCOLORBUFFERBIT); /......

andyhe91
2013/05/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

利用mybatis generator生成实体类、Mapper接口以及对应的XML文件

项目中通常会遇到数据的持久化,如果是采用mybatis的orm,就会涉及到生成xml的问题,刚好mybatis官网提供了这么个插件MyBatis Generator,效果简直是棒呆。 1. 首先需要在build.gradle文件中...

啊哈关关
今天
2
0
SpringSocial相关的知识点

使用SprigSocial开发第三方登录 核心类 ServiceProvider(AbstractOauth2ServiceProvider):主要负责实现server提供商(例如QQ,微信等共有的东西),默认实现类是AbstractOauth2ServiceProvider...

chendom
今天
1
0
Java并发之AQS详解

一、概述   谈到并发,不得不谈ReentrantLock;而谈到ReentrantLock,不得不谈AbstractQueuedSynchronizer(AQS)!   类如其名,抽象的队列式的同步器,AQS定义了一套多线程访问共享资源...

群星纪元
昨天
2
0
Fabric-sdk-java最新教程

Fabric Java SDK是Fabric区块链官方提供的用于Java应用开发的SDK,全称为Fabric-sdk-java,网上可用资料不多,本文列出了精心整理的针对Fabric Java SDK的最新精选教程。 如果希望快速掌握F...

汇智网教程
昨天
2
0
react 子组件监听props 变化

componentWillReceiveProps //已经被废弃 getDerivedStateFromProps// 推荐使用//如果条件不存在必须要返回null static getDerivedStateFromProps(props, current_stat...

一箭落旄头
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部