OpenGL для начинающих

************************************************* Часть II ****************************************************В этой части будут только указаны исправления кода MyOpenGL.pas, которые надеюсь без труда сделаете сами, или просто общие сведения.09 Списки ========="Список - это некоторый набор команд OpenGL, который можно создать один раз, например, перед началом работы программы, а потом им пользоваться вызывая его. По логике он аналогичен процедуре (или функции, как хотите). Отличие его от процедуры в том, что при формировании списка библиотека сохраняет его в каком-то своем, оптимизированном формате и вызовы списка приводят к значительно меньшим вычислительным затратам чем вызов функции, делающей тоже самое. Особенно хорошо это заметно на картах, где операции со списками реализованы аппаратно."(Взято с http://firststeps.ru/mfc/opengl/r.php?41)Где-то до использования MyOpenGL.glDraw (напр. в MyOpenGL.glInit)

// Глобальная переменная для MyOpenGL.pas
var
 MyList: GLuint;
...
 // указываем, что в списке два набора команд
 MyList := glGenLists(2);
 // Создаем первый набор команд
 // Флаг GL_COMPILE указывает что его надо только создать
 // Использование GL_COMPILE_AND_EXECUTE сразу же еще и выполнило бы этот набор
 // В первом наборе будем рисовать треугольник
 glNewList(MyList, GL_COMPILE);
  glBegin(GL_POLYGON);
  glVertex3F(0.0, 0.0, 0.0);
  glVertex3F(100.0, 0.0, 0.0);
  glVertex3F(50.0, sqrt(3)*50, 0.0);
  glEnd;
 // Указываем что завершили создание набора команд
 glEndList();
 // Создаем второй набор команд
 // Во втором наборе к матрице GL_MODELVIEW будет добавляться параллельный
 // перенос на 50 по оси OX и на 1 по оси OZ (это чтобы поверх остального)
 // Поставить переменные значения в перенос нельзя, так как это будет уже
 // другая матрица. Хотя может я и ошибаюсь.
 glNewList(MyList + 1, GL_COMPILE);
  glTranslatef(50, sqrt(3) * 12.5, 1);
 // Указываем что завершили создание набора команд
 glEndList();
MyOpenGL.glDraw можно переписать так. В итоге получим, что рисуется одна неподвижная фигура (зеленая), а другая вращающаяся, выполненая как и первая, и перенесенная в центр первой и на уровень выше первой (красная).
procedure glDraw();
begin
 // очистка Экрана и буфера глубины
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 // Сбрасываем GL_MODELVIEW до единичной
 glLoadIdentity();
 // Устанавливаем зеленый цвет для фигур
 glColor(0.0, 1.0, 0.0, 1);
 // Создаем фигуру, используя набор команд MyList
 glCallList(MyList);
 // Добавляем значение к углу поворота
 Angle := (Angle + 5) mod 360;
 // Вызываем второй набор команд, который хранится по MyList + 1
 // В результате к GL_MODELVIEW добавляется перенос
 glCallList(MyList + 1);
 // Добавим к GL_MODELVIEW-матрице еще и поворот на угол Angle
 glRotate(Angle, 0.0, 0.0, 1.0);
 // Устанавливаем красный цвет для фигур
 glColor(1.0, 0.0, 0.0, 1);
 // Создаем фигуру, используя набор команд MyList
 // Поскольку GL_MODELVIEW-матрица у нее другая, то и распалагается
 // она уже иначе, чем первая фигура
 glCallList(MyList);
 // Выводим на экран подготовленную сцену
 SwapBuffers(DC);
end;
Ну и в MyOpenGL.glKill стоит добавить
glDeleteLists(MyList, 2); // удаляем все элементы списка :-)
Примечание: устоявшееся понятие "список отображениия" - список, в котором все наборы команд - это рисование фигуры (шаблон). См. Народный учебник, Глава 12.10 Собранный пример WinAPI без таймера для отрисовки====================================================Взято у Jan Horn (http://www.sulaco.co.za, http://home.global.co.za/~jhorn)Как обычно, в папке проекта есть MYOpenGL.pas и 1.bmp :-)Идеи таковы: * пока приложение не обработает всю свою очередь сообщений, перерисовкавыполняться не будет;* Если нажали кнопку, то в массиве "Статус кнопок" для соответсвующего элемента выстанавливается значение True, которое скинется послеобработки этого нажатия в ProcessKey. Такая схема позволяет запретитьнакопление нажатий.
program a;
uses
 windows,
 messages,
 MyOpenGL in 'MyOpenGL.pas';
var
 MainWnd: hWND;
 FPSCount: Integer; // Число FPS
 keys : array [0..255] of Boolean; // Статусы кнопок
function IntToStr(Num: Integer) : String;
begin
 Str(Num, result);
end;
// Обработка кнопок
procedure ProcessKeys;
begin
 if (keys[VK_UP]) then
 begin
  // Что-то делаем
  //...
  // Сбрасываем нажатие этой кнопки
  keys[VK_UP] := False;
 end;
 if Keys[Ord('H')] then
 begin
  // Что-то делаем
  //...
  // Сбрасываем нажатие этой кнопки
  Keys[Ord('H')] := FALSE;
 end;
end;
function WindowProc(Wnd: HWND; Msg: Integer; wParam: wParam; lParam:lParam):lResult;stdcall;
begin
 case Msg of
  WM_DESTROY:
  begin
  glKill(MainWnd);
  postquitmessage(0);
  Result := 0;
  exit;
  end;
  WM_KEYDOWN:
  begin
  keys[wParam] := True;
  Result := 0;
  end;
  WM_KEYUP:
  begin
  keys[wParam] := False;
  Result := 0;
  end;
  WM_TIMER:
  begin
  FPSCount := Round(FPSCount * 1000/{FPS-интервал - у нас 1с}1000);
  SetWindowText(MainWnd, PChar('FPS: ' + IntToStr(FPSCount)));
  FPSCount := 0;
  end;
  WM_SIZE:
  begin
  glOnResize(loWord(lParam), hiWord(lParam));
  Result := 0;
  end;
  else
  Result := DefWindowProc(Wnd, Msg, wParam, lParam);
 end;
end;
var
 Mesg: TMsg;
 wc : TWndClassEx;
 finished: Boolean = False; // Флаг завершения работы OpenGL
begin
 wc.cbSize := sizeof(wc);
 wc.style := CS_HREDRAW or CS_VREDRAW;
 wc.lpfnWndProc := @WindowProc;
 wc.cbClsExtra := 0;
 wc.cbWndExtra := 0;
 wc.hInstance := hInstance;
 wc.hIcon := LoadIcon(0, IDI_WINLOGO);
 wc.hCursor := LoadCursor(0, IDC_ARROW);
 wc.hbrBackground := COLOR_BTNFACE + 2;
 wc.lpszMenuName := nil;
 wc.lpszClassName := 'aWnd';
 RegisterClassEx(wc);
 // Создаем окно 400х400
 MainWnd := CreateWindowEx (0, 'aWnd', 'MyOpenGL', WS_OVERLAPPEDWINDOW or WS_VISIBLE, 100, 100, 400, 400, 0, 0, hInstance, nil);
 // Создаем контекст воспроизведения OpenGL и его параметры
 glInit(MainWnd);
 // Задаем матрицы OpenGL для размера окна 400х400
 glOnResize(400, 400);
 // Устанавливаем таймер на 1с для отображения FPS в заголовке окна
 SetTimer(MainWnd, 1, 1000, nil);
 while not finished do
 begin
  // Если очередь сообщений для окна пуста, то проводим
  // расчет и отрисовку сцены, иначе обрабатываем
  // очередь сообщений
  if (PeekMessage(Mesg, 0, 0, 0, PM_REMOVE)) then
  begin
  // Если было получено WM_QUIT, то выход
  if (Mesg.message = WM_QUIT) then
  finished := True
  else
  begin
  TranslateMessage(Mesg);
  DispatchMessage(Mesg);
  end;
  end
  else
  begin
  // Увеличиваем счетчик отрисованных кадров
  Inc(FPSCount);
  // Рисуем-с кадр
  glDraw();
  // Если была до этого нажата ESC, то сразу выходим
  if (keys[VK_ESCAPE]) then
  finished := True
  else
  ProcessKeys;
  end;
 end;
end.

Очень сильно помогло для вывода текста. Спасибо.

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...