opengl es - Android GLES 2 draw line flicker and strange effects -


i trying draw 3d lines in android using gles 2. resulted in strange effects. flicker happens when rotate scene/camera. not that, there lines drawn in 2d (sometime dots) @ random. screenshot: enter image description here

while image shows no problem @ (using different camera angle): enter image description here

i've tried use gles 1 draw these lines , worked (no flicker or random lines). perhaps have shader code? vertex shader taken android gles example simple.

update: after more tries, found happens when camera yaw (y axis rotary) more 90 degree. within range of 0-90 yaw, lines display normally. doing wrong? i'm running program on galaxy tab s android v4.4.2.

here whole code used reproduce erroneous image:

main activity:

package com.mycompany.bug_test;  import android.opengl.glsurfaceview; import android.support.v7.app.actionbaractivity; import android.os.bundle;  public class opengles20activity extends actionbaractivity {      private glsurfaceview mglview = null;      @override     protected void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);          if ( mglview == null ) {             mglview = new myglsurfaceview(this);         }         setcontentview(mglview);     } } 

surface view:

package com.mycompany.bug_test;  import android.content.context; import android.opengl.glsurfaceview; import android.view.motionevent;  class myglsurfaceview extends glsurfaceview {      private final myglrenderer mrenderer;      public myglsurfaceview(context context) {         super(context);          seteglcontextclientversion(2);          mrenderer = new myglrenderer();         setrenderer(mrenderer);     }      private final float touch_scale_factor = 360.0f;     private float mpreviousx;     private float mpreviousy;      @override     public boolean ontouchevent(motionevent e) {          float x = e.getx();         float y = e.gety();          int action_type = e.getaction();         if ( action_type ==  motionevent.action_move ) {             float dx = x - mpreviousx;             float dy = y - mpreviousy;              final float div_mag = 10;             float min_dx = dx;             if ( min_dx > (getrootview().getwidth()/div_mag) ) {min_dx = (getrootview().getwidth()/div_mag);}             if ( min_dx < -(getrootview().getwidth()/div_mag) ) {min_dx = -(getrootview().getwidth()/div_mag);}             float min_dy = dy;             if ( min_dy > (getrootview().getheight()/div_mag) ) {min_dy = (getrootview().getheight()/div_mag);}             if ( min_dy < -(getrootview().getheight()/div_mag) ) {min_dy = -(getrootview().getheight()/div_mag);}              float new_yaw = (  mrenderer.cam_yaw - (min_dx * touch_scale_factor / getrootview().getwidth())  ) % 360;             float new_pitch = mrenderer.cam_pitch + (min_dy * touch_scale_factor / getrootview().getheight());             if ( new_pitch > 89 ) {                 new_pitch = 89;             }             if ( new_pitch < -89 ) {                 new_pitch = -89;             }               synchronized (mrenderer.cam_lock) {                 mrenderer.cam_yaw = new_yaw;                 mrenderer.cam_pitch = new_pitch;             }             system.out.println("yaw=" + new_yaw + "   pitch=" + new_pitch);         }          mpreviousx = x;         mpreviousy = y;         return true;     } } 

and important part, gl renderer:

package com.mycompany.bug_test;  import android.opengl.gles20; import android.opengl.glsurfaceview; import android.opengl.matrix;  import java.nio.bytebuffer; import java.nio.byteorder; import java.nio.floatbuffer;  import javax.microedition.khronos.egl.eglconfig; import javax.microedition.khronos.opengles.gl10;  public class myglrenderer implements glsurfaceview.renderer {      private final string vertexshadercode =             "uniform mat4 umvpmatrix;" +             "attribute vec4 vposition;" +             "void main() {" +             "   gl_position = umvpmatrix * vposition;" +             "}";      private final string fragmentshadercode =             "precision mediump float;" +             "uniform vec4 vcolor;" +             "void main() {" +             "   gl_fragcolor = vcolor;" +             "}";      private int mprogram;      private int mmvpmatrixhandle;     private int mpositionhandle;     private int mcolorhandle;        private final float[] mprojectionmatrix = new float[16];     private final float[] mviewmatrix = new float[16];     float viewaspect;     float fovy = 45;     float fovx = 45;      final object cam_lock = new object();     float cam_pos_x = 0;     float cam_pos_y = 0;     float cam_pos_z = 0;     float fcs_pos_x = 0;     float fcs_pos_y = 0;     float fcs_pos_z = 0;     //try yaw=246.22672   pitch=21.992342 cam_focus_range = 175 visible error.     float cam_pitch = 21.992342f;     float cam_yaw = 246.22672f;     float cam_focus_range = 175;        final float line_gap = 100;     final float line_length = 6000;      private final int coords_per_vertex = 3;     private final int vertexstride = coords_per_vertex * 4; // 4 bytes per vertex      private floatbuffer vertexbuffer;     private int vertexcount = 0;       public myglrenderer() {         float[] gmrklines = new float[(int)( (line_length / line_gap) + 1 ) * 2 * 2 * coords_per_vertex ];          int __p = 0;         (int ln=0; ln<( (line_length / line_gap) + 1 ); ln++) {             gmrklines[__p++] = (float)(line_length /2);                             //x             gmrklines[__p++] = 0;                                                   //y             gmrklines[__p++] = (float)(line_gap *ln - line_length /2);              //z             vertexcount++;             gmrklines[__p++] = (float)(-line_length /2);                            //x             gmrklines[__p++] = 0;                                                   //y             gmrklines[__p++] = (float)(line_gap *ln - line_length /2);              //z             vertexcount++;              gmrklines[__p++] = (float)(line_gap *ln - line_length /2);              //x             gmrklines[__p++] = 0;                                                   //y             gmrklines[__p++] = (float)(line_length /2);                             //z             vertexcount++;             gmrklines[__p++] = (float)(line_gap *ln - line_length /2);              //x             gmrklines[__p++] = 0;                                                   //y             gmrklines[__p++] = (float)(-line_length /2);                            //z             vertexcount++;         }          system.out.println("vertex count=" + vertexcount);          {             bytebuffer bb = bytebuffer.allocatedirect(gmrklines.length * 4);             bb.order(byteorder.nativeorder());             vertexbuffer = bb.asfloatbuffer();             vertexbuffer.put(gmrklines);             vertexbuffer.position(0);         }     }       @override     public void onsurfacecreated(gl10 unused, eglconfig config) {         int vertexshader = myglrenderer.loadshader(gles20.gl_vertex_shader, vertexshadercode);         int fragmentshader = myglrenderer.loadshader(gles20.gl_fragment_shader, fragmentshadercode);         mprogram = gles20.glcreateprogram();          gles20.glattachshader(mprogram, vertexshader);         gles20.glattachshader(mprogram, fragmentshader);         gles20.gllinkprogram(mprogram);          gles20.gluseprogram(mprogram);          mmvpmatrixhandle = gles20.glgetuniformlocation(mprogram, "umvpmatrix");         mpositionhandle = gles20.glgetattriblocation(mprogram, "vposition");         mcolorhandle = gles20.glgetuniformlocation(mprogram, "vcolor");          gles20.gluniform4fv(mcolorhandle, 1, new float[]{0.3f, 0.3f, 0.3f, 1}, 0);           gles20.glclearcolor(0.0f, 0.0f, 0.0f, 1.0f);         gles20.glenable( gles20.gl_depth_test );         gles20.gldepthfunc( gles20.gl_lequal );         gles20.gllinewidth(4);     }      @override     public void ondrawframe(gl10 unused) {         float _cam_pos_x;         float _cam_pos_y;         float _cam_pos_z;         float _fcs_pos_x;         float _fcs_pos_y;         float _fcs_pos_z;         float _cam_pitch;         float _cam_yaw;         synchronized (cam_lock) {             _cam_pos_x = cam_pos_x;             _cam_pos_y = cam_pos_y;             _cam_pos_z = cam_pos_z;             _fcs_pos_x = fcs_pos_x;             _fcs_pos_y = fcs_pos_y;             _fcs_pos_z = fcs_pos_z;             _cam_pitch = cam_pitch;             _cam_yaw = cam_yaw;         }           gles20.glclear(gles20.gl_color_buffer_bit | gles20.gl_depth_buffer_bit);           _fcs_pos_x = 0;         _fcs_pos_y = 0;         _fcs_pos_z = 0;         _cam_pos_y = (float) ( _fcs_pos_y + (cam_focus_range * math.sin( math.toradians(_cam_pitch) )));         double cam_to_focus_horz = cam_focus_range * math.cos( math.toradians(_cam_pitch) );         _cam_pos_x = (float) ( _fcs_pos_x + (cam_to_focus_horz * math.cos( math.toradians(_cam_yaw) )));         _cam_pos_z = (float) ( _fcs_pos_z + (cam_to_focus_horz * math.sin( math.toradians(_cam_yaw) )));          matrix.setlookatm(mviewmatrix, 0, _cam_pos_x, _cam_pos_y,_cam_pos_z, _fcs_pos_x, _fcs_pos_y, _fcs_pos_z, 0, 1, 0);           {             float[] mmvpmatrix = new float[16];             matrix.multiplymm(mmvpmatrix, 0, mprojectionmatrix, 0, mviewmatrix, 0);             gles20.gluniformmatrix4fv(mmvpmatrixhandle, 1, false, mmvpmatrix, 0);              gles20.glenablevertexattribarray(mpositionhandle);              gles20.glvertexattribpointer(mpositionhandle, coords_per_vertex, gles20.gl_float, false,                     vertexstride, vertexbuffer);             gles20.gldrawarrays(gles20.gl_lines, 0, vertexcount);              gles20.gldisablevertexattribarray(mpositionhandle);         }     }      @override     public void onsurfacechanged(gl10 unused, int width, int height) {         if (height <= 0) { // avoid divide 0 error!             height = 1;         }         viewaspect = (float) width / (float) height;         fovx = fovy * viewaspect;          gles20.glviewport(0, 0, width, height);         glu_perspective(mprojectionmatrix, 0, fovy, viewaspect, 1.0f, 8000.0f);     }       public static int loadshader(int type, string shadercode) {         int shader = gles20.glcreateshader(type);          gles20.glshadersource(shader, shadercode);         gles20.glcompileshader(shader);          int[] _param = new int[4];         gles20.glgetshaderiv(shader, gles20.gl_compile_status, _param, 0);         system.out.println("shader no : " + shader);         system.out.println("compile status = " + _param[0] + "   (gl_true=" + gles20.gl_true + ")");         system.out.println("err : " + gles20.glgetshaderinfolog(shader));          return shader;     }      void glu_perspective(float[] retmtx, int offset, float fovy, float aspect, float znear, float zfar)     {         float fw, fh;          fh = (float) (math.tan(fovy / 360 * math.pi) * znear);         fw = fh * aspect;          matrix.frustumm(retmtx, offset, -fw, fw, -fh, fh, znear, zfar );     } } 

i experienced same problem samsung devices (i had 3 of them showing same issues). turned out drawing lines gl_line_strip or gl_lines results in artefacts , flickering show in screenshots. if line traverses camera plane , if first coordinate of line behind camera's plane , second coordinate in front of camera's plane. when it's other way round - no problem.

in opinion not make sense @ , seems driver problem - there no error in code.

as workaround let vertex shader detect constellation , flip vertices. detection done checking sign of matrice's z-scaling component [2][2]. in case vertices {0,0,1} , {0,0,-1} - flipping can done negating vertex values.

// vertex shader snippet cposition = vposition; vomatrix = viewmatrix * objmatrix; if ( vomatrix [2][2] < 0.0 ) cposition = -vposition; 

i hope helps (even if answer comes in quite late).


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -