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

OpenGL для начинающих Решив разобраться с OpenGL и просмотрев DRBK, я увидел печальную картину - то что там есть никак не дает пинка в нужном направлении для написания программ,использующих OpenGL. Ниже я постарался собрать в пучок результаты моих исследований и получил этот текст и MyOpenGL.pas. Я совсем не претендую на правильность терминов в описании и на то, как надо писать OpenGL-программы. Но простую OpenGL-программу вы точно сможете написать, использовав MyOpenGL.pas, после прочтения нижеследующего, как на VCL, так и на чистом WinAPI.Может кому пригодится для начала - написанное достаточно просто >:-)Были использованы следующие источники* Исходники Jan Horn (http://www.sulaco.co.za, http://home.global.co.za/~jhorn)В частности Skyboxes и Гаусово размытие. Второе уже есть в DRKB без имени автораРабота с графикой и мультимедиа > DerectX, OpenGL > OpenGL - радиальное размытие (названия функций, основа программы и много другое взяты оттуда).* Учебник по OpenGL (главы 1.3, 1.5) с www.ru-coding.com.* MS SDK > OpenGL Programmer's Reference, поставляемый вместе с Delphi (общая справка)* модуль EasyGL.pas Данилова Андрея (http://dasoft.land.ru)(своровал пару идей по оформлению VCL).* Статья по рисованию вращающего сердечка на OpenGL (не помню где брал).* Перевод Народного учебника по OpenGL от NeHe (http://nehe.gamedev.net). Брать тут - http://pmg.org.ru/nehe/nehehtml.zip(ну очень хороший учебник, хоть и на C; must see).01 Контексты устройства и воспроизведения========================================="DC (Device Context - контекст устройства). Это то, на чём мы рисуем, и в Delphi контекст устройства представлен как TCanvas" (см. 1)Получить его можно следующим образом

var
 DC: hDC;
...
 DC := GetDC(Form1.Hanle);
или
 DC := Form1.Canvas.Handle;
"Графическая система OpenGL, как и любое другое приложение Windows, также нуждается в ссылке на окно, на котором будет осуществляться воспроизведение - специальной ссылке на контекст воспроизведения - величина типа HGLRC (Handle openGL Rendering Context, ссылка на контекст воспроизведения OpenGL). Для получения этого контекста OpenGL нуждается в величине типа HDC (контекст воспроизведения) окна, на который будет осуществляться вывод."Создать его можно следующим образом
uses OpenGL;
...
var
 DC: hDC;
 RC: hGLRC;
...
 DC := GetDC(Form1.Handle); // получаем контекст устройства
 SetDCPixelFormat(DC); // устанавливаем формат точки (см. 2)
 RC := wglCreateContext(DC); // создать новый контекст воспроизведения
 wglMakeCurrent(DC, RC); // устанавливаем его текущим
Здесь SetDCPixelFormat(DC) самописная функция, код см. в MyOpenGL.pas.Дополнительно 1. Работа с графикой и мультимедиа > GDI - графика в Delphi2. Работа с графикой и мультимедиа > DerectX, OpenGL > Работа с OpenGL - Введение 3. Работа с графикой и мультимедиа > DerectX, OpenGL > Работа с OpenGL - Минимальная программа 02 Инициализация и завершение работы с OpenGL=============================================Поскольку часть операций при инициализации зависит от размеров окна и должна повторятьсяпри каждом изменении размеров окна, то эта часть вынесена в отдельную процедуру, которая выполняется при инициализации и при изменении размеров окна.
{------------------------------------------------------------------}
{ Инициализация OpenGL }
{------------------------------------------------------------------}
procedure glInit(Wnd: hWND);
const
 // Константы, задающие свойства материала фигур
 mat1_amb : array [0..2] of Single = (0.2, 0.2, 0.2);
 mat1_dif : array [0..2] of Single = (0.8, 0.8, 0.0);
 mat1_spec: array [0..2] of Single = (0.6, 0.6, 0.6);
 mat1_shininess = 10;
 // Константы для источника света
 light_pos : array [0..3] of glFloat=(100.0, 100.0, 0.0, 1.0);
 light_amb : array [0..3] of glFloat=(0.6, 0.6, 0.6, 1.0);
 light_dif : array [0..3] of glFloat=(1.0, 1.0, 1.0, 1.0);
 light_spec : array [0..3] of glFloat=(1.0, 1.0, 1.0, 1.0);
 light_spot_direction : array [0..3] of glFloat=(1.0, 1.0, 1.0, 1.0);
 // Цвет тумана
 fogColor: array [0..3] of GLfloat = (0, 1.0, 0, 1.0);
var
 fogMode: GLint;
begin
 // Инициализация контекста воспроизведения OpenGL
 DC := GetDC(Wnd); // Получить контекст устройства для окна
 SetDCPixelFormat(DC); // Установить формата пикселов
 RC := wglCreateContext(DC); // создать новый контекст воспроизведения
 wglMakeCurrent(DC, RC); // Установить его текущим
 // Свойства материала для режима glEnable(GL_COLOR_MATERIAL)
 glMaterialfv(GL_FRONT, GL_AMBIENT, @mat1_amb);
 glMaterialfv(GL_FRONT, GL_DIFFUSE, @mat1_dif);
 glMaterialfv(GL_FRONT, GL_SPECULAR, @mat1_spec);
 glMaterialf (GL_FRONT, GL_SHININESS,mat1_shininess);
 // Свойства источника света GL_LIGHT1 для режима glEnable(GL_LIGHTING)
 // Стандартный источник одна команда: glEnable(GL_LIGHT0);
 glLightfv(GL_LIGHT1, GL_POSITION,@light_pos);
 glLightfv(GL_LIGHT1, GL_AMBIENT, @light_amb); // направленность
 glLightfv(GL_LIGHT1, GL_DIFFUSE, @light_dif); // рассеивание
 glLightfv(GL_LIGHT1, GL_SPECULAR, @light_spec);
 glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, @light_spot_direction);
 // разрешить источник света GL_LIGHT1
 glEnable(GL_LIGHT1);
 // Свойства тумана для режима glEnable(GL_FOG)
 fogMode := GL_EXP; // GL_EXP2, GL_LINEAR
 glFogi(GL_FOG_MODE, fogMode); // установить режим
 glFogfv(GL_FOG_COLOR, @fogColor); // цвет тумана
 glFogf(GL_FOG_DENSITY, 0.002); // плотность - 0.2%
 glHint(GL_FOG_HINT, GL_DONT_CARE); // GL_NICEST, GL_FASTEST.
 glClearColor(0.0, 0.0, 0.2, 1.0); // Установить цвет фона - синий
 glClearDepth(1.0); // Очистить буфер глубины
 glDepthFunc(GL_LESS); // Тип теста глубины
 glShadeModel(GL_SMOOTH); // плавное цветовое сглаживание

 // glEnable(..) - включить режим, glDisable(..) - отключить
 glEnable(GL_LIGHTING); // разрешить осещенность
 //glEnable(GL_FOG); // разрешить тумана
 glEnable(GL_DEPTH_TEST); // разрешить тест глубины, с использованием
  // функции определенной в glDepthFunc
 glEnable(GL_NORMALIZE); // разрешить нормали (различение передней
  // и задней сторон плоских объектов)
 glEnable(GL_COLOR_MATERIAL); // разрешить использование материалов на объектах
 glEnable(GL_TEXTURE_2D); // разрешить наложение текстур
 //glEnable(GL_BLEND); // разрешить смешивание (напр. прозрачность)
  // не совместимо с glEnable(GL_DEPTH_TEST)
 glLoadTexture('1.bmp', Texture); // загружаем текстуру
end;

{------------------------------------------------------------------}
{ Обработчик на изменение размеров окна }
{------------------------------------------------------------------}
procedure glOnResize(Width, Height: Integer);
begin
 if (Height = 0) then Height := 1; // Предупреждаем деление на 0
 glViewport(0, 0, Width, Height); // Устанавливаем область отображения
  // на все окно
 // Настройка матрицы проекции
 glMatrixMode(GL_PROJECTION); // Выбираем матрицу проекции
 glLoadIdentity(); // Устанавливаем ее единичной
 // Устанавливаем тип проеции - Ортогональный
 glOrtho(-Width div 2, Width div 2, -Height div 2, Height div 2, -800, 800);
 // Настройка видовой матрицы
 glMatrixMode(GL_MODELVIEW); // Выбираем матрицу проекции
 glLoadIdentity(); // Устанавливаем ее единичной
end;
Инициализация OpenGL производится последовательным вызовом этих двух процедур - сначала gLInit (в ее начале происходит создание контекста воспроизведения, упомянутогов первой главе), а потом glOnResize.Отмечу, что включение/выключение режимов можно делать когда угодно, а не только приинициализации.Завершение работы с OpenGL проводит функция glKill.
{------------------------------------------------------------------}
{ Завершение работы с OpenGL }
{------------------------------------------------------------------}
procedure glKill(Wnd: hWND);
begin
 wglMakeCurrent(DC, 0);
 wglDeleteContext(RC);
 ReleaseDC(Wnd, DC);
end;
03 Создание и рисование примитивов==================================Ниже будет описан процесс отрисовки, использующий таймер. Сначала подготавливаем объекты сцены процедурой сферу и треугольник, апотом командой SwapBuffers(..) выводим сцену на экран.Для улучшения понимания здесь порезанный вариант MyOpenGL.glDraw.
{------------------------------------------------------------------}
{ Создание объектов под отрисовку }
{------------------------------------------------------------------}
procedure glDraw();
var
 Obj: GLUquadricObj;
begin
 // очистка Экрана и буфера глубины
 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 ...
 // Пример рисования разноцветного треугольника
 glBegin(GL_POLYGON);
  glColor(0.0, 0.5, 0.0, 0.0);
  glVertex3F(-50, -sqrt(3)*50, 0); // 1-я вершина
  glColor(0.5, 0.0, 0.0, 0.0);
  glVertex3F(-100, -sqrt(3)*100, 0); // 2-я вершина
  glColor(0.0, 0.0, 0.5, 0.0);
  glVertex3F(-125, -sqrt(3)*100, 0); // 3-я вершина
 glEnd;
 ...
 // Пример рисования сферы
 glColor(1.0, 1.0, 1.0, 0.5); // установить цвет объекта
 Obj := gluNewQuadric;
 gluSphere(Obj, 100, 25, 25); // создать сферу R = 100, детализация - 25х25
 ...
 // Выводим на экран подготовленную сцену
 SwapBuffers(DC);
end;
По таймеру выполняем
glDraw();
gluNewQuadric используется для создания объемных фигур одной командой
var
 Obj : GLUquadricObj;
...
 Obj := gluNewQuadric;
 // Режимы отображения фигуры
 gluQuadricDrawStyle(Obj, GLU_FILL); // GLU_POINT, GLU_LINE, GLU_SILHOUETTE
 gluQuadricOrientation (Obj, GLU_INSIDE); // GLU_OUTSIDE
 gluQuadricNormals (Obj, GLU_SMOOTH); // - нормаль для каждой точки
  // GLU_FLAT - для сегмента
  // GLU_NONE - не строить нормалей
 gluQuadricTexture(Obj, GL_TRUE); // - разрешить наложение текущей текстуры
 // Создание фигуры
 gluSphere(Obj, 100, 25, 25); // сфера R = 100, детализация - 25х25
или
 gluCylinder(Obj, 10, 100, 150, 30, 1); // цилиндр - R0 = 10, R1 = 100, H = 150, детализация - 30 плоскостей
или
 gluDisk(Obj, 10, 100, 30, 1); // Диск - R0 = 10, R1 = 100, детализация - 100
или
 gluPartialDisk(Obj, 10, 100, 30, 100, 0, 120); // треть диска с параметрами как у верхнего
...
 //Освобождаем память
 gluDeleteQuadric(Obj);
Quadric-объекты являются надстройкой над конструкцией glBegin-glEnd.Для glBegin определены следующие константы(подробнее см. SDK OpenGL)GL_POINTS - последовательность точекGL_LINES - линии (пара точек; пара точек) GL_LINE_STRIP - ломаная (аналог последовательности lineto)GL_LINE_LOOP - замкнутая GL_TRIANGLES - треугольникGL_TRIANGLE_STRIP - объединенная группа треугольниковGL_TRIANGLE_FANGL_QUADS - четырехугольникGL_QUAD_STRIP - объединенная группа четырехугольниковGL_POLYGON - плоский полигон Так же стоит обратить внимание на glPolygonMode, позволяющий по различному отображатьстроемую фигуру (см. код для Quadric)04 Преобразования координат и проекции====================================== Цитата Q: Возникла такая ситуация. Есть несколько объектов. Hyжно повеpнyтьнекотоpые из них. Функция glRotate() повоpачивает всю сценy. Сyществyетли функция, котоpая повоpачивает только некотоpые (не все) вершины?"Для задания различных преобразований объектов сцены в OpenGL используются операции над матрицами, при этом различают три типа матриц: видовая, проекций и текстуры. Все они имеют размер 4x4"В каждый момент можем работать только с одним из типов матрицы. Выбрать нужную можно следующим образом

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

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

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