Рендеринг текстур OpenTK ES 1.1

У меня есть метод, который я использую для рендеринга небольшой карты с использованием плиток, но когда я заканчиваю рендеринг и хочу сделать перевод, изменяющий переменную «transY», используя другой метод, ничего не происходит, поэтому я должен снова вызвать RenderTesture(), чтобы сделать это. Как я могу сделать это без ненужного рендеринга, потому что это может замедлить работу приложения при использовании большего количества тайлов?

void RenderTexture ()
{
    MakeCurrent ();
    GL.Clear((int)All.ColorBufferBit | (int)All.DepthBufferBit);
    GL.MatrixMode(All.Modelview);
    GL.LoadIdentity();

    GL.Translate(-transX, transY, -10);

    for (int i = 0; i < tileRows; i++) 
    {
        for (int j = 0; j < tileColumns; j++)
        {
            GL.BindTexture(All.Texture2D, textureIds [i*tileColumns + j]);
            GL.EnableClientState(All.VertexArray);
            GL.EnableClientState(All.TextureCoordArray);
            GL.PushMatrix ();
            GL.Translate(j*2, -i*2, 0);
            GL.VertexPointer(3, All.Float, 0, frontV);
            GL.TexCoordPointer(2, All.Float, 0, frontT);
            GL.DrawArrays (All.TriangleFan, 0, 4);
            GL.PopMatrix ();
        }
    }
    GL.DisableClientState(All.VertexArray);
    GL.DisableClientState(All.TextureCoordArray);

    SwapBuffers ();
}

Если у кого-то есть совет для меня, я буду очень благодарен!

Заранее спасибо!


person Bube    schedule 12.06.2014    source источник


Ответы (2)


Узкое место, скорее всего, заключается в количестве изменений состояния (GL.BindTexture) и количестве вызовов отрисовки, которые вы делаете (GL.DrawArrays). В общем, вы должны рисовать как можно больше за один вызов отрисовки.

Самый простой подход — использовать «атлас текстур»:

  1. объединить все ваши текстуры тайлов в одну большую текстуру (это "атлас текстур")
  2. объединить все вершины плитки в один массив вершин
  3. вызовите GL.BindTexture один раз, чтобы связать атлас текстуры
  4. вызовите GL.DrawArrays один раз, чтобы отобразить все плитки

Так как же визуализировать различные текстуры тайлов? Просто: вы меняете координаты текстуры вершины, чтобы они указывали на правильную плитку внутри атласа текстуры.

Один размер 1024x1024 может содержать 256 различных фрагментов размером 64x64. В зависимости от количества отдельных тайлов в вашей игре вам, возможно, придется использовать несколько текстурных атласов. Кроме того, в зависимости от размера вашей карты, вы можете разделить ее на «области» с отдельными массивами вершин для каждой (вы не хотите отображать 1 миллион плиток в каждом кадре, если ваш монитор может отображать только 1000 плиток).

Само по себе это даст ощутимый прирост производительности. Как только это заработает, вы можете получить второй большой прирост, сохранив свои массивы вершин на графическом процессоре с помощью объектов буфера вершин (VBO).

person The Fiddler    schedule 13.06.2014

Большое спасибо!

Стратегия «Текстурный атлас» может быть очень хорошей идеей. Я реализовал это прошлой ночью, и похоже, что рендеринг набирает скорость. Я уменьшил загрузку тайлов NxM, используя отдельные текстуры, загрузив одно большое растровое изображение тайлов NxM, используя одну текстуру, и я реализовал метод изменения массива вершин (в отношении новых размеров растрового изображения - NxM)

    public void UpdateFrontVertex(int rowNumber, int columnsNumber)
    {
        for (int i = 0; i < 12; i++) {
            if (i % 3 == 0)
                frontVertex [i] = defaultFrontVertex[i] * rowNumber;    // x-axis
            else if (i % 3 == 1)
                frontVertex [i] = defaultFrontVertex[i] * columnsNumber;    // y-axis
            else if (i % 3 == 2)
                frontVertex [i] = defaultFrontVertex[i];    // z-axis
        }
    }

После этого у меня есть карта!!!

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

//zoom in
transY = (transY * 2 + 1);
transX = (transX * 2 + 1);

//zoom out
transX = ((transX - 1) / 2);
transY = ((transY - 1) / 2);

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

Еще раз спасибо за большую помощь, теперь я приступлю к реализации панорамирования и масштабирования.

person Bube    schedule 15.06.2014
comment
Рад, что смог помочь. :) - person The Fiddler; 16.06.2014