Главная страница
Навигация по странице:

  • Глава 2: Немного истории

  • FASM OpenGL tutorial ГлавнаяФорумРесурсыПубликации Публикации Новые Новые Лучшие Лучшие Песочница Песочница

  • Глава 5: Текстурирование

  • Глава 7: Туман (без лошади)

  • Приложение 2: Битовые карты (ну там, тройка, семерка, туз...)

  • Old School vb style Russian (Обратная связь Помощь

  • Регистрация Регистрация ИнформацияДругие публикации от archive Сортировать комментарииГлавнаяПубликацииDirectX/OpenGLFASM OpenGL tutorial

  • Fasm opengl tutorial Архив Глава 1 Бредисловие (вместо педисловия)


    Скачать 198.1 Kb.
    НазваниеFasm opengl tutorial Архив Глава 1 Бредисловие (вместо педисловия)
    АнкорFASM OpenGL
    Дата30.07.2022
    Размер198.1 Kb.
    Формат файлаpdf
    Имя файлаFASM OpenGL tutorial _ WASM.pdf
    ТипСтатья
    #638082

    FASM OpenGL Дата публикации 26 мар 2005
    FASM OpenGL tutorial — Архив Глава 1: Бредисловие (вместо педисловия)
    Привет всем (уважаемым читателям/телезрителям/"а также их родителями пр ;) Сразу хочу предупредить, что это моя первая статья, поэтому просьба не пинать меня ногами, никакого заме-е-ечательного Набоковского слога и живописных эпитетов вы тут не увидите :( Все выдержано в сухом "преподавательском" тоне без малейшего намека на "программерские"
    шутки про "юзеров", телепузиков, "Microsoft" и "г-на Била Гейтса" (а ровно и пауз на неопределенный срок фразой "я ушел бухать, так как я вовсе не "бухаю. Да да, не смейтесь, я спротЦмен ;) ) Разочаровавшись (многие уже потянулись к "Esc"/бутылке/соске) начнем собсен- н-но...
    Глава 2: Немного истории
    Как говорил товарищ Берлага, если приподнять завесу, то становится весьма очевидным что стандарт OpenGL разрабатывается фирмой Silicon Graphics (теперь SGI) слета года. Этот программный интерфейс был во многом основан на библиотеке IRIS GL, поддерживаемой с года. Для развития нового интерфейса был организован консорциум The OpenGL Architecture
    Review Board (ARB). На данный момент OpenGL является стандартной библиотекой для всех разрядных операционных систем (Unix, Mac, Windows). Ну и хватит на этом. В конце концов это вам не лезгинка, а твист. в смысле не "Большая Советская Энциклопедия".
    Глава 3: Инструментарий
    Сразу скажу что писать мы будем на ассемблере (вообще говоря, все следует писать на ассемблере ;) , а точнее на FlatAssembler (FASM) т.к. он очень быстрый, компактный, постоянно развивается и не отягощен всякими бредовыми конструкциями (типа assume/offset) других ассемблеров (типа TASM ;)... а, ну да, самое главное, для читателей откуда-нибудь из Изгггаеля,
    его еще и на шару (конечно же под небо-о-ольшой процЭнт ;) можно скачать на www.flatassembler.net
    Берем оттуда версию "for Win32 GUI" которая еще и, до кучи, оснащена простеньким IDE ! Далее. Распаковываем добро из скаченного архива "fasmw.zip"
    в какую- нибудь папку, и "усе готово шэф" Глава 4: Первое приложение (Я предполагаю что вы уже писали под Win32 хотя бы и "Hello world !" (если нетто почитайте какой-нибудь tutorial поэтому поводу, благо, их в сети туева хуча расплодилась. Окинув
    Главная
    Публикации
    DirectX/OpenGL
    FASM OpenGL tutorial
    Главная
    Форум
    Ресурсы
    Публикации
    Публикации
    Новые
    Новые
    Лучшие
    Лучшие
    Песочница
    Песочница
    | Новые публикации
    Новые публикации
    Пользователи
    Правила
    Войти или зарегистрироваться
    взглядом прилагаемый "simple.asm" в папке "simple" вы заметили что в нем нету даже оконной процедуры. Ой фу-у-у-у ! Ноне спешите закрывать fasmw.exe, это всего лишь следствие моих небольших "оптимизаций" (а иначе накой хрен нам писать на ассемблере, как не из извращенческих соображений оптимизации ?) Но обо всем по порядку. Надеюсь следующий код понятен всем ? (fasminc можно установить например так (в файле autoexec.nt для WinXP)
    "set fasminc=путь_к_папке_fasm")
    ;формат exe файла format PE GUI 4.0 точка входа программы entry start включаем файлы API процедур должна быть установлена переменная окружения "fasminc") include '%fasminc%\win32a.inc' констант OpenGL include '..\include\opengl_const.inc' и макросов include '..\include\opengl_macros.inc' начало программы start: Для начала спрячем курсор, дабы некоторые "продвинутые" юзвери не начали тыкать им куда не попадя, пораниться ведь можно (Извращения начинаются, см. "push ebx" обнулим ebx. Т.к. он не изменяется API процедурами то будем использовать push ebx вместо push 0, для оптимизации xor ebx,ebx
    ;спрячим курсор invoke ShowCursor,ebx Для начала "урока рисования" нам нужно создать окно, а точнее его класс (и тут не без извращений ;) ) размером с экран. Можно, конечно, для начала изменить разрешение, а потом уже уверенно создавать окно с известным размером, но это будет слишком просто для нас (и долго) ;) Поэтому мы получим текущее разрешение экрана пои (по Z пока не будем ;) ) и запихнем их в стек (перед этим забьем его нулями (ebx) это у нас будут другие параметры процедуры CreateWindowEx. Вообще многие функции подставляют вместо "0" (ebx) параметры "по умолчанию, этим, как говорит Microsoft, "интеллектуальным свойством" мы будем активно пользоваться во всех частях а) Помним при этом что функции возвращают результат в "eax". Вообще, следите за стеком ! Это хоть и геморойно, но зато позволяет не сохранять кучу ненужных "промежуточных" результатов функций (вроде поместим в стеке" для процедуры "CreateWindowEx" push ebx push ebx push ebx push ebx получим текущее разрешение по вертикали invoke GetSystemMetrics,SM_CYSCREEN поместим его в стек для процедуры "CreateWindowEx" push eax и по горизонтали invoke GetSystemMetrics,ebx и его в стек push eax Тут мы используем полученное разрешение экрана (его берем уже из стека. а накой нам лишние переменные ?) чтобы найти его (экрана) AspectRatio (разрешающую способность, те) Потом она нам еще пригодится
    ;вычислим соотношение разрешений экрана по горизонтали и вертикали fild dword [esp] fidiv dword [esp+4] и сохраним его в ratio fstp [ratio] По идее, для создания класса окна нам его нужно было бы сначала описать,
    зарегистрировать... В общем, скука ужасная (и еще байтов жрет кучу !) Вместо этого мы просто создадим окно с предопределенным классом, таких в винде множество, номы выберем ну хотя бы класс "edit" (о чем красноречиво сообщает строка szClass) Помним о том что некоторые "недостающие" в ее параметры мы уже положили в стек di
    создадим окно размером с экран с предопределенным классом "edit"
    ;(т.к. его регистрировать не надо, то это позволяет избавиться от ненужного кода) invoke CreateWindowEx,WS_EX_TOPMOST,\ szClass,szTitle,WS_VISIBLE+WS_POPUP,ebx,ebx Итак, окно мы создали. Если вы уже рисовали что-нибудь под Win32, то вызнаете что для этого нужно получить его "контекст, это делается довольно просто (так как контекст окна нам еще пригодится, мы сохраним его водном из "неиспользуемых" (в функциях Win32 API) регистров) получим контекст окна invoke GetDC,eax сохраним его в ebp xchg ebp,eax Теперь нужно задать режим работы а, число бит на пиксель, режимы отображение и прочую белиберду (половину из которой мы оставляем нулевой (те. по умолчанию)
    ;инициализируем дескриптор формата
    ;пикселей OpenGL (поддержку OpenGL и двойной буферизации) mov [pfd.dwFlags],PFD_DRAW_TO_WINDOW+\
    PFD_SUPPORT_OPENGL+PFD_DOUBLEBUFFER тип пикселей RedGreenBlueAlpha mov [pfd.iPixelType],PFD_TYPE_RGBA глубину цвета mov [pfd.cColorBits],32 плоскость отображения mov [pfd.dwLayerMask],PFD_MAIN_PLANE выберем его invoke ChoosePixelFormat,ebp,pfd и установим его invoke SetPixelFormat,ebp,eax,pfd У насесть контекст окна, у насесть пиксельный формат ! "Мы сделаем из тебя парень новую звезду. Аннннн нет, для начала нам еще осталось преобразовать контекст окна в "нечто"
    понятное у (т.к OpenGL не должен знать что такое Windows, для этого используется специальная "windows-compliant" функция API wgl***) и еще сделать его "текущим" (те. рисовать будем в него)
    ;преобразуем контекст окна в контекст OpenGL invoke wglCreateContext,ebp и сделаем его текущим invoke wglMakeCurrent,ebp,eax
    Фууу-х-х-х-х ! Самое сложное позади ;) Винды остались не удел, теперь "познакомимся",
    собственно, с простыми удобным ем ;) Говоря голосом ведущего "в мире животных, эта забавная зверушка тоже требует некоторой настройки параметров (ОПЯТЬ ?!) Дело в том что нам нужно включить "перспективные преобразования, проще говоря перспективу, она зависит от текущей разрешающей способности экрана (те. max_x/max_y) вот для этого то мы ее и вычисляли. Так как некоторые извращенческие функции OpenGL воспринимают только параметры типа Double (8 байт) то придется пихать их в стек макросом glCall (который использует макрос glPush) А шо делать ? У нас же Intel Все-таки :( Число 90.0 это требуемый "угол обзора" можно поставить его 45.0 или 60.0 как кому нравится. Числа 0.1 и 100.0 это координаты "отсекающих плоскостей, все, что находится между ними, будет отображено на экране. Остальное - обрезано. Надо заметить что многие функции API OpenGL (glRotate,
    glTransform и пр) работают с "текущей матрицей, коих 3 (GL_MODELVIEW, GL_PROJECTION и) поэтому чтобы преобразовать матрицу перспективы мы выбираем ее функцией выберем режим вычисления перспективных преобразований (наилучший) invoke glHint,GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST выберем для преобразований матрицу перспективной проекции invoke glMatrixMode,GL_PROJECTION умножим ее на матрицу перспективы, те. попросту включим ее (используем макрос glcall т.к. параметры передаются в виде 8 байтов) glcall gluPerspective,90.0,ratio,0.1,100.0 выберем для преобразований матрицу изображения invoke glMatrixMode,GL_MODELVIEW
    Ура, а вот ион, "основной цикл. В нем вы "пока" ;) не увидите навороченной демы от просто очистка экрана и выход по Esc. Т.к. мы работаем в режиме "двойной буферизации" то рендеринг идет в дополнительный буфер, для отображения его на экране нужно вызвать функцию GDI32 "SwapBuffers". Дабы впоследствии (когда мы добавим сюда что-нибудь) все не вертелось с бешеной скоростью, добавим сюда еще и синхронизацию с таймером
    ;основной цикл
    .draw: получаем текущее значение счетчика начала работы Windows (для синхронизации) invoke GetTickCount сравним его с сохраненным значением cmp eax,[msec] если оно не изменилось то ждем jz .draw если значение поменялось сохраним его mov [msec],eax очистим буфер экрана invoke glClear,GL_COLOR_BUFFER_BIT отобразим буфер на экран invoke SwapBuffers,ebp проверим на нажатие клавиши ESC invoke GetAsyncKeyState,VK_ESCAPE если она не нажата test eax,eax то продолжим цикл jz .draw Не забудем выйти и описать переменные ;) Обратите внимание как (как просто ! ;) ) в е описывается импорт и ресурсы.
    ;выход из программы invoke ExitProcess,ebx заголовок окна szTitle db 'OpenGL tutorial by Tyler Durden - Simple',0 имя предопределенного класса окна szClass db 'edit',0 включим файл с описанием импорта data import include '..\include\imports.inc' end data описание ресурсов data resource directory RT_ICON,icons,RT_GROUP_ICON,group_icons resource icons,1,LANG_NEUTRAL,icon_data resource group_icons,1,LANG_NEUTRAL,icon icon icon,icon_data,'..\resources\icons\simple.ico' end data счетчик тиков таймера msec dd ? соотношение разрешений экрана по горизонтали и вертикали ratio dq ? дескриптор пиксельного формата pfd PIXELFORMATDESCRIPTOR Ну, вот в принципе и все, в первом OpenGL приложении. Это, типа, был "template", дальше я буду добавлять только измененные части.
    Глава 4: Первый цветной треугольники тут негры ;) Ну, покончив с пережитками Win32 программирования, откинувшись (и оттопырившись) на спинку стула, можно наконец приступить ку вплотную. Оказывается нарисовать на нем треугольник непросто, а, как говорится, очень просто ! Все что надо это задать его координаты.
    Для начала сообщим что мы хотим, собственно, рисовать треугольники (GL_TRIANGLES) т.е.
    каждые три точки определяют один треугольник (следующие три - уже другой)
    ;начало рисования треугольника invoke glBegin,GL_TRIANGLES Теперь задаем координаты его вершин и их цвет. Цвет представляет собой 3 а (красную,
    зеленую и синюю (чуть было не написал голубую ;) ) составляющие) о чем говорит постфикс функции "3f". Этими префиксами/постфиксами отличаются все функции OpenGL API (те. если
    надо задать еще и alpha-состовляющую - используем функцию glColor4f, если нужно задавать параметры в Double то 3d/4d или 3i/4i для Integer) Тоже самое относится и к функции соответственно первый параметр - координата X, второй - Y, третий - цвет й вершины invoke glColor3f,1.0,0.0,0.0 ее координаты invoke glVertex3f,-1.0,-1.0,1.0 цвет й вершины invoke glColor3f,0.0,1.0,0.0 ее координаты invoke glVertex3f,1.0,-1.0,1.0 цвет й вершины invoke glColor3f,0.0,0.0,1.0 ее координаты invoke glVertex3f,1.0,1.0,1.0 Все, нарисовались конец рисования треугольника invoke glEnd Если все таки оставить, то мы ничего не увидим, т.к. треугольник будет лежать прямо в точке наблюдения, надо бы его отодвинуть. Но, так как мы будем делать это каждую итерацию цикла то наш треугольник будет все дальше и дальше отодвигаться от нас (проверьте это сами, удалив вызов glLoadIdentity) поэтому вначале мы будем "обнулять" матрицу изображения.
    ;обнулим текущую матрицу (матрицу изображения) invoke glLoadIdentity отодвинем объекты вглубь экрана (z=-3.5) invoke glTranslatef,ebx,ebx,-3.5 Просто нарисованный треугольник ничем не говорит нам о своей "трехмерности, надо его для этого повращать. Делается это функцией glRotate которая вращает (умножает текущую матрицу на матрицу поворота) на угол [theta] вокруг векторов с координатами (0,0,0) и (второй параметр,
    третий параметр, четвертый параметр) соответственно. Угол мы будем увеличивать каждую итерацию цикла (т.к. матрица изображения "обнуляется")
    ;умножим матрицу изображения на матрицу поворота повернем все объекты сцены на угол theta относительно вектора изв загрузим значение угла theta fld [theta] увеличим его назначение и запишем обратно fstp [theta] Вот и все ! И оч-ч-чень просто, по-моему...
    Глава 5: Да будет свет Свет в OpenGL включается очень просто (как и многое другое) выключателем ;) те. функцией glEnable с параметром GL_LIGHTING (отключается соответственно функцией glDisable). Нужно еще включить еще и определенный источник GL_LIGHT* (номер источника. Мы не будем пока парить себе мозг разнообразными видами источников и их параметрами, включим для начала источник GL_LIGHT0 (для него параметры настроены по умолчанию)
    ;включим источник света GL_LIGHT0 (используя значения по умолчанию) invoke glEnable,GL_LIGHT0 включим освещение invoke glEnable,GL_LIGHTING Так как в этой главе мы будем рисовать объемную фигуру (кубик) то нужно еще включить режим отсечения не лицевых граней (а то все грани кубика будут рисоваться и перекрывать друг друга) те. буфер. Делается это опять же функцией glEnable. Цвет получившегося
    освещенного) полигона зависит от свойств "материала" и только :( Чтобы правильно отображать его цвет нужно еще включить режим его отслеживания (включим режим отсечения не лицевых граней (буфер) invoke glEnable,GL_DEPTH_TEST включим изменение свойств материала в зависимости от его цвета invoke glEnable,GL_COLOR_MATERIAL Для того чтобы использовать освещение, для каждой грани нужно определить нормаль.
    Делается это функцией glNormal3f, координата X, координата Y, координата начало рисования куба из 6 четырехугольников GL_QUADS каждые 4 точки glVertex описывают один четырехугольник) invoke glBegin,GL_QUADS нормаль го четырехугольника invoke glNormal3f,0.0,0.0,1.0 цвет й вершины invoke glColor3f,1.0,0.0,0.0 ее координаты invoke glVertex3f,-1.0,-1.0,1.0 цвет й вершины invoke glColor3f,0.0,1.0,0.0 ее координаты invoke glVertex3f,1.0,-1.0,1.0 и т.д. invoke glColor3f,0.0,0.0,1.0 invoke glVertex3f,1.0,1.0,1.0 invoke glColor3f,1.0,1.0,0.0 invoke glVertex3f,-1.0,1.0,1.0 нормаль го четырехугольника invoke glNormal3f,0.0,0.0,-1.0 invoke glColor3f,0.0,0.0,1.0 invoke glVertex3f,-1.0,-1.0,-1.0 invoke glColor3f,0.0,1.0,0.0 invoke glVertex3f,-1.0,1.0,-1.0 invoke glColor3f,1.0,0.0,0.0 invoke glVertex3f,1.0,1.0,-1.0 invoke glColor3f,1.0,1.0,0.0 invoke glVertex3f,1.0,-1.0,-1.0 нормаль го четырехугольника invoke glNormal3f,0.0,1.0,0.0 invoke glColor3f,0.0,1.0,0.0 invoke glVertex3f,-1.0,1.0,-1.0 invoke glColor3f,1.0,1.0,0.0 invoke glVertex3f,-1.0,1.0,1.0 invoke glColor3f,0.0,0.0,1.0 invoke glVertex3f,1.0,1.0,1.0 invoke glColor3f,1.0,0.0,0.0 invoke glVertex3f,1.0,1.0,-1.0 нормаль го четырехугольника invoke glNormal3f,0.0,-1.0,0.0 invoke glColor3f,0.0,0.0,1.0 invoke glVertex3f,-1.0,-1.0,-1.0 invoke glColor3f,1.0,1.0,0.0 invoke glVertex3f,1.0,-1.0,-1.0 invoke glColor3f,0.0,1.0,0.0 invoke glVertex3f,1.0,-1.0,1.0 invoke glColor3f,1.0,0.0,0.0 invoke glVertex3f,-1.0,-1.0,1.0 нормаль го четырехугольника invoke glNormal3f,1.0,0.0,0.0 invoke glColor3f,1.0,1.0,0.0 invoke glVertex3f,1.0,-1.0,-1.0 invoke glColor3f,1.0,0.0,0.0 invoke glVertex3f,1.0,1.0,-1.0 invoke glColor3f,0.0,0.0,1.0 invoke glVertex3f,1.0,1.0,1.0 invoke glColor3f,0.0,1.0,0.0 invoke glVertex3f,1.0,-1.0,1.0 нормаль го четырехугольника invoke glNormal3f,-1.0,0.0,0.0 invoke glColor3f,0.0,0.0,1.0 invoke glVertex3f,-1.0,-1.0,-1.0 invoke glColor3f,1.0,0.0,0.0 invoke glVertex3f,-1.0,-1.0,1.0 invoke glColor3f,1.0,1.0,0.0 invoke glVertex3f,-1.0,1.0,1.0 invoke glColor3f,0.0,1.0,0.0 i
    k l
    f
    invoke glVertex3f,-1.0,1.0,-1.0 конец рисования куба invoke glEnd Заметьте что мы вызываем glRotatef 3 раза, для придания траектории вращения большей random'ности
    Глава 5: Текстурирование
    Для пущего реализЬма напялим на наш кубик текстуру. Делается это тоже проще пареной репы.
    Для начала нужно ее (текстуру) нарисовать (можно выдрать откуда-то, главное помните, что ее размер должен быть степенью двойки (256*256*24bpp в примере) ;), и сохранить в формате "raw" (например ом или IrfanView) конечно размер полученного файла будет немаленьким, но проще потом exe-шник сжать ом чем париться с JPEG/TGA форматами...
    Затем подключим полученный файл в виде ресурса в resourse.inc fileres texture,'textures.raw' Далее ее нужно перевести в понятный у формат функцией glTexImage2D. говорит что текстура у нас х мерная, следующий ноль (ebx) определяет mip-map уровень для нее (для ускорения текстурирования из текстуры можно предварительно сгенерировать несколько уменьшенных копий, ноу нас пока только одна, ка - это число компонент в цвете (у нас RGB, а может быть и1-а (R), ее, затем размерность текстуры пои соответственно (256*256), "0" (ebx) это толщина "рамки" вокруг текстуры, далее формат текстуры, RGB, RGB, ...), тип каждой компоненты (у нас байт) и, собственно, смещение в файле
    (texture+16).
    ;создадим 256x256x24bpp текстуру из ресурса texture (raw файл) invoke glTexImage2D,GL_TEXTURE_2D,ebx,\
    3,256,256,ebx,GL_RGB,\
    GL_UNSIGNED_BYTE,texture+16 Теперь осталось определить еще некоторые параметры текстуры, такие как фильтры уменьшения/увеличения (GL_TEXTURE_MIN_FILTER/GL_TEXTURE_MAG_FILTER) (те. которые применяются когда текстура, соответственно, меньше/больше требуемой для текстурирования в данный момент времени) функцией glTexParameteri. Установим их в GL_LINEAR (лучшее качество, можно еще GL_NEAREST побыстрее, но похуже)
    ;установим фильтр текстуры приуменьшении установим фильтр текстуры при увеличении (linear) invoke glTexParameteri,GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR Вообще говоря, нужно было предварительно выбрать ID текстуры (1 для первой текстуры, 2 для второй и т. д) функцией glBindTexture, нотку настолько одна, и вся работа идет с ой текстурой (по умолчанию, тонам ничего не мешает этого не делать.
    ;выберем текстуру номер 1 invoke glBindTexture,GL_TEXTURE_2D,1 Осталось только включить текстурирование функцией включим текстурирование invoke glEnable,GL_TEXTURE_2D Усе, однако OpenGL не знает как привязать координаты вершин объектов к текстурным координатам (за исключением автоматической генерации текстурных координатно об этом позже) так что надо ей об этом сообщить функцией glTexCoord2f с двумя параметрами (для х мерной текстуры) x и y координатами текстуры (они изменяются также как и все остальное в - в относительных координатах от 0.0 до нормаль го четырехугольника invoke glNormal3f,0.0,0.0,1.0 координата текстуры для ой вершины invoke glTexCoord2f,0.0,1.0 я вершина i
    k l
    f
    invoke glVertex3f,-1.0,-1.0,1.0 координата текстуры для ой вершины invoke glTexCoord2f,1.0,1.0 я вершина invoke glVertex3f,1.0,-1.0,1.0 и т.д. В случае с несколькими текстурами, их выбор осуществляется, как я уже говорил, функцией Глава 6: Alpha смешивание (blending) или шара продолжается смешивание позволяет нам использовать эффекты прозрачности. Для этого нужно опять таки его просто включить функцией glEnable (вам даже не надо знать как оно работает ! Вот шара помучившись со своим дос-софтверным 3D движком можно вздохнуть спокойно ;) настроить его тип можно функцией glBlendFunc, параметры источника (что смешивается),
    параметры результата (с чем смешивается. Параметры зависят от требуемого результата.
    ;выберем режим работы альфа смешивания invoke glBlendFunc,GL_SRC_ALPHA,GL_ONE и включим его invoke glEnable,GL_BLEND Чтобы было с чем смешивать, нужно отключить режим отсечения не лицевых граней (попросту буфер) функцией выключим режим отсечения не лицевых граней (буфер) invoke glDisable,GL_DEPTH_TEST либо вообще его не включать (как у нас в примере).
    Глава 7: Туман (без лошади)
    А теперь "офигенно" сложный этапа) Туман ! Делается даже сложней чем alpha смешивание ;) а именно:
    ;выберем режим работы тумана (экспоненциальный) invoke glFogi,GL_FOG_MODE,GL_EXP2 установим его цвет (fogColor) invoke glFogfv,GL_FOG_COLOR,fogColor его интенсивность invoke glFogf,GL_FOG_DENSITY,0.55 начало invoke glFogf,GL_FOG_START,1.0 и конец invoke glFogf,GL_FOG_END,3.0 установим режим вычисления тумана (наилучший) invoke glHint,GL_FOG_HINT,GL_NICEST установим цвет очистки экрана равный цвету тумана invoke glClearColor,0.5,0.5,0.5,1.0 включим туман invoke glEnable,GL_FOG цвет тумана fogColor dd 0.5,0.5,0.5,1.0 И все ! Параметры я думаю говорят сами за себя. Так как "туманятся" только объекты, то для пущей выразительности окрашиваем остатки экрана под цвет тумана (непонятно почему разработчики OpenGL не предусмотрели для glClearColor вариант с постфиксом fv (передается указатель на массив из Float'ов). Режим "работы" тумана можно выбрать и другой (ну, например,
    с 9 до 6 вечера, безвыходных или GL_LINEAR, поэкспериментируйте...
    Глава 8: Outline шрифты
    Заценим теперь, какую "титаническую" работу проделала Microsoft (ну вот, а говорил, что не будет про них) в своем е "3D Text". Для начала привычные для шрифтов вызовы API: создаем объект типа (ти-и-ипа) "шрифт" (все значения оставляем на совести, и даем установку (а-ля Кашпировский) для "рисования".
    ф
    создадим шрифт все значения по умолчанию "0", шрифт семейства "Comic Sans MS") invoke CreateFont,ebx,ebx,ebx,ebx,ebx,ebx,\ ebx,ebx,ebx,ebx,ebx,ebx,ebx,fontName выберем полученый объект (шрифт) для текущего контекста окна (ebp) invoke SelectObject,ebp,eax Дальше вступает вдело преобразовывает векторный (именно векторный ! Шрифт "System" преобразовать не удастся, а жаль) в так называемый список (с. что ?!), т.е.
    последовательность OpenGL команд описания графических примитивов (те что обычно задаются между glBegin, glEnd). Для этого используется функция wglUseFontOutlinesA (или ее unicode версия wglUseFontOutlinesW для символов с кодами больше 255) Получаем "outline Мы будем преобразовывать символы начиная с нулевого (ebx) по 255 (всего, значит, символов, единица означает что используются полигоны, а не линии ("0"), "0.2" это толщина нашего шрифта, в ebp, если помните, сохранен контекст OpenGL. Для операций с несколькими (у нас - 256) списками нужно выбрать первый список (вообще-то его их нужно было сгенерировать функцией glGenLists, но за нас это делает OpenGL). Для этого используется функция преобразуем символы от го догов список х мерных моделей (outline font) толщиной 0.2.
    ;"1" означает использование полигонов вместо линий ("0") invoke wglUseFontOutlinesA,ebp,\ ebx,256,listBase,ebx,0.2,1,ebx выберем первый элемент в списке invoke glListBase,listBase Посмотрим на предыдущие примеры аи офигеем ;) Зачем было столько носиться с оптимизацией, если размер какой-то завшивленной 256*256*24bpp текстуры занимает целых кило ? Это не есть хорошо, будем теперь генерить ее вручную ! Это не tutorial про генерацию текстур (читайте в "Hugi" про это, поэтому выберем простую "шумовую" текстуру, для этого неплохо подходят код нашей проги. Заюзаем его в качестве текстуры (хе-хе, вот это я понимаю,
    извращение). OpenGL, конечно, ничего не знает про координаты текстуры для "outline" шрифта,
    да и вклиниться в работу функции wglUseFontOutlines и "наследить" там вызовами glTexCoord2f будет сложно (для этого нужно юзать feedback буфер, так что просто предоставим заниматься этим самой OpenGL, включив автоматическую генерацию текстурных координат (да, да, вот где еще одна шара !). Причем выберем режим текстуры GL_SPHERE_MAP, который обычно используется в создании всяческих отражений (enironment создадим 16x16x32bpp текстуру используя в качестве значений цветов пикселей опкоды нашей программы начиная сметки установим тип генерируемой текстуры в направлении "S" (GL_SPHERE_MAP) invoke glTexGeni,GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP в направлении "T" (GL_SPHERE_MAP) invoke glTexGeni,GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP и включим автоматическую генерацию текстурных координат в направлении "S" invoke glEnable,GL_TEXTURE_GEN_S и "T" invoke glEnable,GL_TEXTURE_GEN_T
    Ндааа... Опять глава кончилась не успев начаться ;) Ах да, нужно еще написать какое-нибудь слово (желательно не из трех букв, хотя в OpenGL слава Богу еще не встроили Parental Lock ;)
    все-таки это не DirectX), для этого вызовем списки (хмм, с этим словом главное не описАться...
    ой) с номерами равными кодам желаемых букв (т.к. мы генерили символы от "0" до "Делаем это функцией glCallLists.
    ;вызавем txtIntro_length элементов списка (шрифта) с номерами указанными в строке байт (GL_UNSIGNED_BYTE) txtIntro invoke glCallLists,txtIntro_length,GL_UNSIGNED_BYTE,txtIntro Ура ! Получилось довольно красиво (и, главное, всего натри кило. Можно даже забацать из этого какое-нибудь "Newschool scrolltro". Дерзайте.
    Глава 9: Motion blur и рендеринг в текстуру
    И так, мы уже вплотную подобрались к алгоритмам используемым в демках. Т.к. OpenGL не позволяет (нормальным образом) получить доступ к видеопамяти, поэтому и алгоритмы эффектов здесь соответствующие - извращенческие. Так что обычным образом motion blur нам сделать не удастся, будем юзать "встроенную" возможность OpenGL blur'ить текстуры при их растягивании (ну да, нам даже не надо знать как работают motion blur фильтры !) Вкратце план довольно прост. Отрендерив сцену в окно размером blurSize*blurSize (512*512 в примере, скопируем полученное изображение из экранной памяти в текстуру. Идем дальше (Строго на север, в порядке 50 метров, нарисуем четырехугольник с полученной текстурой, размером с экран, поверх изображения. Затем (Проходя мимо пЫхты"), отрисуем сцену еще раз.
    Все, т.к. альфа смешивание включено, то каждый раз смешивая текстуру с предыдущими сценами (с альфа компонентой меньше "1.0") и черный экран (с альфа компонентой "0.0"), она будет постепенно "исчезать. Так как мы будем рендерить все впустую текстуру, то сначала нужно ее создать, делается это как и обычно:
    ;выберем текстуру номер 1 invoke glBindTexture,GL_TEXTURE_2D,1 создадим blurSizexblurSizex24bpp текстуру из буфера TextureBlank (пустого) invoke glTexImage2D,GL_TEXTURE_2D,ebx,3,blurSize,\ blurSize,ebx,GL_RGB,GL_UNSIGNED_BYTE,textureBlank Заметьте, что кубик мы предварительно "компилируем" в список.
    ;создадим новый список cubeList invoke glNewList,cubeList,GL_COMPILE
    Blur'ить мы будем не каждый раза только через 4 фрейма (иначе "хвост" будет слишком маленьким, да и тормознуто это).
    ;увеличим счетчик кадров а inc [blurCounter] он стал равен мнет не в этот раз ;) jnz .notBlur Сначала нужно установить окно размером blurSize*blurSize, и отрендерить туда нашу "сцену".
    ;установим окно вывода с координатами 0,0 размером blurSize*blurSize invoke glViewport,ebx,ebx,blurSize,blurSize
    ;отрендерим blur сцену call renderMotionBlur Скопируем то что получилось в текстуру, функцией glCopyTexImage2D. показывает что текстура двухмерная, следующий ноль (ebx) - это mip-map уровень, затем координаты текстуры (0,0), ее размер (blurSize*blurSize), и размер границы ("0"). Очистим экран,
    и вернем OpenGL'ое окно обратно.
    ;выберем текстуру номер 1 invoke glBindTexture,GL_TEXTURE_2D,1 скопируем в нее отрендеринную только что сцену размером blurSize*blurSize invoke glCopyTexImage2D,\
    GL_TEXTURE_2D,ebx,GL_RGB,ebx,ebx,blurSize,blurSize,ebx очистим буфер экрана и буфер invoke glClear,GL_COLOR_BUFFER_BIT+GL_DEPTH_BUFFER_BIT установим окно вывода с координатами 0,0 размером screenWidth*screenHeight invoke glViewport,ebx,ebx,[screenWidth],[screenHeight] Теперь как нам нарисовать четырехугольник точно размером с экран ? Ведь у плевать на пиксели, он оперирует какими-то "условными единицами" (зелеными, наверное ;) ). Для этого
    нам надо установить так называемую "Ортогональную (прямоугольную) проекцию" делается это не сложнее установки перспективной проекции:
    ;и умножим на матрицу ортогональной проекции glcall glOrtho,0.0,screenWidthDouble,screenHeightDouble,0.0,-1.0,1.0 Усе, рисуем нашу сцену четырехугольником (заметьте, что перспективную проекцию мы устанавливаем не функцией, а, просто, сохранив проекционную матрицу в стеке функцией glPushMatrix, и восстанавливаем ее функцией выберем текстуру номер 1 invoke glBindTexture,GL_TEXTURE_2D,1 уменьшим альфа компоненту объектов (0.9) invoke glColor4f,1.0,1.0,1.0,0.9 выберем для преобразований матрицу перспективной проекции invoke glMatrixMode,GL_PROJECTION сохранить текущую матрицу (матрицу перспективы) invoke glPushMatrix обнулим ее invoke glLoadIdentity и умножим на матрицу ортогональной проекции glcall glOrtho,0.0,screenWidthDouble,screenHeightDouble,0.0,-1.0,1.0 выберем для преобразований матрицу изображения invoke glMatrixMode,GL_MODELVIEW обнулим текущую матрицу (матрицу изображения) invoke glLoadIdentity нарисуем четырехугольник размером в экран
    ;(отрендеренная до этого сцена используется в качестве тексуры) invoke glBegin,GL_QUADS invoke glTexCoord2f,ebx,1.0 invoke glVertex2i,ebx,ebx invoke glTexCoord2f,ebx,ebx invoke glVertex2i,ebx,[screenHeight] invoke glTexCoord2f,1.0,ebx invoke glVertex2i,[screenWidth],[screenHeight] invoke glTexCoord2f,1.0,1.0 invoke glVertex2i,[screenWidth],ebx invoke glEnd выберем для преобразований матрицу перспективной проекции invoke glMatrixMode,GL_PROJECTION восстановим ее из стека invoke glPopMatrix В принципе ничего сложного тут нет, все абсолютно "прозрачно, смотрите код и все поймете. Глава 10: Zoom blur
    Ур-ра ! Последняя часть а (пока, гы гы). Надоели вы мне, хех, как сказал один доцент
    (тоже ученый, у него 3 класса образования "пришить бы вас, да возиться неохота" ;). Но пока,
    так... Копаем. Копать будем "zoom blur", или как его еще иногда (и неправильно) называют "radial blur", или даже "volumetric lights"... Ноне в названии дело, а в его простоте. Собственно,
    после предыидущей главы, делать мне тут нечего, разве что так, "на шухере постою. Алгоритм довольно тормознутый (для моей отстойной видюхи GeForce4 MX), в 1024*768 лучше не пускать,
    поэтому установим-ка, для начала, что нибудь вроде подготовим структуру описывающую видеорежим, ее размер mov [dmScreenSettings.dmSize],dmScreenSettings_size разрешение по горизонтали mov [dmScreenSettings.dmPelsWidth],screenWidth вертикали mov [dmScreenSettings.dmPelsHeight],screenHeight изменяемые поля mov [dmScreenSettings.dmFields],DM_PELSWIDTH+DM_PELSHEIGHT сменим видеорежим invoke ChangeDisplaySettings,dmScreenSettings,ebx Обратите внимание на, уже набивший всем оскомину, "эффект" широкоформатной пленки (типа,
    фи-и-и-ильму, фи-и-и-ильму !), который кое-кто уже умудрился впарить даже в 256b intro. Т.к. я поубивал много лишних вызовов процедур (к примеру, glViewport нужно было бы вставить
    после инициализации, то прога потеряла некоторую долю логичности (а заодно и пару "килограмм, но к 10 главе мы уже все стали "хавцами" в е, неправда ли установим окно вывода с координатами 0,77 размером screenWidth*screenHeight invoke glViewport,ebx,77,screenWidth,screenHeight Сам алгоритм, который очень похож на motion blur, состоит в следующем (неизмененные места оставлены специально. Отрендерив сцену в окно размером blurSize*blurSize (256*256 в примере, скопируем полученное изображение из экранной памяти в текстуру. Нарисуем четырехугольники с полученной текстурой поверх изображения несколько) раз, каждый раз увеличивая их размер, от blurSize до полноэкранного размера, и уменьшая значение альфа компоненты. Рулим ;) (можно отрендерить сцену еще раз, поверх этого, номы не будем).
    Смотрим код:
    ;инициализируем максимальный радиус радиального аи начальные значения переменных mov dword [blurInc],ebx mov dword [blurDec],1.0 mov dword [blurAlpha],0.35 цикл радиального размытия
    .renderMotionBlur: сохраним счетчик push ecx увеличим радиус "справа"/уменьшим "слева" и уменьшим альфа компоненту радиального а fld dword [blurDelta] fld st0 fadd dword [blurInc] fstp dword [blurInc] fsubr dword [blurDec] fstp dword [blurDec] fld dword [blurAlpha] fsub dword [alphaDelta] fstp dword [blurAlpha] выберем текущее значение альфа компоненты invoke glColor4f,[esp],[esp],1.0,[blurAlpha] нарисуем четырехугольник размером в экран
    ;(отрендеренная до этого сцена используется в качестве тексуры) invoke glBegin,GL_QUADS invoke glTexCoord2f,[blurInc],[blurDec] invoke glVertex2i,ebx,ebx invoke glTexCoord2f,[esp],[blurInc] invoke glVertex2i,ebx,screenHeight invoke glTexCoord2f,[blurDec],[blurInc] invoke glVertex2i,screenWidth,screenHeight invoke glTexCoord2f,[esp],[blurDec] invoke glVertex2i,screenWidth,ebx invoke glEnd восстановим счетчик pop ecx уменьшим его dec ecx и продолжим цикл jnz .renderMotionBlur
    Незабудем вернуть видеорежим обратно, для этого просто вызовем функцию "вернем видеорежим обратно invoke ChangeDisplaySettings,ebx,ebx Вот и все ! Уже украли/обрили... Просто, но, черт возьми, эффЭктно (и впереди я, на белом верблюде. Так о чем это я ? Ага, пришло, наконец, время долгожданного прощания. Просьба не устраивать сцен и истерик ;) обнимемся как братья. Э-э-э-э, что там еще говорят ? Желаю счастья в личной жизни. Один маленький, но очень гордый птичка. Нет, не то. Типа
    надобранич дитлохи, до зустричи (тут я прям прослезился, как все Хрюши, Степаши и тети Тани/
    Амаяки Акопяны, канала ОРТ, вместе взятые)...
    Приложение 1: Vertex Не успев обрадоваться от вышеописанного расставания (сцена с рыдающими детьми "Папа Папа ! На кого ты нас покинул ?!"). Любая вернулся (wmplayer.exe Ну "да-ра-гггие мАи" ну не мог же я выпустить вас "в люди" голыми, так сказать ! Так бы сейчас и писали glBegin'ами. Шо вы ? Это уже совсем не модно ! Щас "в Европе, а также в лучших домах
    Филадельфии" все поголовно юзают массивы вершин. Вообще то, массив вершин (vertex array) - это почти тоже самое, что и команды между glBegin/glEnd, только их выполняет сама карта,
    подставляя значения из нашего массива. Как нам уже известно, описывать приходится не только, собственно, вершины, но и нормали, текстурные координаты, цвет и пр, поэтому и массивы бывают разные. Однако, мы не будем мучить себя подключением всех массивов,
    скинем просто все в кучу функцией "glInterleavedArrays" (те. данные в массиве идут последовательно, сначала нормаль одной вершины, потом ее текстурные координаты, цвет и пр. затем сами координаты вершины. Затем тоже самое для следующей вершины и т.д.). Она принимает параметрами тип "сваленных в кучу" массивов, тут это GL_N3F_V3F, те. N3F - массив нормалей, по 3 а на нормаль и V3F - массив вершин, тоже из х float'ов на вершину, так называемый "stride" - "расстояние" между данными для соседней вершины (у нас будет "0" (ebx)
    т.к. данные в массиве идут подряди наконец, ссылку на массив сданными. Но glInterleavedArrays только подключает массивы на отображение, их еще нужно, собственно,
    отобразить. Делается это функциейй "glDrawArrays". Первый параметр - это тип используемых примитивов (GL_TRIANGLES), второй - это первый элемент массива (ebx=0, те. рисуем все элементы) и третий параметр - это общее число элементов...
    ;включим отображение массивов нормалей по 3 а на нормаль) и вершина на нормаль) invoke glInterleavedArrays,GL_N3F_V3F,ebx,mdlShip
    ;отрисуем вершинный массив из 8686 треугольников, начиная с треугольника номер "0" (ebx) invoke glDrawArrays,GL_TRIANGLES,ebx,8686*3-1 Дело за малым - осталось найти де взять этот массив ;) Можно, конечно, и ручками (как в следующем приложении, ноя (для демонстрации "крутизны" массивов вершин) отконвертил модельку а (предварительно сохранив ее 3DStudio в формате "ASC"). Можно было вставить ее просто как переменную (mdlShip dd ...) но это б заняло полтора мегабайта ;) Так что пришлось вынести ее в отдельный файл, и скомпилить ом, в результате чего получился Kb бинарник, который я засунул в ресурсы директивой "file".
    mdlShip file '..\resources\models\ship.bin' Обратите внимание как я "генерил" текстуру (так вот откуда Cпилберг спер терминатора T1000 взяв за основу только красные компоненты "пикселей" (а наделе опкоды... красные уже и сюда добрались) "GL_LUMINANCE_ALPHA". Для придания текстуре яркости, я использовал специальный режим обработки bitmap'ов (о них в следующем приложении) те. здесь - текстуры" с параметром "GL_RED_SCALE" (множителем красной (нет, ну хоть в кавычках это слово пиши) компоненты) и значением "10.0".
    invoke glPixelTransferf,GL_RED_SCALE,10.0 Ну, теперь все быстренько на борьбу с кубиками и торами ! Рисуйте свои модельки и вперед.
    Помните только (неоднократно натыкался на такое "недопонимание) что массив индексов, это на самом деле массив индексов цветов в режимах с маленькой глубиной цвета (256 цветов и т.д.) а не массив индексов вершин (как в 3D моделях).
    Приложение 2: Битовые карты (ну там, тройка, семерка, туз...)
    Ну почему обязательно карты ? Есть много интересных и полезных спортивных игр ! Например литрбо... оуэ-э-э-э битмап шрифты ! Еще бы, как же иначе мы напишем в нашу демку кучу псевдо-философского бреда, и причем непременно (непреме-е-енно !) "разъежающейся-
    Регистрация фев 2017
    Публикаций:
    532
    Постоянная ссылка блендещайся" ой. После главы про outlined шрифты, здесь уже все прозаично. Как обычно "создадим" шрифт:
    ;создадим шрифт (размером "9", остальные значения по умолчанию "0"
    ;, шрифт семейства "Lucida Console") invoke CreateFont,-9,ebx,ebx,ebx,ebx,\
    ;ebx,ebx,ebx,ebx,ebx,ebx,ebx,ebx,fontName выберем полученый объект шрифт) для текущего контекста окна (ebp) invoke SelectObject,ebp,eax Теперь, по анологии с outlined шрифтами, преобразуем все это в список команд рисования битмап'ов функцией "контекст OpenGL (первый символ (число символов (список (берем й" преобразуем символы от го догов список битмап'ов invoke wglUseFontBitmapsA,ebp,ebx,256,ebx Установим ортогональную проекцию (для битмап'ов работать в ней удобнее. Вот тут начинается самое интересное. Будем делать "Матрицу" ! Нуту самую, что "has Neo...". Надеюсь ему понравилось, номы за него ОТОМСТИМ ! Вощ-щ-щем расклад такой. Заведем массивна каждую "строку" "матрицы" с координатами X (dword), Y (dword) и ее начальным символом. Генерим каждой все вышеописанное. В основном цикле распихиваем "строки" по сгенереным координатам, каждый раз начиная с начального символа "строки" и "начального цвета" (черного, увеличивая их для каждой следующей буквы. Начальный символ увеличивается для каждой "charChangeFrequency" "строки. Каждый последний символ "строки" выделяем голубым цветом (мстим за Нео)
    6. Так как координата "Y" увеличивается на размер "строки" по вертикали, то вернем ее на место, пришьем, попутно, + 3 за побег (+ 5 за детсад, т.к. "строки" должны "бежать" вниз. Если какая-нибудь "строка" сЦучилась (читай, вылезла за края экрана) - обнулим ей "Y"
    (шоб неповадно было. Просто матрица это ж страшный "порожняк, поэтому напялим эту в качестве текстуры,
    для начала, хотяб на кубик (месть продолжается. Делается это как обычно,
    копированием экрана в текстуру функцией "Надеюсь вы что-нибудь поняли. Если нетто смотрите код, там понятней. Вообще-то это была задумка написать "город" а-ля в "Матрице, отсюда и кубик, но меня потом вконец обломало Пишите сами, в общем. На томи сказке/тьюториалу конец (делу венец и т.п.) а кто слушал !!! © Tyler Durden
    archive
    New Member Комментарии 1
    3.645

    Old School vb style Russian (Обратная связь Помощь
    Условия и правила software by XenForo™ ©2016 Перевод XF-Russia.ru
    Автор:
    archive
    Категория:
    DirectX/OpenGL
    Создано:
    26 мар Последние обновления мар 2005
    Комментарии:
    1
    Просмотров:
    3.645
    Последнее сообщение июл 2021
    Статус:
    Активный
    Публикаций:
    532
    illya334 23 июл Ау тебя есть файл http://tylerdurden.planet-d.net/download.php?file=files/tutorial.rar?
    Регистрация
    Регистрация
    Информация
    Другие публикации от archive Сортировать комментарии
    Главная
    Публикации
    DirectX/OpenGL
    FASM OpenGL tutorial


    написать администратору сайта