android – Opengl开发GPU依赖吗?

我在opengl ES2.0中开发了一个 android应用程序.在这个应用程序中,我曾经通过GL surfaceView中的触摸事件绘制多个线条和圆圈.

由于opengl依赖于GPU,目前它在Google Nexus 7(ULP GeForce)中运行良好.

在三星Galaxy Note 2(MALI 400MP)中,我试图绘制多条线,但它清除了前一条线,并将当前线绘制为新线.

在Sony Xperia Neo V(Adreno 205)中,我试图画一条新线,它会使表面崩溃,如下图所示.

是否可以使其在所有设备上运行,或者我是否需要为单个GPU编写代码?

源代码

MainActivity.java

//in OnCreate method of my activity,i set the glsurfaceview and renderer

final ActivityManager activityManager =
    ( ActivityManager ) getSystemService( Context.ACTIVITY_SERVICE );
final ConfigurationInfo configurationInfo =
    activityManager.getDeviceConfigurationInfo(  );
final boolean supportsEs2 = ( configurationInfo.reqGlEsVersion >= 0x20000
                  || Build.FINGERPRINT.startsWith( "generic" ) );

if( supportsEs2 ) {
    Log.i( "JO","configurationInfo.reqGlEsVersion:"
           + configurationInfo.reqGlEsVersion + "supportsEs2:"
           + supportsEs2 );
// Request an OpenGL ES 2.0 compatible context.
    myGlsurfaceView.setEGLContextClientVersion( 2 );

    final DisplayMetrics displayMetrics = new DisplayMetrics(  );
    getWindowManager(  ).getDefaultDisplay(  ).getMetrics( displayMetrics );

// Set the renderer to our demo renderer,defined below.
    myRenderer = new MyRenderer( this,myGlsurfaceView );
    myGlsurfaceView.setRenderer( myRenderer,displayMetrics.density );
    myGlsurfaceView.setRenderMode( GLSurfaceView.RENDERMODE_CONTINUOUSLY );

    MyGLSurfaceView.java
//in this im getting the coordinates of my touch on the glSurfaceView to draw the line and //passing those points to the renderer class
        public MyGLsurfaceview( Context context ) {
        super( context );
        Log.i( "JO","MyGLsurfaceview1" );

    }

    public MyGLsurfaceview(
    Context context,AttributeSet attrs )
    {
        super( context,attrs );
        con = context;
        mActivity = new MainActivity(  );
        mActivity.myGlsurfaceView = this;
        Log.i( "JO","MyGLsurfaceview2" );
    }

    public void setRenderer(
    MyRenderer renderer,float density )
    {
        Log.i( "JO","setRenderer" );
        myRenderer = renderer;
        myDensity = density;
        mGestureDetector = new GestureDetector( con,mGestureListener );
        super.setRenderer( renderer );
        setRenderMode( GLSurfaceView.RENDERMODE_CONTINUOUSLY );

    }
    @Override public boolean onTouchEvent( MotionEvent ev ) {

        boolean retVal = mGestureDetector.onTouchEvent( ev );

        if( myline ) {

            switch ( ev.getAction(  ) ) {

            case MotionEvent.ACTION_DOWN:

                isLUp = false;

                if( count == 1 ) {
                    dx = ev.getX(  );
                    dy = ev.getY(  );
                    dx = ( dx / ( getWidth(  ) / 2 ) ) - 1;
                    dy = 1 - ( dy / ( getHeight(  ) / 2 ) );

                    firstX = dx;
                    firstY = dy;
                } else if( count == 2 ) {

                    ux = ev.getX(  );
                    uy = ev.getY(  );
                    ux = ( ux / ( getWidth(  ) / 2 ) ) - 1;
                    uy = 1 - ( uy / ( getHeight(  ) / 2 ) );

                    secondX = ux;
                    secondY = uy;

                    myRenderer.dx = firstX;
                    myRenderer.dy = firstY;
                    myRenderer.ux = secondX;
                    myRenderer.uy = secondY;

                    midX = ( firstX + secondX ) / 2;
                    midY = ( firstY + secondY ) / 2;
                    Log.e( "JO","Line:firstX" + firstX +
                           "firstY" + firstY );
                    lp = new LinePoints( firstX,firstY,secondX,secondY,midX,midY );
                    lineArray.add( lp );

                    myRenderer.isNewClick = false;
                    myRenderer.isEnteredAngle = false;
                    myRenderer.myline = true;
                    myRenderer.mycircle = false;
                    myRenderer.mydashedline = false;
                    myRenderer.eraseCircle = false;
                    myRenderer.eraseLine = false;
                    myRenderer.eraseSelCir = false;
                    myRenderer.angle = angle;
                    myRenderer.length = length;
                    requestRender(  );
                    count = 0;

                }
                count++;

                break;
            case MotionEvent.ACTION_MOVE:

                isLUp = true;

                break;

            case MotionEvent.ACTION_UP:

                if( isLUp ) {

                    ux = ev.getX(  );
                    uy = ev.getY(  );
                    ux = ( ux / ( getWidth(  ) / 2 ) ) - 1;
                    uy = 1 - ( uy / ( getHeight(  ) / 2 ) );
                    Log.i( "JO","line2:" + ux + "," + uy );

                    secondX = ux;
                    secondY = uy;
                    myRenderer.dx = firstX;
                    myRenderer.dy = firstY;
                    myRenderer.ux = secondX;
                    myRenderer.uy = secondY;

                    midX = ( firstX + secondX ) / 2;
                    midY = ( firstY + secondY ) / 2;
                    Log.e( "JO",midY );
                    lineArray.add( lp );

                    myRenderer.isNewClick = false;
                    myRenderer.isEnteredAngle = false;
                    myRenderer.myline = true;
                    myRenderer.mycircle = false;
                    myRenderer.mydashedline = false;
                    myRenderer.mysnaptoedge = false;
                    myRenderer.mysnaptoMiddle = false;
                    myRenderer.eraseCircle = false;
                    myRenderer.eraseLine = false;
                    myRenderer.eraseSelCir = false;
                    count = 1;
                    requestRender(  );
                }

                break;

            }
        }
    }
}

MyRenderer.java

//renderer class to render the line to the glsurfaceview
Lines line;
public MyRenderer(
    MainActivity mainActivity,MyGLsurfaceview myGlsurfaceView )
{
    Log.i( "JO","MyRenderer" );
    this.main = mainActivity;
    myGlsurface = myGlsurfaceView;

}

public void onDrawFrame(
    GL10 gl )
{
    line.draw( dx,dy,ux,uy );
}

@Override public void onSurfaceCreated(
    GL10 gl,EGLConfig config )
{
    Log.i( "JO","onSurfaceCreated" );
// Set the background frame color
    GLES20.glClearColor( 0.0f,0.0f,1.0f );
// Create the GLText
    glText = new GLText( main.getAssets(  ) );

// Load the font from file (set size + padding),creates the texture
// NOTE: after a successful call to this the font is ready for
// rendering!
    glText.load( "Roboto-Regular.ttf",14,2,2 );  // Create Font (Height: 14
// Pixels / X+Y Padding
// 2 Pixels)
// enable texture + alpha blending
    GLES20.glEnable( GLES20.GL_BLEND );
    GLES20.glBlendFunc( GLES20.GL_ONE,GLES20.GL_ONE_MINUS_SRC_ALPHA );
}

@Override public void onSurfaceChanged(
    GL10 gl,int width,int height )
{
// Adjust the viewport based on geometry changes,// such as screen rotation
    GLES20.glViewport( 0,width,height );

    ratio = ( float ) width / height;

    width_surface = width;
    height_surface = height;

/*
* // this projection matrix is applied to object coordinates // in the
* onDrawFrame() method Matrix.frustumM(mProjMatrix,-ratio,ratio,* -1,1,3,7);
*/
// Take into account device orientation
    if( width > height ) {
        Matrix.frustumM( mProjMatrix,-1,10 );
    } else {
        Matrix.frustumM( mProjMatrix,-1 / ratio,1 / ratio,10 );
    }

// Save width and height
    this.width = width; // Save Current Width
    this.height = height;   // Save Current Height

    int useForOrtho = Math.min( width,height );

// TODO: Is this wrong?
    Matrix.orthoM( mVMatrix,-useForOrtho / 2,useForOrtho / 2,0.1f,100f );
}

Line.java

//Line class to draw line

public class Lines
{

    final String vertexShaderCode = "attribute vec4 vPosition;"
        + "void main() {" + " gl_Position = vPosition;" + "}";

    final String fragmentShaderCode = "precision mediump float;"
        + "uniform vec4 vColor;" + "void main() {"
        + " gl_FragColor = vColor;" + "}";

    final FloatBuffer vertexBuffer;
    final int mProgram;
    int mPositionHandle;
    int mColorHandle;

// number of coordinates per vertex in this array
    final int COORDS_PER_VERTEX = 3;
    float lineCoords[] = new float[6];
    final int vertexCount = lineCoords.length / COORDS_PER_VERTEX;
    final int vertexStride = COORDS_PER_VERTEX * 4; // bytes per vertex
// Set color with red,green,blue and alpha (opacity) values
    float lcolor[] = { 1.0f,1.0f,1.0f };

    public Lines(
         )
    {

// initialize vertex byte buffer for shape coordinates
        ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
                                  lineCoords.
                                  length * 4 );
// use the device hardware's native byte order
        bb.order( ByteOrder.nativeOrder(  ) );

// create a floating point buffer from the ByteBuffer
        vertexBuffer = bb.asFloatBuffer(  );

// prepare shaders and OpenGL program
        int vertexShader =
            MyRenderer.loadShader( GLES20.GL_VERTEX_SHADER,vertexShaderCode );
        int fragmentShader =
            MyRenderer.loadShader( GLES20.GL_FRAGMENT_SHADER,fragmentShaderCode );

        mProgram = GLES20.glCreateProgram(  );  // create empty OpenGL Program
        GLES20.glAttachShader( mProgram,vertexShader );    // add the vertex shader
// to program
        GLES20.glAttachShader( mProgram,fragmentShader );  // add the fragment
// shader to program
        GLES20.glLinkProgram( mProgram );   // create OpenGL program executables
    }

    public void draw(
    float dX,float dY,float uX,float uY )
    {

        lineCoords[0] = dX;
        lineCoords[1] = dY;
        lineCoords[2] = 0.0f;
        lineCoords[3] = uX;
        lineCoords[4] = uY;
        lineCoords[5] = 0.0f;
        Log.i( "JO","lineCoords:" + lineCoords[0] + "," + lineCoords[1] +
               "," + lineCoords[3] + "," + lineCoords[4] );

        vertexBuffer.put( lineCoords );
        vertexBuffer.position( 0 );
// Add program to OpenGL environment
        GLES20.glUseProgram( mProgram );

// get handle to vertex shader's vPosition member
        mPositionHandle =
            GLES20.glGetAttribLocation( mProgram,"vPosition" );

// Enable a handle to the triangle vertices
        GLES20.glEnableVertexAttribArray( mPositionHandle );

// Prepare the triangle coordinate data
        GLES20.glVertexAttribPointer( mPositionHandle,COORDS_PER_VERTEX,GLES20.GL_FLOAT,false,vertexStride,vertexBuffer );

// get handle to fragment shader's vColor member
        mColorHandle =
            GLES20.glGetUniformLocation( mProgram,"vColor" );

// Set color for drawing the triangle
        GLES20.glUniform4fv( mColorHandle,lcolor,0 );
        GLES20.glLineWidth( 3 );
// Draw the triangle
        GLES20.glDrawArrays( GLES20.GL_LINES,vertexCount );

// Disable vertex array
        GLES20.glDisableVertexAttribArray( mPositionHandle );
    }

}

解决方法

好的,这里又一次:^ 1

OpenGL is not a scene graph. OpenGL does not maintain a scene,knows about objects or keeps tracks of geometry. OpenGL is a drawing API. You give it a canvas (in form of a Window or a PBuffer) and order it to draw points,lines or triangles and OpenGL does exactly that. Once a primitive (=point,line,triangle) has been drawn,OpenGL has no recollection about it whatsoever. If something changes,you have to redraw the whole thing.

重绘场景的正确步骤是:

>禁用模板测试,以便以下步骤在整个窗口上运行.
>使用glClear(位)清除帧缓冲区,其中位是位掩码,指定要清除画布的哪些部分.渲染新帧时,您要清除所有内容,因此位= GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
>设置视口,构建适当的投影矩阵
>为场景中的每个对象加载正确的模型视图矩阵,设置制服,选择顶点数组并进行绘图调用.
>通过冲洗管道完成渲染.如果使用单个缓冲窗口glFinish(),如果使用双缓冲窗口调用SwapBuffers.在更高级别框架的情况下,这可以由框架执行.

重要事项在双缓冲窗口上完成绘图后,您不能继续发送绘图操作,因为通过执行缓冲区交换,您绘制的后台缓冲区的内容是未定义的.因此,您必须重新开始绘图,从清除帧缓冲区开始(步骤1和2).

您的代码遗漏的正是这两个步骤.另外我的印象是你正在执行OpenGL绘图调用,直接对输入事件做出反应,可能在输入事件处理程序中.不要这样做!而是使用输入事件添加到要绘制的基元列表(在您的情况下为行),然后发送重绘事件,这使框架调用绘图函数.在绘图功能中迭代该列表以绘制所需的线条.

重绘整个场景在OpenGL中是规范的!

[1](geesh,我已经厌倦了每隔3个左右写一次这个问题……)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


更新Android SDK到3.0版本时,遇到Failed to rename directory E:\android\tools to E:\android\temp\ToolPackage.old01问题,导致无法更新,出现该问题的原因是由于3.0版本与较早的sdk版本之间文件结构有冲突,解决
Android 如何解决dialog弹出时无法捕捉Activity的back事件 在一些情况下,我们需要捕捉back键事件,然后在捕捉到的事件里写入我们需要进行的处理,通常可以采用下面三种办法捕捉到back事件: 1)重写onKeyDown或者onKeyUp方法 2)重写onBackPressed方
Android实现自定义带文字和图片的Button 在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法。一.用系统自带的Button实现 最简单的一种办法就是利用系统自带的Button来实现,这种方式代码量最小。在Button的属性中有一个是drawable
Android中的"Unable to start activity ComponentInfo"的错误 最近在做一款音乐播放器的时候,然后在调试的过程中发现一直报这个错误"Unable to start activity ComponentInfo",从字面
Android 关于长按back键退出应用程序的实现最近在做一个Android上的应用,碰到一个问题就是如何实现长按back键退出应用程序。在网上查找了很多资料,发现几乎没有这样的实现,大部分在处理时是双击back键来退出应用程序。参考了一下双击back键退出应用程序的代码,网上主流的一种方法是下面
android自带的时间选择器只能精确到分,但是对于某些应用要求选择的时间精确到秒级,此时只有自定义去实现这样的时间选择器了。下面介绍一个可以精确到秒级的时间选择器。 先上效果图: 下面是工程目录: 这个控件我也是用的别人的,好像是一个老外写的,com.wheel中的WheelView是滑动控件的主
Android平台下利用zxing实现二维码开发 现在走在大街小巷都能看到二维码,而且最近由于项目需要,所以研究了下二维码开发的东西,开源的二维码扫描库主要有zxing和zbar,zbar在iPos平台上应用比较成熟,而在Android平台上主流还是用zxing库,因此这里主要讲述如何利用zxing
Android ListView的item背景色设置以及item点击无响应等相关问题 在Android开发中,listview控件是非常常用的控件,在大多数情况下,大家都会改掉listview的item默认的外观,下面讲解以下在使用listview时最常见的几个问题。1.如何改变item的背景色和按
如何向Android模拟器中导入含有中文名称的文件在进行Android开发的时候,如果需要向Android模拟器中导入文件进行测试,通过DDMS下手动导入或者在命令行下通过adb push命令是无法导入含有中文文件名的文件的。后来发现借用其他工具可以向模拟器中导入中文名称的文件,这个工具就是Ultr
Windows 下搭建Android开发环境一.下载并安装JDK版本要求JDK1.6+,下载JDK成功后进行安装,安装好后进行环境变量的配置【我的电脑】-——>【属性】——>【高级】 ——>【环境变量】——>【系统变量】中点击【新建】:变量名:CLASSPATH变量值:……
如何利用PopupWindow实现弹出菜单并解决焦点获取以及与软键盘冲突问题 在android中有时候可能要实现一个底部弹出菜单,此时可以考虑用PopupWindow来实现。下面就来介绍一下如何使用PopupWindow实现一个弹出窗。 主Activity代码:public void onCreat
解决Android中的ERROR: the user data image is used by another emulator. aborting的方法 今天调试代码的时候,突然出现这个错误,折腾了很久没有解决。最后在google上找到了大家给出的两种解决方案,下面给出这两种方法的链接博客:ht
AdvserView.java package com.earen.viewflipper; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory;
ImageView的scaleType的属性有好几种,分别是matrix(默认)、center、centerCrop、centerInside、fitCenter、fitEnd、fitStart、fitXY。 |值|说明| |:--:|:--| |center|保持原图的大小,显示在ImageVie
文章浏览阅读8.8k次,点赞9次,收藏20次。本文操作环境:win10/Android studio 3.21.环境配置 在SDK Tools里选择 CMAKE/LLDB/NDK点击OK 安装这些插件. 2.创建CMakeLists.txt文件 在Project 目录下,右键app,点击新建File文件,命名为CMakeLists.txt点击OK,创建完毕! 3.配置文件 在CMa..._link c++ project with gradle
文章浏览阅读1.2w次,点赞15次,收藏69次。实现目的:由mainActivity界面跳转到otherActivity界面1.写好两个layout文件,activity_main.xml和otherxml.xmlactivity_main.xml<?xml version="1.0" encoding="utf-8"?><RelativeLayout ="http://schemas..._android studio 界面跳转
文章浏览阅读3.8w次。前言:最近在找Android上的全局代理软件来用,然后发现了这两款神作,都是外国的软件,而且都是开源的软件,因此把源码下载了下来,给有需要研究代理这方面的童鞋看看。不得不说,国外的开源精神十分浓,大家相互使用当前基础的开源软件,然后组合成一个更大更强的大开源软件。好吧,废话不多说,下面简单介绍一下这两款开源项目。一、ProxyDroid:ProxyDroid功能比较强大,用到的技术也比较多,源码也_proxydroid
文章浏览阅读2.5w次,点赞17次,收藏6次。创建项目后,运行项目时Gradle Build 窗口却显示错误:程序包R不存在通常情况下是不会出现这个错误的。我是怎么遇到这个错误的呢?第一次创建项目,company Domain我使用的是:aven.com,但是创建过程在卡在了Building 'Calculator' Gradle Project info这个过程中,于是我选择了“Cancel”第二次创建项目,我还是使用相同的项目名称和项目路_r不存在
文章浏览阅读8.9w次,点赞4次,收藏43次。前言:在Android上使用系统自带的代理,限制灰常大,仅支持系统自带的浏览器。这样像QQ、飞信、微博等这些单独的App都不能使用系统的代理。如何让所有软件都能正常代理呢?ProxyDroid这个软件能帮你解决!使用方法及步骤如下:一、推荐从Google Play下载ProxyDroid,目前最新版本是v2.6.6。二、对ProxyDroid进行配置(基本配置:) (1) Auto S_proxydroid使用教程
文章浏览阅读1.1w次,点赞4次,收藏17次。Android Studio提供了一个很实用的工具Android设备监视器(Android device monitor),该监视器中最常用的一个工具就是DDMS(Dalvik Debug Monitor Service),是 Android 开发环境中的Dalvik虚拟机调试监控服务。可以进行的操作有:为测试设备截屏,查看特定进程中正在运行的线程以及堆栈信息、Logcat、广播状态信息、模拟电话_安卓摄像头调试工具