Создание приложений на основе Windows.Form + OpenGL

[Статья не закончена]

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

Сперва добавить, потом перемешать

Начнем с того, что создадим пустую форму. Далее щелчком правой кнопки мыши, в любом пустом месте «ToolBox», откроем диалог «Choose Item…». Здесь необходимо нажать на кнопку «Browse» и указать путь к OpenTK.dll. Проверь, появился ли компонент «GLControl» на закладке «.NET Framework Components», так как это показано на рисунке.

После этого добавь компонент GLControl на твою форму, так же как и любой другой .NET компонент. На твоей форме появиться новый компонент GLControl с именем glControl1.
Сразу бросатеся в глаза то, что glControl1 содержит в себе «графический мусор», не думай, что это проблемы связаны с твоей видеокартой. Все дело в том, что под капотом GLControl происходит вызов GLContext (контекст отвечающий за прорисовку изображения), который создается только во время выполнения твоей программы.

Рецепт красоты.

Как уже было сказано, GLContext создается во время выполнения программы. Поэтому получить доступ к свойствам glControl1 можно только после создания GLContext. После запуска приложения, обратиться к glControl можно после того, как было обработано событие Load().
Выполнение команд начинающихся с GL.* возможен в любом месте программы (кроме конструктора формы).
Как проверить был ли создан контекст или нет? Одним из решением этого вопроса служит объявление переменой
bool loaded = false
которая принимает значение true, при обработке Load()

  public partial class Form1 : Form
  {
    bool loaded = false;
 
    public Form1()
    {
      InitializeComponent();
    }
 
    private void Form1_Load(object sender, EventArgs e)
    {
      loaded = true;
    }
  }

Теперь, для того чтобы избавить себя от ошибки обращения к несуществующему контексту, обращением к glControl1, добавим следующие строчки

private void glControl1_Resize(object sender, EventArgs e)
{
      if (!loaded)
        return;
}

Заводим мотор. Минимальное приложение на OpenTK

Пришло время увидеть что-нибудь на экране монитора. В разделе Using добавляем ссылки на пространство имен библиотеки OpenTK и OpenTK.Enums и реализуем обработку события OnPaint()

using OpenTK.OpenGL;
using OpenTK.OpenGL.Enums;
 
...
 
private void glControl1_Paint(object sender, PaintEventArgs e)
{
   if (!loaded) //Пока контекст не создан
     return;
 
   GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
   glControl1.SwapBuffers();
}

Скомпилируй и запусти проект. То что ты видишь это настоящий "Черный Квадрат" от создателей OpenTK.

Теперь давайте добавим немного цвета. Лучшее место для размещения кода задающего «цвет очистки» - в обработке события OnLoad()

    private void Form1_Load(object sender, EventArgs e)
    {
      loaded = true;
      GL.ClearColor(Color.SkyBlue);
    }

Немного настроек

Следующее шаг- это создание желтого треугольника. Для начала (если ты желаешь стать добропорядочным жителем страны OpenGL) установим ортографическую матрицу проекций используя GL.Ortho() и вызовем GL.Viewport().
Добавим новые строки в обработку события Load. Небольшое замечание - будем игнорировать изменение размера окна пользователем.
Для ясности код первоначальной настройки разделен на несколько частей

    private void Form1_Load(object sender, EventArgs e)
    {
      loaded = true;
      GL.ClearColor(Color.SkyBlue);
      SetupViewport();
    }
 
    private void SetupViewport()
    {
      int w = glControl1.Width;
      int h = glControl1.Height;
      GL.MatrixMode(MatrixMode.Projection);
      GL.LoadIdentity();
      GL.Ortho(0, w, 0, h, -1, 1); // Верхний левый угол имеет кооординаты(0, 0)
      GL.Viewport(0, 0, w, h); // Использовать всю поверхность GLControl под рисование
}

Между инструкциями Clear() и SwapBuffers() разместим код рисующий треугольник:

 private void glControl1_Paint(object sender, PaintEventArgs e)
    {
      if (!loaded)
        return;
 
      GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
 
      GL.MatrixMode(MatrixMode.Modelview);
      GL.LoadIdentity();
      GL.Color3(Color.Yellow);
      GL.Begin(BeginMode.Triangles);
      GL.Vertex2(10, 20);
      GL.Vertex2(100, 20);
      GL.Vertex2(100, 50);
      GL.End();
 
      glControl1.SwapBuffers();
    }

Поздравляю ! Теперь к стране OpenGL присоеднился новый гражданин.

Желание управлять

Теперь попробуем управлять треугольником с клавиатуры. Сделаем так, чтобы после нажатия на пробел, треугольник сдвигался на один пиксель вправо.
Для работы с клавиатурой возможно использовать два подхода - обрабабатывать событие Windows.Forms или использовать OpenTK KeyboardDevice. Если GLControl является небольшой частью твоего WinForms приложения, лучше обрабатать стандартное события WinForms.
Введем переменную int x=0; которая будет увеличиваться при наступлении события KeyDown, которое


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
objarni's picture

Cool, someone is actually translating the GLControl guide to russian :)

RomanKositsyn's picture

Ahha

Супер! Ждем продолжения! Могу помочь в переводе (в рамках моих знаний английского, пиши в пм).

RomanKositsyn's picture

На самом деле на этом проблемы и заканчиваются.
Всё остальное связано уже с OpenGL.
Рекомендую прочесть книгу "OpenGL суперкнига".