[lang_en]This article is not avaliable in english.[/lang_en]

Недавно нашел у себя на компьютере весьма памятный мне материал – текст брошюры, которая продавалась в моем городе на рынке в книжной лавке.  Это был октябрь 2000 года и мне тогда было 14 лет отроду.

06

Материал был написан на основе своего опыта работы с библиотекой OpenGL и разработкой проекта “Автомобиль в движении”. Как это всё было тогда наивно, но по своему загадочно и величественно на то время. В общем это было начало начал так сказать.

Прилагающийся материал к брошюре (Delphi source code + executables): Delphi

Глава 1.

1.0  Построение объектов.

В OpenGL масса команд, относящихся к построению объектов. ?з всего этого множества нам в данном случае понадобятся только две: построение треугольника и квадрата.

Всем хорошо известно, что для построения треугольника необходимо три вершины, а они в свою очередь требуют координат. Мы с вами собираемся строить трёхмерные объекты, значит вершины, образующие их, будут иметь три координаты: x,y,z. Теперь разберёмся, как с помощью OpenGL создать треугольник. Построение начинается с glBegin(здесь указывается, что строим) и заканчивается glEnd. В качестве значения в glBegin указываем: GL_TRIANGLES(строить треугольник). Вершины создаются с помощью команды glVertex3f(x,y,z), где x,y,z – координаты вершины. ?так, чтобы построить треугольник нам потребуется между glBegin и glEnd указать три команды glVertex3f с координатами каждой вершины. Пример построения находится в папке Ex.01. Там представлена программа, которая рисует треугольник. Если вы совсем не знакомы с OpenGL, то поясню: из всего написаного вам нужно только знать, что процедурой WMPAINT мы перересовываем экран, там расположены команды построения треугольника. Также в процедуре Form Create мы устанавливаем формат пикселей и задаём задний фон, с помощью команды glClear(r,g,b,a), где r,g,b,a – параметры, формирующие задий фон и имеющие значение от 0 до 255. Хотя значения могут быть записаны от 0 до 1 десятичным дробным числом. Если вам захочется, чтобы ваш треугольник изменил свой цвет, то воспользуйтесь командой glColor3f(r,g,b), гдe r,g,b принимают те же значения, что и в предыдущем случае.

Если вы внимательно прочитали материал в книге, относящийся к треугольникам и проработали пример, то теперь можете попробовать нарисовать что-то своё. Ну, а если вы уже получили опыт по этой части создания объектов, то можно переходить к квадрату. Здесь всё просто. Вместо GL_TRIANGLES в glBegin мы задаём GL_QUADS(рисование квадрата). Естественно и вызовов команд рисования вершин станет четыре. Пример надится в Ex.02. Хорошо запомните данный материал, с ним мы ещё встретимся неоднократно.

1.1 Перемещение в пространстве.

В OpenGL существуют команды: перемещения(glTranslatef), поворота (glRotatef), масштабирования (glScalef). При их вызове, происходит манипулирование над системой координат, т.е. если вы хотите переместить, повернуть “камеру”, с помощью которой мы смотрим на сцену, то эти команды записываются просто так, как есть.

?НФОРМАЦ?Я. Если команды поместить в процедуру перересовки экрана, то они будут вызываться при рисовании каждого кадра, тем самым получиться эффект анимации.

Но если вы хотите, не трогая систему координат, манипулировать каким-то объектом, то вы должны поместить команды его рисования между glPushMatrix(запомнить матрицу) и glPopMatrix(восстановить матрицу). Затем вызвать необходимые команды перед glBegin. Этим вы получите нужный эффект. Давайте теперь рассмотрим, что нужно указывать в командах преобразования.

glTranslatef(x,y,z), где x,y,z числа, имеющие тип Real, а точнее glFloat(десятичное дробное число). Здесь вы указываете значения сдвига. Пример находится в Ex.03.

glRotatef(l,x,y,z). В данном случае l – это угол поворота, а x,y,z принимают значения -1,0,1. Это для удобства и вам так будет легче, т.е. вы задали угол 120 градусов и вам необходимо повернуть свою модель на такой угол по оси x, тогда вы записываете так: glRotatef(120,1,0,0); Пример на использование этой каманды находится в Ex.04.

glScalef(x,y,z), где x,y,z числа, принимающие значения типа GLfloat. Здесь 1 означает обычный масштаб, если меньше, то по этой оси объект уменьшается, а если больше, то увеличивается. Пример расположен в Ex.05.

?так мы уже умеем строить и манипулировать объектами, так давайте для закрепления построим куб (конечно пока созданные сцены выглядят невзрачно, но это только пока) и чтобы его лучше рассмотреть, пусть камера крутится вокруг него. Попробуйте сделать сами, а потом посмотрите как это получилось у меня. Пример находиться в Ex.06.

1.2 Списки и их предназначение.

Списки в OpenGL – это очень полезная вещь. Представим, что нам необходимо построить массив треугольников(одинаковых). Для решения данной задачи можно пользоваться раннее изученными методами, а можно использовать списки, т.е. не рисовать много объектов, а нарисовать один, затем поместить его в список и вызывать сколько нужно раз. Список обявляется как константа (Например: const Obj = 1). После объявления мы должны занести что-нибудь в него. Список начинается с glNewList, далее мы строим всё необходимое и список заканчивается glEndList. Вносить информацию в список можно например в процедуре создания формы (FormCreate), затем при перерисовке мы должны вызвать список(glCallList(название списка)). По завершению работы приложения список нужно удалить(glDeleteList(имя , номер)). Пример находиться в Ex.07. Там мы назначаем новый список, заносим в него информацию(рисование треугольника), т.е. мы как-бы даём треугольнику имя, а затем, при перерисовке, создаём цикл, который каждый раз вызывает процедуру рисования треугольника, при этом смещая точку рисования. После компиляции вы увидете 5 треугольников, выстроенных в ряд. Попробуйте создать сцену, где треугольники имеют разный масштаб или ещё что-нибудь типа этого.

1.3 ?спользование других программ для построения объектов.

Предположим нужно создать модель автомобиля. На это может уйти год, если строить по треугольникам или квадратам. Другое дело если взять графический редактор, например 3D Studio Max. В нём есть утилита, которая записывает объект в файл формата *.ASC. ?менно этим файлом я и воспользовался, но в нём слишком много лишних слов, поэтому я создал программу на QBasic, которая убирает всё лишнее. Она расположена в папке CreateFile. После преобразований мы получаем файл, в котором есть координаты и номера вершин, образующие грань. В папке Ex.08 расположена программа, которая читает такие файлы.(в этой же папке для примера есть файл с названием List. Вы можете открыть его и посмотреть, что получится). Это очень полезный пример и вы могли бы, изучив его, читать другие открытые форматы(*.dxf,*.wrl,*.x). В этом примере я читаю координаты вершин, а потом строю треугольники. Если вы уже попробовали эту программу, то наверное заметили, что модель открывается в сетчатой форме. Для этого я использовал команду glPolygonMode(грани, на которых будет действие, затем указывается, в каком виде выводить). В качестве граней вы можете задать GL_FRONT(лицевые), GL_BACK(задние), GL_FRONT_AND_BACK(и те и те). Выводить можно в виде точек, линий или фоновой модели: GL_POINT(выводить в виде точек), GL_LINE(сетчатая модель), GL_FILL(тоновая модель). Этим примером я хочу показать, что не стоит изобретать колесо.

Глава 2.

2.0 Тест глубины.

Тест глубины необходим для правильной передачи положения объектов в сцене. Откройте первое упражнение. После компиляции вы увидите два треугольника: один на другом. Хотя, если верить координатам, то один должен проткнуть другого. Здесь и появляется вопрос: А как это сделать? Ответом будет использование теста глубины. Давайте посмотрим следующий пример. В нём всё как и должно быть по-настоящему, т.е. один треугольник протыкает второй. Теперь всё правильно! Осталось только запомнить, что тест глубины включается с помощью команды glEnable(GL_DEPTH_TEST) и выключается с помощью glDisable(GL_DEPTH_TEST). Попробуйте поэксперементировать с его использованием.

2.1 Подробнее о цвете.

Теперь пришло время создавать более красивые сцены. Для начала добавим в неё источник света(о нём подробно я расскажу в следующей главе). С помощью команды glEnable(GL_LIGHTING) мы включаем в сцене свет, потом задав компьютеру glEnable(GL_LIGHT0)  на сцене появляется источник света, порядковый номер которого 0. Делее если вы хотите по-прежнему пользоваться командой glColor3f, то вам нужно включить её использование с помощью glEnable(GL_COLOR_MATERIAL). Затем я хочу вам сказать, что в OpenGL объекту может задаваться значение фонового отражения(GL_AMBIENT), диффузного(GL_DIFFUSE), зеркального(GL_SPECULAR) и излучаемого света(GL_EMISSION). Они задаются в команде glColorMaterial(face, mode), где face – это грани, на которые параметры будут задаваться(GL_FRONT, GL_BACK, GL_FRONT_AND_BACK) и mode – это режим, для которого будет задаваться цвет(эти режимы я перечислил чуть выше). К примеру, если вы хотите установить для объекта значение зеркального отражения, тогда вы должны выполнить следующие действия:

glEnable(GL_COLOR_MATERIAL);

glColorMaterial(GL_FRONT, GL_SPECULAR);

glColor3f(0.4,0.1,0.0);

{Дальше вы рисуете объект, на который хотите установить это значение.}

2.2 Свойства материала объекта.

В OpenGL есть команда glMaterialfv, которая задаёт свойства материала, но нужно помнить, что для этого необходимо отключить действие glColorMaterial с помощью glDisable(GL_COLOR_MATERIAL).

?так вернёмся к команде glMaterialfv. Она имеет три параметра. Первый задаёт грани, на которые будет осуществляться действие. Второй задаёт свойство. Оно может иметь значения: GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, GL_AMBIENT_AND_DIFFUSE и GL_SHININESS.

GL_AMBIENT – значение фонового отражения.

GL_DIFFUSE – значение диффузного отражения.

GL_SPECULAR – значение зеркального отражения.

GL_EMISSION – значение излучаемого света.

GL_AMBIENT_AND_DIFFUSE – значение фонового и диффузного отражения вместе.

При указании одного из них третий параметр будет массивом, сотоящим из четырех чисел (r,g,b,a).

GL_SHININESS – степень ослабления зеркального отражения. Если указать его в качестве второго параметра, то третий бедет лежать в диапазоне от 0 до 128. Пример находится в папке Ex.03.

Конечно вам выбирать, чем пользоваться, но нужно знать, что glColorMaterial работает быстрее. Опираясь на это, вы сможите сделать более быстрые приложения.

2.3 Прозрачные объекты.

В нашем мире мы часто встречаем прозрачные объекты, но как это отобразить в OpenGL. Такой эффект смешения цветов достигается с использованием альфа-компонента. До этого мы пользовались командой glColor3f, теперь пришло время познакомиться с ещё одной командой glColor4f. Она имеет 4 параметра: r,g,b,a. Первые три, я думаю, понятны, а вот последний задаётся значением, причём, чем оно меньше, тем прозрачней будет объект. Я ввёл новую команду , но это не значит, что можно её добавить в приложение и дело с концом. Нет, так не получится. Смешение цветов сначала нужно разрешить glEnable(GL_BLEND), потом задать параметры смешения: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). Теперь можно и потренироваться по данной теме. Пример расположен в папке Ex.05.

Глава 3.

3.0 Освещение.

В прошлой главе мы уже затронули тему освещения, т.е. для нанесения на объект различных параметров материала мы включали освещение с помощью команды glEnable(GL_LIGHTING), а потом включали источник освещения glEnable(GL_LIGHT0). Так давайте подробнее коснёмся этой темы. На данный момент, мы очень часто пользуемся светом и даже трудно представить, что случилось бы, если вдруг его не станет. Но даже если так, то тогда объекты не будут иметь цвета, а точнее не будут отражать свет и для нас они станут чёрными. Даже не обязательно что-нибудь представлять, можно просто выключить свет ночью и вы ничего не увидите. Это происходит и в OpenGL. Конечно, первые упражния мы делали без использования освещения, но из него складывается цвет или как я уже говорил излучаемый свет, поэтому нам просто необходимо ознакомиться с освещением и тогда вы сможите делать поистине красивые эффекты.

После того как вы включили освещение в общем(glEnable(GL_LIGHTING)),включаете источник с каким-то номером. Этот номер бедут использоваться для задания свойств источнику освещения. С помощью команды glLightfv, которая имеет три параметра. В первом мы указываем номер источника (Например, GL_LIGHT0). Во-втором мы задаём вид характеристики источника света, с которыми мы уже знакомы. Это GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR. Конечно, источник должен иметь свою позицию. Для её задания используйте GL_POSITION. В третьем параметре мы указываем значение выбранной характеристики. Для всех рассмотренных видов 4 числа. Думаю, что для первых трёх объяснять не нужно(r,g,b,a), а вот для последнего необходимо пояснить, что первые три – позиция в пространстве, а от последнего зависит, будет ли учитываться затухание света от расстояния до объекта. Если больше 0, то да, иначе нет.

3.1 Модель освещения.

В предыдущей главе мы познакомились с характеристиками материала объекта и если вы помните, то их цвет можно было задавать и для нелицевых сторон, но в данном случае мы бы ничего не увидели, т.к. по умолчанию источник света “освещает” только лицевые. Для того, чтобы управлять такими свойствами освещения, используется модель освещённости. Это команда glLightModelfv, которая имеет два параметра. Первый – вид модели освещённости. Может быть:

– GL_LIGHT_MODEL_AMBIENT(при этом виде освещённости второй параметр является массивом, содержащим 4 числа(r,g,b,a)  и это значение распространяется на всю сцену);

– GL_LIGHT_MODEL_VIEWER(в случае указания этого вида, второй параметр лежит в интервале от нуля до плюс бесконечности, при этом если 0, то направление зеркального отражения всё время параллельно наблюдателю, иначе оно просчитывается обычным образом);

– GL_LIGHT_MODEL_TWO_SIDE(при указании этого вида второй параметр имеет такое же значение, как и в предыдущем случае, только если оно равно 0, то освещение падает на лицевые грани, иначе на все подряд).

3.1 Рисование тени.

?сточники освещения – это конечно хорошо, но как нам получить тень от объекта. Если честно, то это тоже не очень трудно, почти так же, как смешение цветов, только здесь свои методы. Данный эффект заключается в том, что над полом рисуем объект в цвете, а под полом – без такового.  Здесь нам пригодятся и смешение цветов, и буфер трафарета. Последний необходим для рисования однотонной тени. Пример находится в папке Ex.02. Просмотрев его, вы увидите автомобиль с прозрачными стёклами и тенью, т.е. итоговую картинку мы уже нарисовали.

?так, давайте подробнее рассмотрим пример с тенью. С созданием формы я включаю смешение цветов:

glEnable(GL_BLEND);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Эти команды нам необходимы в данной ситуации для того, чтобы тень приняла свой облик, т.е. мы смешиваем перевёрнутый корпус автомобиля, окрашенный в чёрный цвет, с полом. Заметьте, что я вызываю команду масштабирования и сплющиваю бесцветный корпус во избижании неблагоприятных последствий, но вы можете попробовать убрать эту команду. Так же, перед рисованием модели под полом, я выключаю тест глубины, потому-что тень должна быть необъёмной.

?, наконец, я использовал тест трафарета. Как уже было сказано выше, для рисования однотонной тени без узоров, но при этом я включаю его использование только перед рисованием тени и выключаю сразу после завершения. Заметьте, что перед включением теста трафарета я его очищаю :

glClear(GL_STENCIL_BUFFER_BIT);

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

Глава 4.

4.0 Динамика движения.

Ещё в прошлой главе мы с вами нарисовали конечную картинку и если вам что-то не нравиться, то вы должны приложить все усилия и полученный опыт для необходимого результата. Можете, например, сделать корпус модели блестящий, а поверхность закрасить зелёным, как угодно. Главное, чтобы вы хоть понимали, что делаете. Попробуйте изменять значения параметров и смотреть на полученный результат. Всё-таки это и останется картинкой, чем бы вы не закрашивали, она вам всё равно через некоторое время надоест. Это я знаю из личного опыта. Но вот анимация, игра – это другое дело и на них можно полюбоваться подольше. В этой книге я рассматриваю только движение по осям x и y. Откройте единственное упражнение к этой главе. Там расположен исходный текст небольшой программы, от которой до игры совсем чуть-чуть и если у вас была мечта создать что-то подобное, то дерзайте.

Давайте немного разберёмся в этом исходном тексте. В начале программа читает с файлов объекты и при перерисовке они выводятся на экран. Здесь рисуется и тень, и прозрачное стекло. Первые 36 кадров идёт движение камеры, только после этого вы можете манипулировать автомобилем. При нажатии вперёд, мы увеличиваем скорость (delta := delta + 0.05), а при нажатии назад – уменьшаем. Нажатием пробел – скорость резко уменьшается и обратите внимание на фары. Они загораются.

В процедуре перерисовки экрана написаны формулы, по которым вычисляется позиция автомобиля. Они основаны на зависимости перемещения по осям x и y, так же от угла поворота, который может принимать значения от -360 до 360. В этой программе идёт постоянная скорость, т.е. вы нажали вперёд один раз и ту скорость, которую эта машина приобрела за нажатие, она и сохраняет. Если вам больше нравиться по другому, то вы можете в самом начале процедуры перерисовки дописать следующее: delta := delta – 0.01. Написав это, вы получите эффект движения по инерции, т.е. при отпускании клавиши “газа” машина будет медленно катиться, пока, наконец, не остановиться.

Если у вас появятся ещё какие-нибудь идеи, то можете попробовать их на деле. Просто каждый человек ставит перед собой разные задачи и каждый имеет свой вкус. Некоторым может нравиться движение чётко по физическим законам, а некоторых тянет к космосу(если вы и правда предпочитаете космическое пространство, тогда поменяйте модель на космический корабль и немного подработайте сцену).

Моя первая публикация
Tagged on:     

2 thoughts on “Моя первая публикация

  • Wednesday October 23rd, 2013 at 03:45 PM
    Permalink

    “поэтому я создал программу на QBasic, которая убирает всё лишнее”

    а можно заполучить эту программу на QBasic??

  • Wednesday October 23rd, 2013 at 03:56 PM
    Permalink

    Боюсь сейчас будет весьма затруднительно найти эту программу, да и какой в этом смысл ? Вы испытываете сложности при работе с asc форматом ?

Leave a Reply

Your email address will not be published. Required fields are marked *