GL_LINES исчезают / мерцают при повороте камеры на Android с OpenGL ES 2.0

#android #opengl-es #camera #galaxy

#Android #opengl-es #камера #галактика

Вопрос:

В моем приложении для Android я использую OpenGL ES 2.0, и мне нужно показать сетку в центре сцены. У меня также есть камера, которую можно поворачивать вокруг центра сцены.

Я отрисовываю сетку, используя GL_LINES и простую шейдерную программу.

На некоторых устройствах, которые у меня есть, все работает нормально, однако на одном устройстве (в частности, Galaxy Note 10.1 2014 edition) у меня проблема с исчезновением линий сетки / мерцанием при повороте камеры, т. Е. При некоторых ракурсах камеры линии не видны.

Вот как выглядит проблема:

введите описание изображения здесь

И вот как это должно работать:

введите описание изображения здесь

Что я заметил, так это то, что похоже, что линии начинают мерцать под некоторыми углами камеры, когда их конечные точки (или начальные точки, не уверен) появляются за ближней усеченной плоскостью камеры (т. Е. За камерой). Таким образом, нет мерцания, когда камера смотрит на сетку сверху, и нет мерцания, когда камера смотрит с двух из четырех сторон или издалека.

Я пытался найти решение или возможную причину этой проблемы в течение нескольких дней, но пока ничего не нашел. Поэтому я решил спросить вас, люди. Я был бы признателен за некоторую помощь, предложения. Возможно, кто-то с опытом работы в OpenGL мог бы догадаться, что вызывает проблему из этого описания.

Также возникает вопрос, может быть, это не проблема в моем коде, а проблема с конкретным устройством, с драйвером или т. Д.? Но у меня нет способа проверить это. У меня на руках только три устройства Android, и этого, вероятно, недостаточно, чтобы сделать такой вывод наверняка.

Он отлично работает на старом Galaxy Tab 10.1 и на телефоне Lenovo P780. Однако Galaxy Note 10.1 является более новым устройством и имеет очень большое разрешение (2560 x 1600), поэтому я также думаю, что, возможно, это не из-за драйвера устройства / графического процессора, а, возможно, из-за высокого разрешения?

Другая геометрия (заполненные полигоны, а не линии) отображается нормально.

Вот мой код.

Настройка drawFrame и матриц проекта / просмотра:

     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    GLES20.glLineWidth(1f);

    float screenRatio = (float)viewportWidth / (float)viewportHeight;

    Matrix.setIdentityM(matrixProjection, 0);
    MatrixHelper.perspectiveM(matrixProjection, 0, 90, screenRatio, 0.1f, 1000f);                

    Matrix.setIdentityM(matrixView, 0);

    Matrix.translateM(matrixView, 0, 0f, 0f, -10f);        

    rotationAngle = rotationAngle   (10f * deltaSec);

    Matrix.rotateM(matrixView, 0, 45f, 1f, 0f, 0f);
    Matrix.rotateM(matrixView, 0, rotationAngle, 0f, 1f, 0f);        


    GLES20.glUseProgram(shaderGrid.ShaderProgramId);

    GLES20.glUniformMatrix4fv(shaderGrid.vProjection, 1, false, matrixProjection, 0);
    GLES20.glUniformMatrix4fv(shaderGrid.vView, 1, false, matrixView, 0);

    renderGrid.Draw(shaderGrid, origin); //see code from this method below
  

Drawing lines:

     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferIds[0]);                              
    GLES20.glVertexAttribPointer(shader.aPosition, 3, GLES20.GL_FLOAT, false, 0, 0);
    GLES20.glEnableVertexAttribArray(shader.aPosition);        

    float [] m = new float[16];

    Matrix.setIdentityM(m, 0);

    GLES20.glUniformMatrix4fv(shader.vModel, 1, false,  m, 0);            

    GLES20.glDrawArrays(GLES20.GL_LINES, 0,     10 * 2 * 4); 
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
    GLES20.glDisableVertexAttribArray(shader.aPosition);
  

Вот мой код шейдера (извините за такой формат =)):

     public String GetShaderFragmentCode()
    {        
        return
          "precision mediump float;"  
          "void main() "  
          "{"  
          "  gl_FragColor = vec4(0.7, 0.7, 0.7, 1.0);"  
          "}";            
    }

    public String GetShaderVertexCode()
    {
        return
          "uniform mat4 vProjection;"  
          "uniform mat4 vModel;"  
          "uniform mat4 vView;"  

          "attribute vec3 aPosition;"  

          "void main() "  
          "{"  
          "  gl_Position = (vProjection * vView * vModel) * vec4(aPosition.xyz, 1.0);"  
          "}";
     }
  

Вот минимальное приложение для воспроизведения проблемы (подождите, пока сетка полностью не повернется):

Скомпилированный APK

Исходный код

Я не уверен, действительно ли это помогает, потому что это зависит от конкретного устройства, но я также буду признателен за ваш отзыв в случае, если у вас возникнет такая же проблема на других устройствах. Или если у вас есть другое устройство с высоким разрешением, у которого нет этой проблемы.

И вот случайный материал, который я пытался посмотреть, повлияет ли это на проблему (но пока безуспешно, тот же результат):

  • отключить / включить GL_CULL_FACE
  • явно установите glLineWidth равным 1f или другим значениям
  • используйте glDrawElements вместо glDrawArrays
  • измените угол наклона усеченной камеры (с 0,1 f до 100f)
  • измените усеченный zFar (от 10f до очень больших значений)
  • измените vec3 на vec4 для aPosition в коде шейдера (и без преобразования с использованием .xyz)
  • используя GL_LINE_STRIP — чтобы увидеть, что произойдет, линии по-прежнему исчезают
  • использование GL_TRIANGLE_STRIP и т.д. — Полигоны не исчезают, поэтому проблема конкретно с линиями, но мне нужны линии

Я также заметил этот артефакт, когда готовил примеры:

введите описание изображения здесь

Он появляется, а затем очень быстро исчезает при повороте камеры и мерцании линий.

Комментарии:

1. Я не изучал ваш код в деталях. Но, судя по симптомам и, в частности, по фильму, мое первое предположение — проблема с драйвером. Мне кажется, что обрезка строк может быть нарушена. В качестве эксперимента или возможного обходного пути, можете ли вы попробовать рисовать линии более короткими сегментами, например, по одному сегменту для каждого квадрата сетки, вместо одной длинной линии по всей длине?

2. Спасибо за предложение. Я пробовал с более короткими сегментами, и теперь мерцает только тот, который ближе к камере. Так что, вероятно, это действительно проблема с отсечением. И теперь это выглядит лучше, если не обращать особого внимания, вы почти не видите этого. Однако я боюсь, что мне нужно будет отправить больше данных о вершинах, но, возможно, об этом глупо беспокоиться с современным оборудованием. А также все еще есть этот артефакт, как на последнем снимке, так что это не идеальное решение = ( Теперь я думаю, может быть, попытаться вычислить и скрыть ближе к сегментам камеры при перемещении камеры.

3. И все же возникает вопрос, как убедиться, что это действительно проблема с драйвером. Возможно, было бы лучше игнорировать эту проблему и не усложнять ее только для устранения проблемы с одним устройством. Может быть, просто сделайте более короткие сегменты и забудьте об этом.