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

Posted

tags:

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

OpenGLES是一个让人崩溃的东西。在Andorid手机上做3D还就得用它。把我记的一些笔记分享在这里吧:androidOpenGLES简介20011-6-3Android系统使用OpenGL的标准接口来支持3D图形功能,android3D图形系统也分为java框架和本地代码两部分。本地代码主要实现的OpenGL接口的库,在Java框架层,javax.microedition.khronos.opengles是java标准的OpenGL包,android.opengl包提供了OpenGL系统和AndroidGUI系统之间的联系。Android的本地代码位于frameworks/base/opengl下,JNI代码位于frameworks/base/core/com_google_android_gles_jni_GLImpl.cpp和frameworks/base/core/com_google_android_gles_jni_EGLImpl.cpp,java类位于opengl/java/javax/microedition/khronos下本地测试代码位于frameworks/base/opengl/tests。包括angeles、fillrate等14个测试代码,这些代码都可以通过终端进行本地调用测试(模拟器中使用adbshell)。OpenGLES1.x固定管线操作,支持glVertexPointer()等函数,不支持GLSL。头文件在ndk的GLES目录下,库文件是libGLESv1_CM.so。OpenGLES2.x可编程管线操作,不兼容1.x,不支持固定管线操作,例如glVertexPointer()等函数。支持GLSL(还必须用这个来编程)。头文件在ndk的GLES2目录下,库文件是libGLESv2.so。OpenGLES学习2011-6-30OpenGL定义了自己的数据类型。应该坚持使用这些OpenGL的数据类型,从而保证可移植性和效率。OpenGLES目前不支持64位数据类型。OpenGLES只支持三边形。OpenGLES只支持gl开头的函数,glu库都不支持。OpenGLES从OpenGL中删除的功能:1.glBegin/glEnd2.glArrayElement3.显示列表4.求值器5.索引色模式6.自定义裁剪平面7.glRect8.图像处理(这个一般显卡也没有,FireGL/Quadro显卡有)9.反馈缓冲10.选择缓冲11.累积缓冲12.边界标志13.glPolygonMode14.GL_QUADS,GL_QUAD_STRIP,GL_POLYGON15.glPushAttrib,glPopAttrib,glPushClientAttrib,glPopClientAttrib16.TEXTURE_1D、TEXTURE_3D、TEXTURE_RECT、TEXTURE_CUBE_MAP17.GL_COMBINE18.自动纹理坐标生成19.纹理边界20.GL_CLAMP、GL_CLAMP_TO_BORDER21.消失纹理代表22.纹理LOD限定23.纹理偏好限定24.纹理自动压缩、解压缩25.glDrawPixels,glPixelTransfer,glPixelZoom26.glReadBuffer,glDrawBuffer,glCopyPixelsOpenGLES2.02011-10-92.0和1.1不兼容。-2.0使用的头文件是ndk的include目录下的GLES2目录,有gl2.h,gl2ext.h,gl2platform.h,而1.1使用的是GLES目录。-2.0使用的库文件是ndk的lib目录下的libGLESv2.so,而1.1使用的是libGLESv1_CM.so。-2.0中取消了很多1.1函数,例如glMatrixModel和glLoadIdentity等。OpenGL着色语言(GLSL――OpenGLShadingLanguage)-使用2.0,必须学此语言。因为很多1.1的函数都被取消了。san-angelesNDKOpenGLES1.1的例子程序2012-3-8SanAngeles,查维基百科,是一个虚构的未来概念城市,位于南加州。常在电影中出现,来源自LosAngeles和SanDiego.该程序的演示效果是,观察一个宏伟的城市,地面是镜面有建筑倒影,城市中有飞船飞过。前后有5、6个观察点,而且镜头在每个观察点不停的移动。这个例子,用NDK(C++)调用OpenGLES1.1来绘制了SanAngeles这个城市。基本上全部使用了NDK,Java程序只有1个。用vc2005演示一下,目的通过跟踪代码了解一些细节。方法是:-将jni下所有的.h文件,以及demo.c,app-win32.c复制出来,放在一个专门的目录下,然后改造成用OpenGL的而不是ES的。(或者干脆删除大段的绘制代码,保证编译通过)首先分析Java代码-DemoActivity.java,这是唯一的Java文件,它主要需要下列4个jni的接口:-privatestaticnativevoidnativeInit();//初始化-privatestaticnativevoidnativeResize(intw,inth);-privatestaticnativevoidnativeRender();//绘制1帧-privatestaticnativevoidnativeDone();其次分析C++代码app-android.c-首先,调用了importGLInit(),动态导入OpenGL的库。-其次,调用了appInit(),在内存中建立了平台无关的3D对象集合。建立方法是用一个数组,用类似画圆拔高的方式产生诸多三角形。-然后,在每个时钟周期中调用appRender(),细节是:-prepareFrame(width,height);//准备OpenGLES绘制框架。其实就是清空颜色和深度缓冲,重置投影和模型矩阵。-camTrack();//算好在当前时钟周期,镜头的位置、朝向及焦距等。然后调用gluLookAt来实现。-configureLightAndMaterial();//设置光源和材质-drawModels(-1);//先绘制倒影(其实就是将所有模型z轴倒过来画)-第一个循环,是画精致的物体-第二个循环,是画运动的物体-drawGroundPlane();//再绘制镜子一般的地面。在绘制前取消光照,打开混合,然后绘制。绘制后还原状态。-drawModels(1);//再绘制所有模型-drawFadeQuad();//最后绘制淡出框,用融合的方式画一个遮住整个视口的2D框,融合系数和时间相关。 参考技术A FrameBuffer对象的概念可以参见前面文章AndroidOpenGLES开发教程(23):FrameBuffer。简单的和2D图像类比,FrameBuffer如果对应到二维图形环境中,就是一个2D的内存数组空间,缺省情况为屏幕的显存,也可以创建Offscreen内存空间,此时FrameBuffer可以是一个二维数组,数组每个元素代表一个像素颜色。对于三维图形来说,除了需要代表颜色的二维数组(ColorBuffer),还需要深度二维数组(DepthBuffer)或遮罩数组(StencilBuffer),因此在OpenGL中的FrameBuffer为上述ColorBuffer,DepthBuffer,StencilBuffer的集合。如果手机具有GPU,其缺省的FrameBuffer也是3D屏幕显示区域。通过OpenglES扩展支持,应用程序也可以创建内存中的FrameBuffer对象(不用于屏幕显示)。通过这种应用程序创建的FrameBuffer对象,OpenGL应用可以将图像显示输出重新定向到这个非屏幕显示用FrameBuffer对象中,类似于二维图形绘制中常用的Offscreen技术。和缺省的屏幕显示FrameBuffer一样,由应用程序创建的FrameBuffer对象也是由ColorBuffer,DepthBuffer和StencilBuffer(可选)的集合组成。这些Buffer在FrameBuffer对象中可以称为FrameBuffer-attachable图像,FrameBuffer定义了一些接入点(AttachmentPoint)可以用于连接(Attach)这些Buffer数组。OpenGLES定义了两种FrameBuffer-attachable图像,Texture和renderbuffer,简单的可以将Texture理解为Colorbuffer或是2D图像,renderbuffer对应于depthbuffer。本回答被提问者采纳

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

【中文标题】在 Android 上使用 OpenGL ES 显示透明纹理的问题【英文标题】:Problems displaying transparent textures with OpenGL ES on Android 【发布时间】:2010-12-29 21:23:19 【问题描述】:

我已经投入了一天多的时间来寻找有关如何在 Android 上使用 OpenGL 渲染透明纹理的解决方案。显然其他人比我运气好,但在尝试了各种解决方案(例如Transparent texture in OpenGL ES for Android)后,我仍然无法完成。

这是我的基本设置:

        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
    gl.glClearColor(0.0f, 0.0f, 0.0f, 1);
    gl.glShadeModel(GL10.GL_FLAT);
    gl.glDisable(GL10.GL_DEPTH_TEST);
    gl.glEnable(GL10.GL_TEXTURE_2D);
    gl.glDisable(GL10.GL_DITHER);
    gl.glDisable(GL10.GL_LIGHTING);

    gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
            GL10.GL_MODULATE);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glViewport(0, 0, w, h);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    GLU.gluOrtho2D(gl, -ratio, ratio, -1, 1);

纹理是通过...加载的

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureName);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
            GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
            GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
            GL10.GL_CLAMP_TO_EDGE);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
            GL10.GL_CLAMP_TO_EDGE);
    gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
            GL10.GL_MODULATE);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

...并且有迹象表明这会由于预乘 alpha 而导致问题。但是 ReplicaIsland 也确实使用了 GLUtils 功能,而且游戏似乎没有透明图像的问题。

现在,如果我使用 Alpha 通道 (PNG) 绘制纹理,它们会显示为纯黑色。没有 alpha 的纹理以各自的颜色正确绘制)。我没有运气就应用了各种 glBlendFunc 调用,即

    gl.glShadeModel(GL10.GL_FLAT);
    gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
    gl.glColor4x(0x10000, 0x10000, 0x10000, 0x10000);

我也试过这个

    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

结果总是纹理完全不可见(完全透明?)。

用于测试的图像来自 ReplicaIsland 项目,这些是标准 PNG。这也意味着使用的纹理符合 2 的幂规则 - 各种帖子中提供的另一种解决方案。我看到一个区别,即 ReplicaIsland 似乎主要依赖于 draw_texture 扩展,而我必须使用 VBO(以便能够应用旋转)。

我们将不胜感激! 谢谢 本

【问题讨论】:

【参考方案1】:

好的,又经过了一天的调试,终于找到了我的错误。它与位图的配色方案无关,glBlendFunc 或类似的东西。

原来我在两个纹理函数调用中草率地使用了GL_FIXEDGL_FLOAT

【讨论】:

以上是关于如何在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,为啥?