2016-10-09 2 views
0

Я следил за учебником SharpGL, который может отображать вращающийся блок. Первоначально у этого были только цвета по умолчанию, нарисованные на нем gl.Color(r, g, b). После этого я попытался текстурировать куб с помощью uv-карты.Плохая производительность sharpGL внутри WPF

Когда я запускаю полноэкранный режим приложения, только окрашивая куб (с компонентом sharpGL, покрывающим всю внутреннюю часть приложения), я получаю 70 ~ 80 кадров в секунду только для отображения цветного куба. Когда я включаю OpenGL.GL_TEXTURE_2D и рисую текстуры на единичном кубе, я получаю 8 ~ 9 кадров в секунду.

Всякий раз, когда растровое изображение загружается для использования в качестве текстуры, оно сохраняется в памяти. Это падение кадров возникает только после включения OpenGL.GL_TEXTURE_2D и вызова gl.TexCoord(c1, c2) для всех координат. Фактически перемещение объекта с gl.Rotate(angle, x, y, z) не оказывает заметного влияния на производительность.

Предоставляемые данные для метода, включая GetBlockUv и CubeCoordinates, являются статическими массивами с плавающей запятой.

Предполагается, что SharpGL выполняет это плохо (т. Е. При отображении сингулярного куба), или есть еще одна причина? Я делаю что-то неправильно, что влияет на производительность? Является ли применение текстур, которые могут повлиять на производительность?

Основной розыгрыш событий происходит в блоке:

public void DrawBlock(object sender, OpenGLEventArgs args) 
    { 
     // Get the OpenGL instance that's been passed to us. 
     OpenGL gl = args.OpenGL; 

     // Reset the modelview. 
     gl.LoadIdentity(); 

     // Move the block to its location 
     gl.Translate(Coord.X, Coord.Y, Coord.Z); 

     gl.Rotate(angle, 1.0f, 1.0f, 0.5f); 
     angle += 3; 

     // retrieve the right texture for this block and bind it. 
     Texture blockTex = BlockTexture.GetBlockTexture(gl, _type); 
     blockTex.Bind(gl); 

     // retrieve the uv map for this block 
     float[] uv = BlockTexture.GetBlockUv(_type); 

     // retrieve the coordinates for a cube 
     float[] cube = CubeCoordinates(); 


     gl.Enable(OpenGL.GL_TEXTURE_2D); 

     // Draw the cube with the bound texture. 
     gl.Begin(OpenGL.GL_QUADS); 
     // 
     // 
     // Begin by allowing all colors. 
     gl.Color(1.0f, 1.0f, 1.0f); 

     // since the uv index increments with 2 each time, we will be keeping track of this separately. 
     int uvInd = 0; 

     // i denotes the current coordinate. Each coordinate consists of 3 
     // values (x, y, z), thus letting us skip 3. 
     // 
     // Seeing as we are creating quads, it is expected that cube.Length 
     // is 3 * 4 * N (where n is a whole number) 
     for (int i = 0; i < cube.Length; i += 3) 
     { 
      // color experiment 
      //if (i < cube.Length/3) 
      //{ 
      // gl.Color(1.0f, 0.00f, 0.00f); 
      //} 
      //else if (i < 2 * (cube.Length/3)) 
      //{ 
      // gl.Color(0.0f, 1.0f, 0.0f); 
      //} 
      //else 
      //{ 
      // gl.Color(0.0f, 0.0f, 1.0f); 
      //} 

      try 
      { 
       // set the coordinate for the texture 
       gl.TexCoord(uv[uvInd], uv[uvInd + 1]); 

       // set the vertex 
       gl.Vertex(cube[i], cube[i + 1], cube[i + 2]); 
      } 
      catch (IndexOutOfRangeException e) 
      { 
       throw new IndexOutOfRangeException(
        "This exception is thrown because the cube map and uv map do not match size"); 
      } 

      // increment the uv index 
      uvInd += 2; 
     } 

     gl.End(); 
     gl.Disable(OpenGL.GL_TEXTURE_2D); 
    } 

OpenGL инициализирован в другом месте

private void OpenGLControl_OpenGLDraw(object sender, OpenGLEventArgs args) 
    { 
     // Get the OpenGL instance that's been passed to us. 
     OpenGL gl = args.OpenGL; 

     // Clear the color and depth buffers. 
     gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); 


     // call the draw method of the GameRunner if the 
     // GameRunner has already been created. 
     game?.DrawOpenGL(sender, args); 


     // Flush OpenGL. 
     gl.Flush(); 
    } 

    private void OpenGLControl_OpenGLInitialized(object sender, OpenGLEventArgs args) 
    { 
     // Enable the OpenGL depth testing functionality. 
     args.OpenGL.Enable(OpenGL.GL_DEPTH_TEST); 
    } 

Все промежуточный GameRunner делает прямо сейчас называть DrawBlock рутина.

Что я хотел бы знать, это некоторое понимание производительности, которую я могу ожидать от openGL/sharpGL и есть ли лучшие альтернативы. Я хотел бы продолжать использовать архитектуру WPF, окружающую игру, но если openGL внутри WPF больше понимается как трюк, это может быть не лучший способ действий.

ответ

1

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

Я не знаю, как включить аппаратное ускорение, так что я действительно не знаю, как исправить проблему.

+0

Согласно http://www.dwmkerr.com/sharpgl-2-0-hardware-acceleration/, он должен быть исправлен в SharpGL 2.0 с использованием другого поставщика контекста Render. Я еще не пытался реализовать это, но это объясняет производительность. Спасибо за ваше время, чтобы ответить. – bas

Смежные вопросы