![]() |
OpenGL. От детского сада до гуру
OpenGL. От детского сада до гуру.
Вступление. Итак, начну серию своих «мирных» статей по CG(computer graphics). Здесь я попытаюсь рассказать вам о программировании под OpenGL и DirectX, о WinAPI и двойной буферизации, о физике твердых тел(Rigid Body) и построении высоко фотореалистичных изображений методом трассировки лучей(Ray Tracing). Надеюсь, это станет интересным для многих, а некоторые и вовсе найдут в себе таланты CG`шников. Для затравки я решил начать с цикла по программированию на С под OpenGL. Хоть приведенный код будет и на С(С++ в данном курсе использовать не обязательно, так что не буду придумывать сложности, мне-то все равно на чем писать, но многих может отпугнуть. Поклонникам ООП, для вас следующие статьи, стоит, например, лишь сказать, что Ray Tracing считается классической и лучшей задачей на С++), но я постараюсь снабжать его максимально понятными и подробными комментариями, всвязи с чем код будет абсолютно портируемым хоть на Delphi, хоть на Python, хоть на Haskell. «Цикл» будет состоять из следующих частей: Часть 1. Базовый макет GLUT-приложения Простейшие OpenGL программы с использованием OpenGL Utility Toolkit для любой операционной системы. Часть 2. Освещение и тени Создание источников света, физические коэффициенты, тени. Часть 3. Рисование полигонов. Текстурирование и прозрачность Рисование собственных фигур. Наложение текстур. Создание прозрачности и полупрозрачности. Часть 4. Мультитекстурирование. OpenGL Shaders. OpenGL Shader Language Наложение нескольких текстур. Инициализация шейдеров. Работа с шейдерами. Язык программирования GLSL. Часть 5. Пример базового макета системы анимации на WinAPI, двойной буферизации и OpenGL «Взрослое» программирование под OpenGL. Пишем без GLUT под Windows. Часть 6. Пример базового макета системы анимации на Qt4 и OpenGL «Взрослое» программирование под OpenGL. Пишем без GLUT кроссплатформенные приложения с использование Qt4. Часть 7. Загрузка моделей из редактора Maya Работать со стандартными моделями и полигонами не интересно. Так что завершим весь цикл загрузкой моделей из популярного редактора 3D графики Maya. Часть 1. Базовый макет GLUT-приложения Начинать, разумеется стоит с самых основ. А потому эту статью я посвящу самой простой части OpenGL.- GLUT или OpenGL Utility Toolkit. Но начнем разбираться по порядку. OpenGL (Open Graphics Library — открытая графическая библиотека) — спецификация, определяющая независимый от языка программирования кросс-платформенный программный интерфейс для написания приложений, использующих двумерную и трехмерную компьютерную графику. (с) Википедия OpenGL работает по принципу клиент-серверной системы, где в роли клиента выступает оформленная программа с использованием специального API, а в роли сервера обрабатывающая OpenGL часть графического процессора(GPU) видеокарты. Нашей задачей будет на протяжении цикла научиться пользоваться API для реализации любой проблемы, а так же понимать, на что идут ресурсы нашей видеокарты и как свести их трату к минимуму.. Вплоть до частей 5 и 6 мы будем пользоваться кроссплатформенной библиотекой GLUT. Это позволит нам не совершать дополнительных инициализаций и писать простой, понятный и кроссплатформенный код. Практически, 99% всех задач можно реализовать с использованием GLUT. Почему же лучше писать на «чистом» API и как это делать мы разберем уже в 5 и 6 частях, когда откажемся от его использования. Пока же начнем разбираться, с чем нам работать ближайшее время. Перед тем, как начнем писать программу, скажу, что GLUT а так же все необходимые библиотеки и файлы заголовков берутся с сайта _http://opengl.org. Итак, после этого вступления начнем писать программу. PHP код:
PHP код:
PHP код:
PHP код:
Абсолютно аналогично будет строится обработка мыши и прочих устройств ввода. PHP код:
PHP код:
|
Часть 2. Освещение и тени
Не прошло и двух суток с публикации на Ачате первой части цикла, как вновь моя Тошиба терпит запущенные GLUT проекты и OpenOffice одновременно. Да, вновь я за клавиатурой, чтобы продолжить свой курс. Хочу сразу сказать спасибо MicRO и mr. p-s за то, что готовы были всегда прочитать предрелизные версии этих заметок, а так же всегда показывали свою заинтересованность и оказывали моральную поддержку. Спасибо вам, ребята, без вас может и не сел бы писать этот «свой взгляд на CG глазами ачатовца». Порадовало, что первую часть статьи зашли почитать многие, жаль лишь, что не откомментировали, так что не знаю, вызвала ли она интерес к CG и достаточно ли приличным языком изъясняюсь. Однако, как бы оно ни было, продолжу свой небольшой курс. Сегодня мы будем говорить о вещи, без которой в CG обойтись нельзя — об освещении и тенях. Мы рассмотрим базовые методы создания светотени в OpenGL, которые дадут достаточно красивый эффект, однако, тех красот, что реализованы в современных играх мы пока не добьемся — к этому нас подведет тема шейдеров, которым на сегодняшний делается все и вся. Но пойдем от простого к сложному. На данный момент мы имеем некий исходник, модифицируя который мы и будем развивать наши знания. Для тех, кто знакомился со статьей чисто теоретически и ничего не компилировал, или же для тех, у кого эта компиляция почему-то не вышла, выкладываю его сразу весь, как он должен быть. Комментарии уберу, их мы уже видели в первой части. PHP код:
PHP код:
PHP код:
Но я бы не был извращенцем, окончи я на этом этапе свою статью. Хоть стандартное освещение OpenGL практически и не используется, но все же раскрою его немного более полно, чем создание однотонной «белой» неинтересной лампочки. Конечно, что-то все равно останется за кадром, но ни в одном учебнике, а уж тем более в серии статей рассказать абсолютно все нельзя. Потому немного вспомним физику и продолжим программирование того, что раскрою я. Прочее же несложно найти. Характеристики освещения: Ambient — стандартный оттенок объекта. Т.е. все неосвещенные объекты изначально не черные, а указанного оттенка серого. Diffuse — рассеянный свет, распространенный в среде. Specular — отраженный свет от объектов. Emission — излучаемый свет. Shininess — степень отражения света. Теперь рассмотрим, как можно использовать эти параметры в OpenGL. А именно добавим 4 вектора(четвертичных, зачем, не знаю, ИМХО — тут тупая трата лишней памяти, но для каких-то темных индийских целей используются четвертичные вектора) для Амбиета, Диффузии, Отражения, Излучения и одну переменную для степени отражения. Из них первые 3 относятся к лампочкам, а так же они все применимы к материалам. Задавать параметры лампочек мы уже умеем — это функции glLightfv и glLightf(использование этой функции мы не разбирали, но для задания специфических коэффициентов она используется для передачи float числа, а не вектора, как glLightfv). Параметры соответственно имя лампочки GL_LIGHTi, изменяемый параметр(в данном случае, Ambient — GL_AMBIENT, Diffuse — GL_DIFFUSE, Specular — GL_SPECULAR) и собственно сам передаваемый параметр. Инициализация может проходить в функции MyInit(причем, даже предпочтительно их задавать там) или непосредственно в Draw(но зачем ее захламлять, давайте там только рисовать). Аналогично с материалами. Оставшиеся параметры GL_EMISSION, GL_SHININESS. Функции работы с материалами glMaterialfv и glMaterialf(по полной аналогии с glLightfv и glLightf). На абсолютной аналогии функция получает 3 параметра: тип поверхности(GL_FRONT — передняя, GL_BACK — задняя, GL_FRONT_AND_BACK — обе), устанавливаемый параметр и сам передаваемый параметр. Работает это, как glColor3d, для всех объектов, идущих после вызова, а потому, использовать эту функцию предпочтительно непосредственно в самом Draw для рисования не однотипных объектов из разных материалов. Итак, мы разобрались со следующей частью великого и почти всемогущего OpenGL. Надеюсь, многие найдут ее для себя интересной и будут ожидать следующей, разумеется, еще более интересная статья, в которой мы начнем создавать собственные объекты из полигонов, текстурировать их и делать полупрозрачными. До новых статей. Всем спасибо за внимание, а я пойду, наконец, спать :) |
Ты зря смешиваешь GL и GLU/GLUT. Я бы не стал начинать с изучения glutWireTorus и glutInitWindowSize.
Самое интересное - написание оберток под все это дело. Классов и шаблонных класов для управления моделями, рендером, графикой и т.д. А так *****то. Наконецто б***ь эти все быдлохакеры-быдлокодеры сраные почитают, увидят незнакомые буковки и спросят : "ОЯЕБАЛ!! А ГДЕ ТУТ UnhookSST( ________ __)" ... Молодец, держи плюсик!! гыгы |
Мой глаз больше радуют статьи о процессе крекинга нефти, например; графика меня не интересует, я в ней не силён и т. д. Но возникает закономерный вопрос: почему статьи не в соответствующем разделе? Выглядят они вполне серьёзно и достойно.
|
Весьма интересно. Ждём перехода на более "низкоуровневую" серию статей :)
|
Часть 3. Рисование полигонов. Текстурирование и прозрачность
6 часов сна, гран-при Санкт-Петербурга по ЧГК, и вновь я мучаю ноут OpenOffice`ом. Большое спасибо за отзывы. Очень приятно удивили и порадовали комментарии. Еще раз спасибо! По поводу замечания KEZ`а. Возможно, при описании WinAPI и Qt, где-то там еще немного коснусь С++ для создания классов управления элементами OpenGL. Этого я вообще делать не планировал, но, возможно, это будет правильно. Я вообще хотел сделать этот курс вводным именно в технологию OpenGL, а его практическое использование уже оставить на потом в таких проектах, как Физика Твердых Тел(Rigid Body) и прочие. Но, если все же сочту полезным, то включу что-то и в этот цикл. Он разрабатывается прямо у вас на глазах. Извиняюсь, что задержал выход этой части дольше, чем обычно. Просто для полной спецификации всех функций, замазывания хвостов и продуманного изложения потребовалось больше времени, чем я ожидал. Итак, поехали. Начнем с несложного, но необходимого материала — построения своих объектов. Рисование «руками» в OpenGL начинается с функции glBegin( int Mode ), где Mode указывает режим рисования и может принимать следующие значения: Код:
GL_POINTS — рисование точекPHP код:
PHP код:
PHP код:
PHP код:
Теперь, вы понимаете, что задав один маленький квадратик мы можем рисовать любой параллелепипед, перемещать его в любое место, растягивать, сжимать, сдвигать(математическое понятие Shift путем умножения матриц) и так далее. Итак, мы можем нарисовать любой объект в любой точке нашего виртуального пространства. Так же хочу отметить еще функции установки параметров «кисти» рисования. А именно: PHP код:
GL_ACCUM_BUFFER_BIT, GL_COLOR_BUFFER_BIT, GL_CURRENT_BIT, GL_DEPTH_BUFFER_BIT, GL_ENABLE_BIT, GL_EVAL_BIT, GL_FOG_BIT, GL_HINT_BIT, GL_LIGHTING_BIT, GL_LINE_BIT, GL_LIST_BIT, GL_PIXEL_MODEL_BIT, GL_POINT_BIT, GL_POLYGON_BIT, GL_POLYGON_STIPPLE_BIT, GL_SCISSOR_BIT, GL_STENCIL_BUFFER_BIT, GL_TEXTURE_BIT, GL_TRANSFORM_BIT, GL_VIEWPORT_BIT. Итак, мы уже почти вплотную стоим рядом с текстурированием. Но, если вы запускали измененные проекты, то могли заметить кривость освещения, а потому последнее маленькое замечание. Дело в том, что когда мы рисовали GLUT фигуры(если вы заинтересовались материалом и рисовали не только тор, но сферу, куб и прочие объекты), то нормали у нас задавались автоматом. Но в данном случае мы все рисовали сами, а потому никаких нормалей нет. Конечно, можно положиться на glEnable(GL_AUTO_NORMAL), но я бы не стал этого делать. В этой ситуации к нам на помощь приходят функции задачи нормалей. А конкретно: PHP код:
Итак, все старые хвосты подправлены, все новые объекты построены. Теперь займемся украшательством, а именно натянем текстуры и посмотрим на прозрачность. В учебных целях я буду использовать не общепринятые форматы BMP, JPG и проч, т.к. писать функции загрузки их в память — это тема отдельной статьи, причем в случае JPG даже не одной. Использовать мы будем некие вымышленные форматы файлов, в которых первые 2 байта — ширина изображения, следующие 2 байта — высота, а далее идет описание каждой точки 3 байтам(r,g,b) для 24-битных изображений и 4 байтами(r,g,b,alpha) для 32-битных изображений. Форматы эти взяты не «с потолка». Примерно в таком виде хранятся изображения после загрузки в оперативной памяти. В учебных целях это самое то для быстрого и не нудного объяснения. В случае ваших проектов, вы, конечно, сможете использовать более популярные форматы загружая их в память и используя их абсолютно аналогично. Для начала напишем функции загрузки в память этих текстур. PHP код:
PHP код:
Итак, у нас есть функции загрузки. Осталось разобраться, как ее использовать. Для этого нам надо будет добавить инициализацию текстур и собственно их рисование. Начнем с инициализации. Для того добавим глобальный массив int Textures[MAX_TEX], где MAX_TEX — максимально число текстур, которое вы планируете использовать(без фанатизма, не делайте его особо большим). Далее в многострадальную функцию MyInit добавим несколько строк: PHP код:
1) Включить режим рисования текстуры GL_TEXTURE_2D(как всегда, с помощью функции glEnable). 2) Переключиться на необходимую текстуру с помощью функции glBindTexture 3) Нарисовать объект, расставляя текстурные координаты 4) После рисования объекта с этой текстурой отключить режим текстурирования(glDisable(GL_TEXTUR E_2D)) Тут все ясно, кроме расставления текстурных координат. В GLUT-моделях они, разумеется, уже расставлены, но нам требуется рисоваться собственные модели. Тут к нам на помощь приходят функции glTexCoord1d, glTexCoord2d, glTexCoord3d, glTexCoord4d и, соответственно, из производные, как и во всех GL-функциях. В качестве параметром они получают текстурные координаты заданного типа в количестве 1,2,3 или 4 соответственно. Для иллюстрации создания текстурированной модели с нормалями нарисуем простейший квадратик и затекстурируем его. Комментарии тут излишни. PHP код:
PHP код:
PHP код:
|
Классно. Прекрасно подходит для начального изучения opengl и glut. Написано все понятно и поймет каждый :)
|
))))))хо-хо Читаю сейчас книжку, там точно такой же рисунок как и аватар у МасТер. След Зомби.
|
Да.. чё вы наезжаете на чувака.. не знаю... лично мне статьи понравились...
Так держать!. Главное то что он их сам писал, а не упёр у кого то. |
| Время: 20:12 |