Урок Инициализация в Windows я начинаю это пособие непосредственного с кода, разбитого на секции, каждая из которых будет подробно комментироваться. Первое, что вы должны сделать это создать проект в Visual C++



страница5/27
Дата17.11.2018
Размер7.85 Mb.
ТипУрок
1   2   3   4   5   6   7   8   9   ...   27

GLYPHMETRICSFLOAT gmf[256] будет содержать информацию о местоположении и ориентации каждого из 256 списков отображения нашего векторного шрифта. Чтобы получить доступ к нужной букве просто напишемgmf[num], где num - это номер списка отображения, соответствующий требуемой букве. Позже в программе я покажу вам, как узнать ширину каждого символа для того, чтобы вы смогли автоматически центрировать текст на экране. Имейте в виду, что каждый символ имеет свою ширину. Метрика шрифта (glyphmetrics) на порядок облегчит вам жизнь.

 

GLYPHMETRICSFLOAT gmf[256];  // Массив с информацией о нашем шрифте



LRESULT CALLBACK WndProc(

HWND, UINT, WPARAM, LPARAM); // Объявление оконной процедуры

 

Следующая часть программы создает шрифт так же, как и при построении растрового шрифта. Как и в уроке №13, это место в программе было для меня самым трудным для объяснения.



 

Переменная HFONT font будет содержать идентификатор шрифта Windows.

 

Далее заполним переменную base, создав набор из 256-ти списков отображения, вызвав функцию glGenLists(256). После этого переменная base будет содержать номер первого списка отображения.



 

GLvoid BuildFont(GLvoid)           // Строим растровый шрифт

{

  HFONT  font;                     // Идентификатор шрифта Windows



  base = glGenLists(256);          // массив для 256 букв

 

Теперь будет интереснее :). Делаем наш векторный шрифт. Во-первых, определим его размер. В приведенной ниже строке кода вы можете заметить отрицательное значение. Этим минусом мы говорим Windows, что наш шрифт основан на высоте СИМВОЛА. А положительное значение дало бы нам шрифт, основанный на высоте ЗНАКОМЕСТА.



 

font = CreateFont(       -12,          // высота шрифта

 

Определим ширину знакоместа. Вы видите, что ее значение установлено в ноль. Этим мы заставляем Windows взять значение по умолчанию. Если хотите, поиграйтесь с этим значением, сделайте, например, широкие буквы.



 

              0,            // ширина знакоместа

 

Угол отношения (Angle of Escapement) позволяет вращать шрифт. Угол наклона (Orientation Angle), если сослаться на 'MSDN help', определяет угол, в десятых долях градуса, между базовой линией символа и осью Х экрана. Я, к сожалению, не имею идей насчет того, зачем это :(.



 

              0,            //Угол перехода

              0,            //Угол направления

 

Ширина шрифта - важный параметр. Может быть в пределах от 0 до 1000. Также можно использовать предопределенные значения: FW_DONTCARE = 0, FW_NORMAL = 400, FW_BOLD = 700 и FW_BLACK = 900. Таких значений много, но эти дают наилучший результат. Понятно, что чем выше значение, тем толще (жирнее) шрифт.



 

FW_BOLD,              //Ширина шрифта

 

Параметры Italic, Underline и Strikeout (наклонный, подчеркнутый и зачеркнутый) могут иметь значения TRUE илиFALSE. Хотите, к примеру, чтобы шрифт был подчеркнутым, в параметре подчеркнутости поставьте значение TRUE, не хотите - FALSE. Просто :).



 

              FALSE,        // Курсив

              FALSE,        // Подчеркивание

              FALSE,        // Перечеркивание

 

Идентификатор набора символов определяет, соответственно, набор символов (кодировку), который мы хотим использовать. Их, конечно, очень много: CHINESEBIG5_CHARSETGREEK_CHARSETRUSSIAN_CHARSET,DEFAULT_CHARSET и т.д. Я, к примеру, использую ANSI. Хотя, DEFAULT тоже может подойти. Если интересуетесь такими шрифтами, как Webdings или Wingdings, вам надо использовать значение SYMBOL_CHARSET вместоANSI_CHARSET.



 

              ANSI_CHARSET,       //Идентификатор кодировки

 

Точность вывода - тоже важный параметр. Он говорит Windows о том, какой тип символа использовать, если их более одного. Например, значение OUT_TT_PRECIS означает, что надо взять TRUETYPE - версию шрифта.Truetype - шрифт обычно смотрится лучше, чем другие, особенно когда буквы большие. Можно также использовать значениеOUT_TT_ONLY_PRECIS, которое означает, что всегда следует брать, если возможно, шрифт TRUETYPE.



 

              OUT_TT_PRECIS,       // Точность вывода

 

Точность отсечения - этот параметр указывает вид отсечения шрифта при попадании букв вне определенной области. Сказать о нем больше нечего, просто оставьте его по умолчанию.



 

              IP_DEFAULT_PRECIS,       //Точность отсечения

 

Качество вывода - очень важный параметр. Можете поставить PROOF, DRAFT, NONANTIALIASED, DEFAULT илиANTIALIASED. Мы с вами знаем, что ANTIALIASED будет лучше смотреться :). Сглаживание (Antialiasing) шрифта - это эффект, позволяющий сгладить шрифт в Windows. Он делает вид букв менее ступенчатым.



 

              ANTIALIASED_QUALITY,// Качество вывода

 

Следующими идут значения семейства (Family) и шага (Pitch). Шаг может принимать значения DEFAULT_PITCH, FIXED_PITCH и VARIABLE_PITCH. Семейство может быть FF_DECORATIVE, FF_MODERN, FF_ROMAN, FF_SCRIPT, FF_SWISS, FF_DONTCARE. Поиграйте этими значениями, чтобы понять, что они делают. Здесь оба параметра установлены по умолчанию.



 

              FF_DONTCARE|DEFAULT_PITCH, // Семейство и Шаг

 

И последнее... Нам нужно настоящее имя используемого нами шрифта. Его можно увидеть, например в Word при выборе шрифта для текста. Зайдите в Word или другой текстовый редактор, выберите шрифт, который требуется, запомните, как он называется, и вставьте его название вместо значения 'Comic Sans MS' в приведенной ниже строке.



 

              "Comic Sans MS");          // Имя шрифта

 

Теперь выберем этот шрифт, связав его с нашим контекстом устройста (DC).



 

SelectObject(hDC, font);       //Выбрать шрифт, созданный нами

 

Подошло время добавить новые строки в программу. Мы построим наш векторный шрифт, используя новую команду -wglUseFontOutlines. Выберем контекст устройства (DC), начальный символ, количество создаваемых символов, и базовое значение списка отображения. Все очень похоже на то, как мы строили растровый шрифт.



 

wglUseFontOutlines( hDC,         // Выбрать текущий контекст устройства (DC)

               0,            // Стартовый символ

               255,          // Количество создаваемых списков отображения

               base,         // Стартовое значение списка отображения

 

Но это еще не все. Здесь мы установим уровень отклонения. Уже при значении 0.0f сглаживание будет видимо. После установки отклонения идет определение толщины шрифта (ширины по оси Z). Толщина, равная 0.0f, понятно, даст нам плоские буквы, то есть двумерные. А вот при значении 1.0f уже будет виден некоторый объем.



 

Параметр WGL_FONT_POLYGONS говорит OpenGL создать "твердый" шрифт при помощи полигонов. Если вместо него вы укажете WGL_FONT_LINES, шрифт будет каркасным, или "проволочным" (составленным из линий). Стоит заметить, если вы укажете значение GL_FONT_LINES, не будут сгенерированы нормали, что сделает невозможным свечение букв.

 

Последний параметр, gmf указывает на буфер адреса для данных списка отображения.



 

                    0.0f,       //Отклонение от настоящего контура

                    0.2f,       //Толщина шрифта по оси Z

                    WGL_FONT_POLYGONS,       //Использовать полигоны, а не линии

                    gmf),       //буфер адреса для данных списка отображения

                    }

 

Следующий код очень простой. Он удаляет 256 списков отображения из памяти, начиная с первого списка, номер которого записан в base. Не уверен, что Windows сделает это за нас, поэтому лучше позаботиться самим, чем потом иметь глюки в системе.



 

GLvoid KillFont(GLvoid)                   // Удаление шрифта

              {

              glDeleteLists(base, 256); // Удаление всех 256 списков отображения

              }

 

Теперь функция вывода текста в OpenGL. Ее мы будем вызывать не иначе как glPrint("Выводимый текст"), точно также, как и в варианте с растровым шрифтом из урока N 13. Текст при этом помещается в символьную строку fmt.



 

GLvoid glPrint(const char *fmt, ...)     // Функция вывода текста в OpenGL

              {

 

В первой строке, приведенной ниже, объявляется и инициализируется переменная length. Она будет использована при вычислении того, какой из нашей строки выйдет текст. Во второй строке создается пустой массив для текстовой строки длиной в 256 символов. text - строка, из которой будет происходить вывод текста на экран. В третьей строке описывается указатель на список аргументов, передаваемый со строкой в функцию. Если мы пошлем с текстом какие-нибудь переменные, этот указатель будет указывать на них.



 

              float         length=0;     // Переменная для нахождения

                                          // физической длины текста

              char          text[256];    // Здесь наша строка

              va_list              ap;    // Указатель на переменный список аргументов

 

Проверим, а может нет никакого текста :). Тогда выводить нечего, и - return.



 

              if (fmt == NULL)            // Если нет текста,

                    return;               // ничего не делаем

 

В следующих трех строчках программа конвертирует любые символы в переданной строке в представляющие их числа. Проще говоря, мы можем использовать эту функцию, как С-функцию printf. Если в переданном постоянном аргументе мы послали программе строку форматирования, то в этих трех строках она будет читать переменный список аргументов-переменных и в соответствии со строкой форматирования преобразовать их в конечный понятный для программы текст, сохраняемый в переменной text. Подробности идут дальше.



 

              va_start(ap, fmt);         // Анализ строки на переменные

              vsprintf(text, fmt, ap);   // И конвертация символов в реальные коды

              va_end(ap);                // Результат сохраняется в text

 

Стоит сказать отдельное спасибо Джиму Вильямсу (Jim Williams) за предложенный ниже код. До этого я центрировал текст вручную, но его метод немного лучше :). Начнем с создания цикла, который проходит весь текст символ за символом. Длину текста вычисляем в выражении strlen(text). После обработки данных цикла (проверки условия завершения) идет его тело, где к значению переменной lenght добавляется физическая ширина каждого символа. После завершения цикла величина, находящаяся в lenght, будет равна ширине всей строки. Так, если мы напечатаем при помощи данной функции слово "hello", и по каким-то причинам каждый символ в этом слове будет иметь ширину ровно в 10 единиц, то, понятно, что в итоге у нас получится значениеlenght=10+10+10+10+10=50 единиц.



 

Значение ширины каждого символа получается из выражения gmf[text[loop]].gmfCellIncX. Помните, что gmfхранит информацию о каждом списке отображения. Если loop будет равна 0, то text[loop] - это будет первый символ нашей с вами строки. Соответственно, при loop, равной 1, то text[loop] будет означать второй символ этой же строки. Ширину символа дает нам gmfCellIncX. На самом деле gmfCellIncX - это расстояние, на которое смещается вправо позиция графического вывода после отображения очередного символа для того, чтобы символы не наложились друг на друга. Так уж вышло, что это расстояние и наша ширина символа - одно и то же значение.

 

Высоту символа можно узнать при помощи команды gmfCellIncY. Это может пригодиться при выводе вертикального текста.



 

       for (unsigned int loop=0;loop//Цикл поиска размера строки

                    {

                    length+=gmf[text[loop]].gmfCellIncX;

                    // Увеличение размера на ширину символа

                    }

 

Полученную величину размера строки преобразуем в отрицательную (потому что мы будем перемещаться влево от центра для центровки текста). Затем мы делим длину на 2: нам не нужно перемещать весь текст влево - только его половину.



 

glTranslatef(-length/2,0.0f,0.0f);       //Центровка на экране нашей строки

 

Дальше мы сохраним в стеке значение GL_LIST_BIT, это сохранит glListBase от воздействия любых других списков отображения, используемых в нашей программе.



 

Команда glListBase(base) говорит OpenGL, где искать для каждого символа соответствующий список отображения.

 

       glPushAttrib(GL_LIST_BIT); // Сохраняет в стеке значения битов списка отображения



       glListBase(base);          // Устанавливает базовый символ в 0

 

Теперь, когда OpenGL знает расположение всех символов, мы можем сказать ей написать текст на экране. glCallListsвыводит всю строку текста на экран сразу, создавая для вас многочисленные списки отображения.



 

Строка, приведенная ниже, делает следующее. Сначала она сообщает OpenGL, где на экране будут находиться списки отображения. strlen(text) находит количество букв, которые мы хотим послать на экран. Далее ему потребуется знать, какой наибольший будет номер списка из подготавливаемых к посылке. Пока что мы не посылаем более 255 символов. Так что мы можем использовать значение GL_UNSIGNED_BYTE (байт позволяет хранить целые числа от 0 до 255). Наконец, мы ему скажем, что отображать при помощи передачи строки text.

 

На тот случай, если вас удивит, что буквы не сваливаются в кучу одна над другой. Каждый список отображения каждого символа знает, где находится правая сторона предыдущего символа. После того, как буква отобразилась на экране, OpenGL перемещает вывод к правой стороне нарисованной буквы. Следующая буква или объект рисования начнет рисоваться с последней позиции OpenGL после перемещения, находящейся справа от последней буквы.



 

Наконец, мы восстанавливаем из стека GL_LIST_BIT - установки OpenGL обратно по состоянию на тот момент. Как они были перед установкой базовых значений командой glCallLists(base).

 

       // Создает списки отображения текста



       glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);

       glPopAttrib(); // Восстанавливает значение Display List Bits

                    }

 

Участок программы, отвечающий за размеры в окне OpenGL, точно такой же, как и в уроке N 1, поэтому здесь мы его пропустим.



 

В конец функции InitGL добавилось несколько новых строк. Строка с выражением BuildFont() из 13 урока осталась прежней, вместе с новым кодом, который создает быстрое и черновое освещение. Источник света Light0 встроен в большинство видеокарт, поэтому достаточно приемлемое освещение сцены не потребует особых усилий с нашей стороны.

 

Еще я добавил команду glEnable(GL_Color_Material). Поскольку символы являются 3D-объектами, вам понадобится раскраска материалов (Material Coloring). В противном случае смена цвета с помощью glColor3f(r,g,b) не изменит цвет текста. Если у вас на экран выводятся кроме текста другие фигуры-объекты 3D-сцены, включайте раскраску материалов перед выводом текста и отключайте сразу после того, как текст будет нарисован, иначе будут раскрашены все объекты на экране.



 

int InitGL(GLvoid)                             // Здесь будут все настройки для OpenGL

{

       glShadeModel(GL_SMOOTH);                // Включить плавное затенение



       glClearColor(0.0f, 0.0f, 0.0f, 0.5f);   // Черный фон

       glClearDepth(1.0f);                     // Настройка буфера глубины

       glEnable(GL_DEPTH_TEST);                // Разрешить проверку глубины

       glDepthFunc(GL_LEQUAL);                 // Тип проверки глубины

       // Действительно хорошие вычисления перспективы

       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

       glEnable(GL_LIGHT0);           // Включить встроенное освещение (черновое) (новая)

       glEnable(GL_LIGHTING);                  // Разрешить освещение                        (новая)

       glEnable(GL_COLOR_MATERIAL);            // Включить раскраску материалов (новая)

 

       BuildFont();                            // Построить шрифт (добавлена)



 

       return TRUE;                            // Инициализация прошла успешно

}

 

Теперь рисующий код. Начнем с очистки экрана и буфера глубины. Для полного сброса вызовем функциюglLoadIdentity(). Затем мы смещаемся на 10 единиц вглубь экрана. Векторный шрифт великолепно смотрится в режиме перспективы. Чем дальше в экран смещаемся, тем меньше шрифт. Чем ближе, тем шрифт больше.



 

Управлять векторными шрифтами можно также при помощи команды glScalef(x,y,z). Если захотите сделать буквы в два раза выше, дайте команду glScalef(1.0f,2.0f,1.0f). Значение 2.0f здесь относится к оси Y и сообщает OpenGL, что список отображения нужно нарисовать в двойной высоте. Если это значение поставить на место первого аргумента (Х), то буквы будут в два раза шире. Ну, третий аргумент, естественно, касается оси Z.

 

int DrawGLScene(GLvoid)                  // Здесь весь вывод на экран



{

       // Очистка экрана и буфера глубины

       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

       glLoadIdentity();                 // Сброс вида

       glTranslatef(0.0f,0.0f,-10.0f);   // Смещение на 10 единиц в экран

 

После сдвига вглубь экрана мы можем повращать текст. Следующие три строки поворачивают изображение по трем осям. Умножением переменной rot на различные значения я пытался добиться как можно более различающихся скоростей вращения.



 

       glRotatef(rot,1.0f,0.0f,0.0f);          // Поворот по оси X

       glRotatef(rot*1.5f,0.0f,1.0f,0.0f);     // Поворот по оси Y

       glRotatef(rot*1.4f,0.0f,0.0f,1.0f);     // Поворот по оси Z

 

Теперь займемся цветовым циклом. Как обычно, использую здесь переменную-счетчик (rot). Возгорание и затухание цветов получается при помощи функций SIN и COS. Я делил переменную rot на разные числа, так что бы каждый цвет не возрастал с такой же скоростью. Результат впечатляющий.



 

       // Цветовая пульсация основанная на вращении

       glColor3f(1.0f*float(cos(rot/20.0f)),1.0f*float(sin(rot/25.0f)),

              1.0f-0.5f*float(cos(rot/17.0f)));

 

Моя любимая часть... Запись текста на экран. Мною были использованы несколько команд, которые мы применяли также при выводе на экран растровых шрифтов. Сейчас вы уже знаете, как вывести текст в команде glPrint("Ваш текст"). Это так просто!



 

В коде, приведенном ниже, мы печатаем "NeHe", пробел, тире, пробел и число из переменной rot и разделенное на 50, чтобы немного его уменьшить. Если число больше 999.99, разряды слева игнорируются (так как в команде мы указали 3 разряда на целую часть числа и 2 - на дробную после запятой).

 

       glPrint("NeHe - %3.2f",rot/50);   // Печать текста на экране



 

Затем увеличиваем переменную rot для дальнейшей пульсации цвета и вращения текста.

 

       rot+=0.5f;                        // Увеличить переменную вращения



       return TRUE;                      // Все прошло успешно

              }

 

И последняя вещь, которую мы должны сделать, это добавить строку KillFont() в конец функции KillGLWindow(), так как я это сделал ниже. Очень важно это сделать. Она очистит все, что касалось шрифта, прежде чем мы выйдем из нашей программы.



 

if (!UnregisterClass("OpenGL",hInstance))// Если класс незарегистрирован

       {

       MessageBox(NULL,"Could Not Unregister Class.",

              "SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

       hInstance=NULL;                   // Установить копию приложения в ноль

       }

KillFont();                              // Уничтожить шрифт

 

Под конец урока вы уже должны уметь использовать векторные шрифты в ваших проектах, использующих OpenGL. Как и в случае с уроком N 13, я пытался найти в сети подобные руководства, но, к сожалению, ничего не нашел. Возможно мой сайт - первый в раскрытии данной темы в подробном рассмотрении для всех, понимающих язык Си? Читайте руководство и удачного вам программирования!



Урок 15. Текстурные шрифты

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

Небольшое примечание, этот код применим только в Windows. Здесь используются функции wgl Windows для построения шрифта. Очевидно, Apple имеет поддержку agl, которая должна делать тоже самое, и X имеет glx. К сожалению, я не могу гарантировать, что этот код переносим. Если кто-нибудь имеет платформо-незавизимый код для вывода шрифтов на экран, пришлите мне его, и я напишу другой урок по шрифтам.

Мы будем использовать код от урока 14 для нашей демонстрационной программы текстурных шрифтов. Если код изменился в каком-либо разделе программы, я перепишу весь раздел кода, чтобы было проще видеть изменения, которые я сделал.

Следующий раздел кода такой же как в уроке 14, но на этот раз мы не включим в него stdarg.h.

 

#include   // Заголовочный файл для Windows



#include     // Заголовочный файл для стандартной библиотеки ввода/вывода

#include     // Заголовочный файл для библиотеки OpenGL32

#include    // Заголовочный файл для библиотеки GLu32

#include // Заголовочный файл для библиотеки GLaux

#include      // Заголовочный файл для математической библиотеки

 

HDC        hDC=NULL;  // Приватный контекст устройства GDI



HGLRC      hRC=NULL;  // Постоянный контекст рендеринга

HWND       hWnd=NULL; // Сохраняет дескриптор окна

HINSTANCE  hInstance; // Сохраняет экземпляр приложения

 

bool  keys[256];      // Массив для работы с клавиатурой



bool  active=TRUE;    // Флаг активации окна, по умолчанию = TRUE

bool  fullscreen=TRUE;// Флаг полноэкранного режима

 

Мы собираемся добавить одну новую переменную целого типа, которая называется texture[]. Она будет использоваться для хранения нашей текстуры. Последние три строки такие же, как в уроке 14 и не изменились и здесь.



 

GLuint  texture[1]; // Одна текстура ( НОВОЕ )

GLuint  base;       // База списка отображения для фонта

 

GLfloat   rot;      // Используется для вращения текста



 

LRESULT  CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Объявление WndProc

 

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



Может быть кто-то уже задавался вопросом, как использовать wingdings шрифт. Это тоже является причиной, по которой я не использую стандартный шрифт. wingdings – СПЕЦИАЛЬНЫЙ шрифт, и требует некоторых модификаций, чтобы заставить программу работать с ним. При этом надо не просто сообщить Windows, чтобы Вы будете использовать wingdings шрифт. Если Вы изменяете, название шрифта на wingdings, Вы увидите, что шрифт не будет выбран. Вы должны сообщить Windows, что шрифт является специальным шрифтом, и не стандартным символьным шрифтом. Но об этом позже.

 

GLvoid BuildFont(GLvoid)       // Построение шрифта



{

  GLYPHMETRICSFLOAT  gmf[256]; // Адрес буфера для хранения шрифта

  HFONT  font;                 // ID шрифта в Windows

 

  base = glGenLists(256);      // Храним 256 символов



  font = CreateFont(  -12,     // Высота фонта

        0,        // Ширина фонта

        0,        // Угол отношения

        0,        // Угол наклона

        FW_BOLD,  // Ширина шрифта

        FALSE,    // Курсив

        FALSE,    // Подчеркивание

        FALSE,    // Перечеркивание

 

Вот она волшебная строка! Вместо того чтобы использовать ANSI_CHARSET, как мы делали в уроке 14, мы используем SYMBOL_CHARSET. Это говорит Windows, что шрифт, который мы строим - не обычный шрифт, составленный из букв. Специальный шрифт обычно составлен из крошечных картинок (символов). Если Вы забудете изменить эту строку, wingdings, webdings и любой другой специальный шрифт, который Вы можете пробовать использовать, не будет работать.



 

        SYMBOL_CHARSET,      // Идентификатор набора символов ( Модифицировано )

 

Следующие строки не изменились.



 

        OUT_TT_PRECIS,       // Точность вывода

        CLIP_DEFAULT_PRECIS, // Точность отсечения

        ANTIALIASED_QUALITY, // Качество вывода

        FF_DONTCARE|DEFAULT_PITCH, // Семейство и шаг

 

Теперь, когда мы выбрали идентификатор набора символов, мы можем выбирать wingdings шрифт!



 

        "Wingdings");       // Имя шрифта ( Модифицировано )

 

  SelectObject(hDC, font);  // Выбрать шрифт, созданный нами



 

  wglUseFontOutlines(  hDC, // Выбрать текущий контекст устройства (DC)

        0,                  // Стартовый символ

        255,                // Количество создаваемых списков отображения

        base,               // Стартовое значение списка отображения

 

Я устанавливаю большой уровень отклонения. При этом GL не будет точно отслеживать контур шрифта. Если Вы зададите отклонение равным 0.0f, Вы заметите проблемы с текстурированием на очень изогнутых поверхностях. Если Вы допустите некоторое отклонение, большинство проблем исчезнет.



 

        0.1f,        // Отклонение от истинного контура

 

Следующие три строки кода те же самые.



 

        0.2f,        // Толщина шрифта по оси Z

        WGL_FONT_POLYGONS, // Использовать полигоны, а не линии

        gmf);        // Буфер адреса для данных списка отображения

}

 

Перед ReSizeGLScene() мы собираемся добавить следующий раздел кода для загрузки нашей текстуры. Вы знаете этот код по прошлым урокам. Мы создаем память для хранения растрового изображения. Мы загружаем растровое изображение. Мы говорим OpenGL, сгенерировать 1 текстуру, и мы сохраняем эту текстуру в texture[0].



Я создаю мип-мап текстуру, так как она смотрится лучше. Имя текстуры - lights.bmp.

 

AUX_RGBImageRec *LoadBMP(char *Filename)     // Загрузка картинки



{

 FILE *File=NULL;          // Индекс файла

 

 if (!Filename)            // Проверка имени файла



 {

  return NULL;             // Если нет вернем NULL

 }

 

 File=fopen(Filename,"r"); // Проверим существует ли файл



 

 if (File)                 // Файл существует?

 {

  fclose(File);            // Закрыть файл



  return auxDIBImageLoad(Filename); // Загрузка картинки и вернем на нее указатель

 }

 return NULL;              // Если загрузка не удалась вернем NULL



}

 

int LoadGLTextures()                      // Загрузка картинки и конвертирование в текстуру



{

 int Status=FALSE;                        // Индикатор состояния

 

 AUX_RGBImageRec *TextureImage[1];        // Создать место для текстуры



 

 memset(TextureImage,0,sizeof(void *)*1); // Установить указатель в NULL

 

 // Загрузка картинки, проверка на ошибки, если картинка не найдена - выход



 if (TextureImage[0]=LoadBMP("Data/Lights.bmp"))

 {

  Status=TRUE;       // Установим Status в TRUE



  glGenTextures(1, &texture[0]);     // Создание трех текстур

  // Создание текстуры с мип-мап наложением

  glBindTexture(GL_TEXTURE_2D, texture[0]);

  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY,

   GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);

  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);

 }

 



В следующих четырех строках кода автоматически генерируются текстурные координаты для любого объекта, который мы выводим на экран. Команда glTexGen чрезвычайно мощная и комплексная, и включает достаточно сложную математику. Но Вы должны только знать то, что GL_S и GL_T - координаты текстуры. По умолчанию они заданы так, чтобы брать текущее x положение на экране и текущее y положение на экране и из них вычислить вершину текстуру. Вы можете отметить, что объекты не текстурированны по z плоскости... только появляются полосы. Передние и задние грани текстурированны, однако, именно это и необходимо. X (GL_S) охватывает наложение текстуры слева направо, а Y (GL_T) охватывает наложение текстуры сверху и вниз.


Каталог: forum
forum -> Лечение гепатозов
forum -> Система ведения овцеводства в крестьянско-фермерских и личных хозяйствах населения
forum -> Yaesuft-857 (ft-897) – переходник для подключения cat интерфейса к микрофонному разъему трансивера
forum -> Васильев Владимир Юрьевич
forum -> tl-wr1043ND Беспроводной гигабитный маршрутизатор серии n copyright & trademarks
forum -> Цели и задачи Контакта rtf docx
forum -> Назовите не менее трех результатов революции 1905- 1907гг. Приведите не менее трех положений, отражающих значение революции для отечественной истории начала 20 века


Поделитесь с Вашими друзьями:
1   2   3   4   5   6   7   8   9   ...   27


База данных защищена авторским правом ©vossta.ru 2019
обратиться к администрации

    Главная страница