OpenGL рисует тысячи 2D кругов

#java #performance #opengl #2d

#java #Производительность #opengl #2d

Вопрос:

В моем приложении я визуализирую тысячи (~ 10k) 2D кругов поверх 3D сцены. У меня это работает, но производительность очень низкая, когда кругов так много (круги маленькие, диаметром ~ 16 пикселей). Мой код для рисования кругов выглядит следующим образом:

 for ( int i = 0; i < numCircles; i  ) {
    int attributeMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT
            | GL.GL_VIEWPORT_BIT | GL.GL_CURRENT_BIT
            | GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT
            | GL.GL_ENABLE_BIT | GL.GL_LIGHTING_BIT;
    gl.glPushAttrib(attributeMask);
    gl.glMatrixMode(GL.GL_PROJECTION);
    gl.glDisable(GL.GL_LIGHTING);
    gl.glPushMatrix();
    gl.glLoadIdentity();
    gl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView()
            .getViewport().height, -1, 1);

    gl.glMatrixMode(GL.GL_MODELVIEW);
    gl.glPushMatrix();
    gl.glLoadIdentity();
    gl.glDisable(GL.GL_DEPTH_TEST);

    Vec4 screenPt // this is calculated for each circle
    double size = 16;
    gl.glTranslated(screen.x, screen.y, 0d);
    gl.glScaled(size, size, size);

    gl.glCallList(fillListId);
    gl.glCallList(outlineListId);

    gl.glMatrixMode(GL.GL_MODELVIEW);
    gl.glPopMatrix();
    gl.glMatrixMode(GL.GL_PROJECTION);
    gl.glPopMatrix();
    gl.glPopAttrib();
}
  

Списки генерируются следующим образом:

     NUM_SEGMENTS = 18;
    double[][] vertices = new double[2][NUM_SEGMENTS];
    for (int i = 0; i < NUM_SEGMENTS; i  )
    {
        double rad = -2 * Math.PI * ((double) i) / ((double) NUM_SEGMENTS);
        double x = Math.cos(rad);
        double y = Math.sin(rad);
        vertices[0][i] = x;
        vertices[1][i] = y;
    }

    gl.glNewList(id, GL.GL_COMPILE);
    gl.glBegin(GL.GL_LINE_LOOP); // 2 lists are actually created, the first time GL.GL_LINE_LOOP IS is used for the outline, and the second time GL.GL_POLYGON is used for the fill
    for (int j = 0; j < vertices[0].length; j  )
    {
        gl.glVertex2d(vertices[0][j], vertices[1][j]);
    }
    gl.glEnd();
    gl.glEndList();
  

Есть ли что-то, что я делаю здесь явно неправильно, чтобы замедлить рендеринг? Должен ли я рассмотреть возможность использования здесь вершинных буферов? Или есть другие методы для ускорения этого?

Спасибо, Джефф

Ответ №1:

Вы можете сгенерировать один круг, наложить его на текстуру, а затем просто создать поверхности (из двух треугольников), которые текстурированы с помощью этого круга.

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

1. Не могли бы вы предоставить пример того, как это сделать? Я еще не слишком продвинулся в OpenGL.

Ответ №2:

Я бы подумал, что весь этот код

 int attributeMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT
        | GL.GL_VIEWPORT_BIT | GL.GL_CURRENT_BIT
        | GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT
        | GL.GL_ENABLE_BIT | GL.GL_LIGHTING_BIT;
gl.glPushAttrib(attributeMask);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glDisable(GL.GL_LIGHTING);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView()
        .getViewport().height, -1, 1);

gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glDisable(GL.GL_DEPTH_TEST);
  

и весь этот код

 gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPopMatrix();
gl.glPopAttrib();
  

может быть выполнено вне цикла и выполнено только один раз.

Вам просто нужно будет нажать и вставить матрицу для перевода / масштабирования объекта.