如何在Android上使用OpenGL ES 2.0绘制点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Android上使用OpenGL ES 2.0绘制点相关的知识,希望对你有一定的参考价值。

参考技术A 如何在Android使用OpenGL
ES
2.0绘制点,看上去并不是一个复杂的问题,但是上网一搜,满眼都是绘制点的代码。
如果你看到类似如下代码,基本上你已经掉坑里了。
···
c
glBeging();
...
glDrawPoint(...);
...
glEnd();
```
如上是使用OpenGL
ES
1.0绘制点的代码。因为架构不同,在OPENGL
ES
2.0的世界里,这一套已经彻底不管用了。
在OpenGL
ES
2.0里绘制点,要使用Shader,使用Shader,用Shader。。。。。。
具体怎么绘制呢,首先你要搞清楚,如何用Shader绘制一个普通带颜色的三角形。我这里假设你已经会了。
三角形显示出来的那一刻,你一定会有这样的代码:
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,
0,
vertexCount);
那么,只显示三角形的三个顶点该怎么办,说来简单,这行代码改成
GLES20.glDrawArrays(GLES20.GL_POINTS,
0,
vertexCount);
即可。
但是,理想和现实的差距总是很大,改完后三角形消失了但是顶点没有出现。正常OpenGL
2.0环境下应该怎么做呢?
1)首先调用
GL20.glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
这样在Shader中可以访问glPointSize;
2)然后类似准备每个顶点色彩那样准备顶点的大小的数值,三角形是三个顶点,就准备3个float。把顶点数据像色彩数据那样,绑定到VOB,再绑定到Shader的参数中。基本上就是照准备色彩那样准备顶点大小数据,不同之处在于每个色彩4个float,每个顶点尺寸1个float。
3)最后,把你的顶点Shader文件改好,增加顶点大小的输入参数和gl_PointSize赋值。
4)另外,如果你打算显示圆形顶点,而不是方形的,还要用GL20.glEnable()函数设置其他参数,具体可查OpenGL官网。
比如:
uniform
mat4
matrix;
attribute
vec4
aVertex;
attribute
vec4
aColor;
attribute
float
aPointSize;
varying
vec4
vColor;
void
main()
vColor
=
aColor;
gl_Position
=
matrix
*
aVertex;
gl_PointSize
=
aPointSize;

这样,基本上就搞定了。
现在,坑爹的问题来了,在Android上你找不到GLES20.GL_VERTEX_PROGRAM_POINT_SIZE的常量,谷歌似乎认为在手机的3D环境下绘制点没多大必要性,所以并没有加上这个参数,好在缺省情况下,模拟器中Shader中的gl_PointSize是打开的(Android
4.4.x)。所以你可以跳过第一步,直接传递点大小的参数,并把Shader改好就成。
那么,为什么你不写gl_PointSize
=
aPointSize,点就显示不出来呢。我估计缺省情况下,gl_PointSize
=
0.0f,所以显示不出来。
如果你显示点的大小总是固定不变的,你甚至可以把传递顶点大小数值的步骤也省略掉,直接在Shader中写上gl_PointSize
=
10.0f;即可。
阅读本文,当你打算在Android上用OPENGL
ES
2.0显示点时,即可跳过谷歌的那些坑了。我想,手机GPU硬件厂商的开发包应该对OpenGL
ES
2.0支持的更好些,比如高通的AdrenoSDK,建议大家下载尝试。

如何在 Android 中将 OpenCV 旋转和平移矢量与 OpenGL ES 一起使用?

【中文标题】如何在 Android 中将 OpenCV 旋转和平移矢量与 OpenGL ES 一起使用?【英文标题】:How to use an OpenCV rotation and translation vector with OpenGL ES in Android? 【发布时间】:2011-04-12 08:10:58 【问题描述】:

我正在开发 Android 上的基本增强现实应用程序。到目前为止,我所做的是用 opencv 检测一个正方形,然后使用 cvFindExtrinsicCameraParams2() 我计算了一个旋转和平移向量。为此,我使用了 4 个对象点,它们只是 (0,0,0) 周围正方形的角和图像中正方形的 4 个角。

这为我提供了一个非常好的旋转和平移矩阵。我还用 cvRodrigues2() 计算了旋转矩阵,因为使用它比旋转向量更容易。只要我使用这些在图像中绘制一些点,一切正常。然而,我的下一步是将这些向量和矩阵传递回 java,然后将它们与 OpenGL 一起使用,在 OpenGLView 中绘制一个正方形。正方形应该正好在 OpenGLView 后面显示的图像中的正方形周围。

我的问题是我找不到在 OpenGL 中使用旋转矩阵和平移向量的正确方法。我开始使用与 openCV 函数完全相同的对象点。然后我以我能想到的几乎所有可能的方式应用旋转矩阵和平移向量。遗憾的是,这些方法都没有产生接近我希望的结果。谁能告诉我如何正确使用它们?

到目前为止,我得到的“最接近”的结果是将整个矩阵随机乘以 -1。但大多数情况下,正方形仍然像镜子一样倒转或旋转 180 度。所以我猜这只是一个幸运的命中,但不是正确的方法。

【问题讨论】:

也许你需要transpose 一些东西。 【参考方案1】:

好的,经过更多的测试,我终于设法让它工作了。虽然我不明白......它确实“工作”。对于将来需要这样做的任何人,这是我的解决方案。

float rv[3]; // the rotation vector
float rotMat[9]; // rotation matrix
float tv[3]; // translation vector.


rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.

//Complete matrix ready to use for OpenGL
float RTMat[] = rotMat[0], rotMat[3], rotMat[6], 0.0f,
                 rotMat[1], rotMat[4], rotMat[7], 0.0f,
                 rotMat[2], rotMat[5], rotMat[8], 0.0f,
                 tv[0], -tv[1], -tv[2], 1.0f;

正如 genpfault 在他的评论中所说,自 OpenGL 以来,所有内容都需要转置,因为 OpenGL 需要以列为主的顺序。 (感谢您的评论,我之前已经看过该页面。)此外,y 和 z 旋转角度以及 y 和 z 平移需要乘以 -1。这是我觉得有点奇怪的地方。为什么只有那些而不是 x 值?

这正如我所猜测的那样有效。但是角落并不完全匹配。我猜这是由一些错误的 openGLView 配置引起的。因此,即使我对我的解决方案仍然不是 100% 满意,但我想这就是我问题的答案。

【讨论】:

这是ModelView矩阵还是投影矩阵? 您需要翻转 y 和 z,因为 open GL 沿 -z 轴向下查看并将其原点定义在左下角,openCV 的原点在左上角,z 很可能是正数。跨度> 【参考方案2】:

潘多罗的方法真的很管用!如果有人想知道“如何将旋转向量转换为旋转矩阵”,我就是这样做的。顺便说一句,我在 OpenGL 2 中使用了这些,而不是 ES。

// use the rotation vector generated from OpenCV's cvFindExtrinsicCameraParams2() 
float rv[] = rotation->data.fl[0], rotation->data.fl[1], rotation->data.fl[2] ; 

// use the translation vector generated from OpenCV's cvFindExtrinsicCameraParams2() 
float tv[] = translation->data.fl[0], translation->data.fl[1], translation->data.fl[2] ; 

float rm[9];
// rotation matrix
CvMat* rotMat = cvCreateMat (3, 3, CV_32FC1); 

// rotation vectors can be converted to a 3-by-3 rotation matrix
// by calling cvRodrigues2() - Source: O'Reilly Learning OpenCV
cvRodrigues2(rotation, rotMat, NULL);

for(int i=0; i<9; i++)
    rm[i] = rotMat->data.fl[i];


rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.

//Complete matrix ready to use for OpenGL
float RTMat[] = rm[0], rm[3], rm[6], 0.0f,
             rm[1], rm[4], rm[7], 0.0f,
             rm[2], rm[5], rm[8], 0.0f,
             tv[0], -tv[1], -tv[2], 1.0f;

祝你好运!

【讨论】:

以上是关于如何在Android上使用OpenGL ES 2.0绘制点的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android上使用OpenGL ES 2.0绘制点

使用OpenGL ES 2.0在Android上创建Audio wave

Android 上的 OpenGL ES 2:如何使用 VBO

如何在Android上将OpenGL ES 1.0代码转换为OpenGL Es 2.0?

在 Android 上使用 OpenGL ES 显示透明纹理的问题

Framebuffer FBO渲染到纹理很慢,在Android上使用OpenGL ES 2.0,为啥?